[offers][chore] Save the generate offer profile analysis into db

pull/380/head
BryannYeap 3 years ago
parent 490d11e249
commit c12c318a0b

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "OffersAnalysis" ALTER COLUMN "overallPercentile" SET DATA TYPE DOUBLE PRECISION,
ALTER COLUMN "companyPercentile" SET DATA TYPE DOUBLE PRECISION;

@ -365,12 +365,12 @@ model OffersAnalysis {
offerId String @unique offerId String @unique
// OVERALL // OVERALL
overallPercentile Int overallPercentile Float
noOfSimilarOffers Int noOfSimilarOffers Int
topOverallOffers OffersOffer[] @relation("TopOverallOffers") topOverallOffers OffersOffer[] @relation("TopOverallOffers")
// Company // Company
companyPercentile Int companyPercentile Float
noOfSimilarCompanyOffers Int noOfSimilarCompanyOffers Int
topCompanyOffers OffersOffer[] @relation("TopCompanyOffers") topCompanyOffers OffersOffer[] @relation("TopCompanyOffers")
} }

@ -102,7 +102,7 @@ function Test() {
], ],
experiences: [ experiences: [
{ {
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
durationInMonths: 24, durationInMonths: 24,
jobType: 'FULLTIME', jobType: 'FULLTIME',
level: 'Junior', level: 'Junior',
@ -151,7 +151,7 @@ function Test() {
}, },
}, },
// Comments: '', // Comments: '',
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
monthYearReceived: new Date('2022-09-30T07:58:54.000Z'), monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
@ -180,7 +180,7 @@ function Test() {
}, },
}, },
comments: undefined, comments: undefined,
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
monthYearReceived: new Date('2022-09-30T07:58:54.000Z'), monthYearReceived: new Date('2022-09-30T07:58:54.000Z'),
@ -261,7 +261,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
durationInMonths: 24, durationInMonths: 24,
id: 'cl96stky6002iw32gpt6t87s2', id: 'cl96stky6002iw32gpt6t87s2',
jobType: 'FULLTIME', jobType: 'FULLTIME',
@ -368,7 +368,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
id: 'cl976t4de00047iygl0zbce11', id: 'cl976t4de00047iygl0zbce11',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
@ -421,7 +421,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
id: 'cl96stky80031w32gau9mu1gs', id: 'cl96stky80031w32gau9mu1gs',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
@ -474,7 +474,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
id: 'cl96stky9003bw32gc3l955vr', id: 'cl96stky9003bw32gc3l955vr',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
@ -527,7 +527,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
id: 'cl976wf28000t7iyga4noyz7s', id: 'cl976wf28000t7iyga4noyz7s',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',
@ -580,7 +580,7 @@ function Test() {
slug: 'meta', slug: 'meta',
updatedAt: new Date('2022-10-12T16:19:05.196Z'), updatedAt: new Date('2022-10-12T16:19:05.196Z'),
}, },
companyId: 'cl95u79f000007im531ysjg79', companyId: 'cl98yuqk80007txhgjtjp8fk4',
id: 'cl96tbb3o0051w32gjrpaiiit', id: 'cl96tbb3o0051w32gjrpaiiit',
jobType: 'FULLTIME', jobType: 'FULLTIME',
location: 'Singapore, Singapore', location: 'Singapore, Singapore',

