|
|
@ -57,88 +57,18 @@ const searchOfferPercentile = (
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const generateAnalysis = async (params: {
|
|
|
|
const getSimilarOffers = async (
|
|
|
|
ctx: {
|
|
|
|
|
|
|
|
prisma: PrismaClient<
|
|
|
|
prisma: PrismaClient<
|
|
|
|
Prisma.PrismaClientOptions,
|
|
|
|
Prisma.PrismaClientOptions,
|
|
|
|
never,
|
|
|
|
never,
|
|
|
|
Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
|
|
|
|
Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
|
|
|
|
>;
|
|
|
|
>,
|
|
|
|
session: Session | null;
|
|
|
|
comparedOffer: Offer,
|
|
|
|
};
|
|
|
|
companyIdFilter: string | undefined,
|
|
|
|
input: { profileId: string };
|
|
|
|
) => {
|
|
|
|
}) => {
|
|
|
|
|
|
|
|
const { ctx, input } = params;
|
|
|
|
|
|
|
|
await ctx.prisma.offersAnalysis.deleteMany({
|
|
|
|
|
|
|
|
where: {
|
|
|
|
|
|
|
|
profileId: input.profileId,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const offers = await ctx.prisma.offersOffer.findMany({
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
company: true,
|
|
|
|
|
|
|
|
location: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
state: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
country: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
offersFullTime: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
baseSalary: true,
|
|
|
|
|
|
|
|
bonus: true,
|
|
|
|
|
|
|
|
stocks: true,
|
|
|
|
|
|
|
|
totalCompensation: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
offersIntern: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
monthlySalary: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
profile: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
background: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
orderBy: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
offersFullTime: {
|
|
|
|
|
|
|
|
totalCompensation: {
|
|
|
|
|
|
|
|
baseValue: 'desc',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
offersIntern: {
|
|
|
|
|
|
|
|
monthlySalary: {
|
|
|
|
|
|
|
|
baseValue: 'desc',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
where: {
|
|
|
|
|
|
|
|
profileId: input.profileId,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!offers || offers.length === 0) {
|
|
|
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
|
|
|
code: 'NOT_FOUND',
|
|
|
|
|
|
|
|
message: 'No offers found on this profile',
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const overallHighestOffer = offers[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
!overallHighestOffer.profile.background ||
|
|
|
|
!comparedOffer.profile.background ||
|
|
|
|
overallHighestOffer.profile.background.totalYoe == null
|
|
|
|
comparedOffer.profile.background.totalYoe == null
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
throw new TRPCError({
|
|
|
|
throw new TRPCError({
|
|
|
|
code: 'NOT_FOUND',
|
|
|
|
code: 'NOT_FOUND',
|
|
|
@ -146,11 +76,11 @@ export const generateAnalysis = async (params: {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const yoe = overallHighestOffer.profile.background.totalYoe as number;
|
|
|
|
const yoe = comparedOffer.profile.background.totalYoe as number;
|
|
|
|
const monthYearReceived = new Date(overallHighestOffer.monthYearReceived);
|
|
|
|
const monthYearReceived = new Date(comparedOffer.monthYearReceived);
|
|
|
|
monthYearReceived.setFullYear(monthYearReceived.getFullYear() - 1);
|
|
|
|
monthYearReceived.setFullYear(monthYearReceived.getFullYear() - 1);
|
|
|
|
|
|
|
|
|
|
|
|
let similarOffers = await ctx.prisma.offersOffer.findMany({
|
|
|
|
return await prisma.offersOffer.findMany({
|
|
|
|
include: {
|
|
|
|
include: {
|
|
|
|
company: true,
|
|
|
|
company: true,
|
|
|
|
location: {
|
|
|
|
location: {
|
|
|
@ -214,7 +144,10 @@ export const generateAnalysis = async (params: {
|
|
|
|
where: {
|
|
|
|
where: {
|
|
|
|
AND: [
|
|
|
|
AND: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
location: overallHighestOffer.location,
|
|
|
|
location: comparedOffer.location,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
companyId: companyIdFilter,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
monthYearReceived: {
|
|
|
|
monthYearReceived: {
|
|
|
@ -225,10 +158,10 @@ export const generateAnalysis = async (params: {
|
|
|
|
OR: [
|
|
|
|
OR: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
offersFullTime: {
|
|
|
|
offersFullTime: {
|
|
|
|
title: overallHighestOffer.offersFullTime?.title,
|
|
|
|
title: comparedOffer.offersFullTime?.title,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
offersIntern: {
|
|
|
|
offersIntern: {
|
|
|
|
title: overallHighestOffer.offersIntern?.title,
|
|
|
|
title: comparedOffer.offersIntern?.title,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
],
|
|
|
@ -250,6 +183,92 @@ export const generateAnalysis = async (params: {
|
|
|
|
],
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const generateAnalysis = async (params: {
|
|
|
|
|
|
|
|
ctx: {
|
|
|
|
|
|
|
|
prisma: PrismaClient<
|
|
|
|
|
|
|
|
Prisma.PrismaClientOptions,
|
|
|
|
|
|
|
|
never,
|
|
|
|
|
|
|
|
Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
|
|
|
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
session: Session | null;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
input: { profileId: string };
|
|
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
|
|
const { ctx, input } = params;
|
|
|
|
|
|
|
|
await ctx.prisma.offersAnalysis.deleteMany({
|
|
|
|
|
|
|
|
where: {
|
|
|
|
|
|
|
|
profileId: input.profileId,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const offers = await ctx.prisma.offersOffer.findMany({
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
company: true,
|
|
|
|
|
|
|
|
location: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
state: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
country: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
offersFullTime: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
baseSalary: true,
|
|
|
|
|
|
|
|
bonus: true,
|
|
|
|
|
|
|
|
stocks: true,
|
|
|
|
|
|
|
|
totalCompensation: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
offersIntern: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
monthlySalary: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
profile: {
|
|
|
|
|
|
|
|
include: {
|
|
|
|
|
|
|
|
background: true,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
orderBy: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
offersFullTime: {
|
|
|
|
|
|
|
|
totalCompensation: {
|
|
|
|
|
|
|
|
baseValue: 'desc',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
offersIntern: {
|
|
|
|
|
|
|
|
monthlySalary: {
|
|
|
|
|
|
|
|
baseValue: 'desc',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
where: {
|
|
|
|
|
|
|
|
profileId: input.profileId,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!offers || offers.length === 0) {
|
|
|
|
|
|
|
|
throw new TRPCError({
|
|
|
|
|
|
|
|
code: 'NOT_FOUND',
|
|
|
|
|
|
|
|
message: 'No offers found on this profile',
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const overallHighestOffer = offers[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let similarOffers = await getSimilarOffers(
|
|
|
|
|
|
|
|
ctx.prisma,
|
|
|
|
|
|
|
|
overallHighestOffer,
|
|
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const offerIds = offers.map((offer) => offer.id);
|
|
|
|
const offerIds = offers.map((offer) => offer.id);
|
|
|
|
|
|
|
|
|
|
|
@ -261,11 +280,13 @@ export const generateAnalysis = async (params: {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const companyAnalysis = Array.from(companyMap.values()).map(
|
|
|
|
const companyAnalysis = await Promise.all(
|
|
|
|
(companyOffer) => {
|
|
|
|
Array.from(companyMap.values()).map(async (companyOffer) => {
|
|
|
|
// TODO: Refactor calculating analysis into a function
|
|
|
|
// TODO: Refactor calculating analysis into a function
|
|
|
|
let similarCompanyOffers = similarOffers.filter(
|
|
|
|
let similarCompanyOffers = await getSimilarOffers(
|
|
|
|
(offer) => offer.companyId === companyOffer.companyId,
|
|
|
|
ctx.prisma,
|
|
|
|
|
|
|
|
companyOffer,
|
|
|
|
|
|
|
|
companyOffer.companyId,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const companyIndex = searchOfferPercentile(
|
|
|
|
const companyIndex = searchOfferPercentile(
|
|
|
@ -300,7 +321,7 @@ export const generateAnalysis = async (params: {
|
|
|
|
percentile: companyPercentile,
|
|
|
|
percentile: companyPercentile,
|
|
|
|
topSimilarOffers: topPercentileCompanyOffers,
|
|
|
|
topSimilarOffers: topPercentileCompanyOffers,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// OVERALL ANALYSIS
|
|
|
|
// OVERALL ANALYSIS
|
|
|
|