@ -5,7 +5,7 @@ import { trpc } from '~/utils/trpc';
function profileAnalysis() { function profileAnalysis() {
const analysis = trpc.useQuery([ const analysis = trpc.useQuery([
'offers.analysis.generate', 'offers.analysis.generate',
{ profileId: 'cl96stky5002ew32gx2kale2x' }, { profileId: 'cl98yxuei002htx1s8lrmwzmy' },
]); ]);
return <div>{JSON.stringify(analysis.data)}</div>; return <div>{JSON.stringify(analysis.data)}</div>;

@ -8,6 +8,7 @@ import type {
OffersOffer, OffersOffer,
OffersProfile, OffersProfile,
} from '@prisma/client'; } from '@prisma/client';
import { JobType } from '@prisma/client';
import { TRPCError } from '@trpc/server'; import { TRPCError } from '@trpc/server';
import { createRouter } from '../context'; import { createRouter } from '../context';
@ -31,14 +32,32 @@ const binarySearchOfferPercentile = (
let start = 0; let start = 0;
let end = similarOffers.length - 1; let end = similarOffers.length - 1;
const salary =
offer.jobType === JobType.FULLTIME
? offer.OffersFullTime?.totalCompensation.value
: offer.OffersIntern?.monthlySalary.value;
if (!salary) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Cannot analyse without salary',
});
}
while (start <= end) { while (start <= end) {
const mid = Math.floor((start + end) / 2); const mid = Math.floor((start + end) / 2);
if (similarOffers[mid].id === offer.id) { const similarOffer = similarOffers[mid];
const similarSalary =
similarOffer.jobType === JobType.FULLTIME
? similarOffer.OffersFullTime?.totalCompensation.value
: similarOffer.OffersIntern?.monthlySalary.value;
if (similarSalary === salary) {
return mid; return mid;
} }
if (offer.id < similarOffers[mid].id) { if (salary < similarSalary) {
end = mid - 1; end = mid - 1;
} else { } else {
start = mid + 1; start = mid + 1;
@ -199,30 +218,29 @@ export const offersAnalysisRouter = createRouter().query('generate', {
}); });
let similarCompanyOffers = similarOffers.filter( let similarCompanyOffers = similarOffers.filter(
(offer) => offer.companyId === overallHighestOffer.companyId, (offer: { companyId: string }) =>
offer.companyId === overallHighestOffer.companyId,
); );
// CALCULATE PERCENTILES // CALCULATE PERCENTILES
const highestOfferAgainstOverallIndex = binarySearchOfferPercentile( const overallIndex = binarySearchOfferPercentile(
overallHighestOffer, overallHighestOffer,
similarOffers, similarOffers,
); );
const highestOfferAgainstOverallPercentile = const overallPercentile = overallIndex / similarOffers.length;
highestOfferAgainstOverallIndex / similarOffers.length;
const highestOfferAgainstCompanyIndex = binarySearchOfferPercentile( const companyIndex = binarySearchOfferPercentile(
overallHighestOffer, overallHighestOffer,
similarCompanyOffers, similarCompanyOffers,
); );
const highestOfferAgainstCompanyPercentile = const companyPercentile = companyIndex / similarCompanyOffers.length;
highestOfferAgainstCompanyIndex / similarCompanyOffers.length;
// FIND TOP >=90 PERCENTILE OFFERS // FIND TOP >=90 PERCENTILE OFFERS
similarOffers = similarOffers.filter( similarOffers = similarOffers.filter(
(offer) => offer.id !== overallHighestOffer.id, (offer: { id: string }) => offer.id !== overallHighestOffer.id,
); );
similarCompanyOffers = similarCompanyOffers.filter( similarCompanyOffers = similarCompanyOffers.filter(
(offer) => offer.id !== overallHighestOffer.id, (offer: { id: string }) => offer.id !== overallHighestOffer.id,
); );
const noOfSimilarOffers = similarOffers.length; const noOfSimilarOffers = similarOffers.length;
@ -247,18 +265,113 @@ export const offersAnalysisRouter = createRouter().query('generate', {
) )
: similarCompanyOffers; : similarCompanyOffers;
return { const analysis = await ctx.prisma.offersAnalysis.create({
company: { data: {
highestOfferAgainstCompanyPercentile, companyPercentile,
noOfSimilarCompanyOffers, noOfSimilarCompanyOffers,
topPercentileCompanyOffers,
},
overall: {
highestOfferAgainstOverallPercentile,
noOfSimilarOffers, noOfSimilarOffers,
topPercentileOffers, overallHighestOffer: {
connect: {
id: overallHighestOffer.id,
}, },
overallHighestOffer, },
}; overallPercentile,
profile: {
connect: {
id: input.profileId,
},
},
topCompanyOffers: {
connect: topPercentileCompanyOffers.map((offer) => {
return { id: offer.id };
}),
},
topOverallOffers: {
connect: topPercentileOffers.map((offer) => {
return { id: offer.id };
}),
},
},
include: {
overallHighestOffer: {
include: {
OffersFullTime: {
include: {
totalCompensation: true,
},
},
OffersIntern: {
include: {
monthlySalary: true,
},
},
company: true,
profile: {
include: {
background: true,
},
},
},
},
topCompanyOffers: {
include: {
OffersFullTime: {
include: {
totalCompensation: true,
},
},
OffersIntern: {
include: {
monthlySalary: true,
},
},
company: true,
profile: {
include: {
background: {
include: {
experiences: {
include: {
company: true,
},
},
},
},
},
},
},
},
topOverallOffers: {
include: {
OffersFullTime: {
include: {
totalCompensation: true,
},
},
OffersIntern: {
include: {
monthlySalary: true,
},
},
company: true,
profile: {
include: {
background: {
include: {
experiences: {
include: {
company: true,
},
},
},
},
},
},
},
},
},
});
return analysis;
}, },
}); });

Loading…
Cancel
Save