[offers][fix] Fix analysis and offers API to accommodate new fields in OffersCurrency

pull/413/head
Bryann Yeap Kok Keong 2 years ago
parent bb97c4dea6
commit be594c7513

@ -56,7 +56,7 @@ const analysisOfferDtoMapper = (
location: offer.location,
monthYearReceived: offer.monthYearReceived,
negotiationStrategy: offer.negotiationStrategy,
previousCompanies: [],
previousCompanies: [], // TODO: Fill this up
profileName,
specialization:
offer.jobType === JobType.FULLTIME
@ -74,10 +74,18 @@ const analysisOfferDtoMapper = (
offer.offersFullTime.totalCompensation.value;
analysisOfferDto.income.currency =
offer.offersFullTime.totalCompensation.currency;
analysisOfferDto.income.baseValue =
offer.offersFullTime.totalCompensation.baseValue;
analysisOfferDto.income.baseCurrency =
offer.offersFullTime.totalCompensation.baseCurrency;
} else if (offer.offersIntern?.monthlySalary) {
analysisOfferDto.income.value = offer.offersIntern.monthlySalary.value;
analysisOfferDto.income.currency =
offer.offersIntern.monthlySalary.currency;
analysisOfferDto.income.baseValue =
offer.offersIntern.monthlySalary.baseValue;
analysisOfferDto.income.baseCurrency =
offer.offersIntern.monthlySalary.baseCurrency;
} else {
throw new TRPCError({
code: 'NOT_FOUND',

@ -8,7 +8,7 @@ function GenerateAnalysis() {
return (
<div>
{JSON.stringify(
analysisMutation.mutate({ profileId: 'cl9h23fb1002ftxysli5iziu2' }),
analysisMutation.mutate({ profileId: 'cl9j50xzk008vutfqg6mta2ey' }),
)}
</div>
);

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

@ -6,6 +6,7 @@ function Test() {
const data = trpc.useQuery([
'offers.list',
{
currency: 'SGD',
limit: 100,
location: 'Singapore, Singapore',
offset: 0,

@ -187,14 +187,14 @@ export const offersAnalysisRouter = createRouter()
{
offersFullTime: {
totalCompensation: {
value: 'desc',
baseValue: 'desc',
},
},
},
{
offersIntern: {
monthlySalary: {
value: 'desc',
baseValue: 'desc',
},
},
},
@ -216,11 +216,11 @@ export const offersAnalysisRouter = createRouter()
// TODO: Shift yoe out of background to make it mandatory
if (
!overallHighestOffer.profile.background ||
overallHighestOffer.profile.background.totalYoe === undefined
overallHighestOffer.profile.background.totalYoe == null
) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Cannot analyse without YOE',
code: 'NOT_FOUND',
message: 'YOE not found',
});
}
@ -257,14 +257,14 @@ export const offersAnalysisRouter = createRouter()
{
offersFullTime: {
totalCompensation: {
value: 'desc',
baseValue: 'desc',
},
},
},
{
offersIntern: {
monthlySalary: {
value: 'desc',
baseValue: 'desc',
},
},
},
@ -279,12 +279,10 @@ export const offersAnalysisRouter = createRouter()
{
offersFullTime: {
level: overallHighestOffer.offersFullTime?.level,
specialization:
overallHighestOffer.offersFullTime?.specialization,
title: overallHighestOffer.offersFullTime?.title,
},
offersIntern: {
specialization:
overallHighestOffer.offersIntern?.specialization,
title: overallHighestOffer.offersIntern?.title,
},
},
],
@ -317,7 +315,7 @@ export const offersAnalysisRouter = createRouter()
similarOffers,
);
const overallPercentile =
similarOffers.length === 0 ? 0 : overallIndex / similarOffers.length;
similarOffers.length === 0 ? 1.0 : overallIndex / similarOffers.length;
const companyIndex = searchOfferPercentile(
overallHighestOffer,
@ -325,10 +323,11 @@ export const offersAnalysisRouter = createRouter()
);
const companyPercentile =
similarCompanyOffers.length === 0
? 0
? 1.0
: companyIndex / similarCompanyOffers.length;
// FIND TOP >=90 PERCENTILE OFFERS
// FIND TOP >=90 PERCENTILE OFFERS, DOESN'T GIVE 100th PERCENTILE
// e.g. If there only 4 offers, it gives the 2nd and 3rd offer
similarOffers = similarOffers.filter(
(offer) => offer.id !== overallHighestOffer.id,
);
@ -337,10 +336,9 @@ export const offersAnalysisRouter = createRouter()
);
const noOfSimilarOffers = similarOffers.length;
const similarOffers90PercentileIndex =
Math.floor(noOfSimilarOffers * 0.9) - 1;
const similarOffers90PercentileIndex = Math.ceil(noOfSimilarOffers * 0.1);
const topPercentileOffers =
noOfSimilarOffers > 1
noOfSimilarOffers > 2
? similarOffers.slice(
similarOffers90PercentileIndex,
similarOffers90PercentileIndex + 2,
@ -348,10 +346,11 @@ export const offersAnalysisRouter = createRouter()
: similarOffers;
const noOfSimilarCompanyOffers = similarCompanyOffers.length;
const similarCompanyOffers90PercentileIndex =
Math.floor(noOfSimilarCompanyOffers * 0.9) - 1;
const similarCompanyOffers90PercentileIndex = Math.ceil(
noOfSimilarCompanyOffers * 0.1,
);
const topPercentileCompanyOffers =
noOfSimilarCompanyOffers > 1
noOfSimilarCompanyOffers > 2
? similarCompanyOffers.slice(
similarCompanyOffers90PercentileIndex,
similarCompanyOffers90PercentileIndex + 2,

@ -5,7 +5,7 @@ import {
dashboardOfferDtoMapper,
getOffersResponseMapper,
} from '~/mappers/offers-mappers';
import { convert } from '~/utils/offers/currency/currency-exchange';
import { convertWithDate } from '~/utils/offers/currency/currency-exchange';
import { Currency } from '~/utils/offers/currency/CurrencyEnum';
import { createValidationRegex } from '~/utils/offers/zodRegex';
@ -106,7 +106,7 @@ export const offersRouter = createRouter().query('list', {
? {
offersIntern: {
monthlySalary: {
value: order,
baseValue: order,
},
},
}
@ -141,7 +141,7 @@ export const offersRouter = createRouter().query('list', {
{
offersIntern: {
monthlySalary: {
value: {
baseValue: {
gte: input.salaryMin ?? undefined,
lte: input.salaryMax ?? undefined,
},
@ -210,7 +210,7 @@ export const offersRouter = createRouter().query('list', {
? {
offersFullTime: {
totalCompensation: {
value: order,
baseValue: order,
},
},
}
@ -250,7 +250,7 @@ export const offersRouter = createRouter().query('list', {
{
offersFullTime: {
totalCompensation: {
value: {
baseValue: {
gte: input.salaryMin ?? undefined,
lte: input.salaryMax ?? undefined,
},
@ -288,36 +288,42 @@ export const offersRouter = createRouter().query('list', {
if (currency != null && currency in Currency) {
data = await Promise.all(
data.map(async (offer) => {
if (offer.offersFullTime?.totalCompensation) {
offer.offersFullTime.totalCompensation.value = await convert(
offer.offersFullTime.totalCompensation.value,
offer.offersFullTime.totalCompensation.currency,
currency,
);
if (offer.offersFullTime?.totalCompensation != null) {
offer.offersFullTime.totalCompensation.value =
await convertWithDate(
offer.offersFullTime.totalCompensation.value,
offer.offersFullTime.totalCompensation.currency,
currency,
offer.offersFullTime.totalCompensation.updatedAt,
);
offer.offersFullTime.totalCompensation.currency = currency;
offer.offersFullTime.baseSalary.value = await convert(
offer.offersFullTime.totalCompensation.value,
offer.offersFullTime.totalCompensation.currency,
offer.offersFullTime.baseSalary.value = await convertWithDate(
offer.offersFullTime.baseSalary.value,
offer.offersFullTime.baseSalary.currency,
currency,
offer.offersFullTime.baseSalary.updatedAt,
);
offer.offersFullTime.baseSalary.currency = currency;
offer.offersFullTime.stocks.value = await convert(
offer.offersFullTime.totalCompensation.value,
offer.offersFullTime.totalCompensation.currency,
offer.offersFullTime.stocks.value = await convertWithDate(
offer.offersFullTime.stocks.value,
offer.offersFullTime.stocks.currency,
currency,
offer.offersFullTime.stocks.updatedAt,
);
offer.offersFullTime.stocks.currency = currency;
offer.offersFullTime.bonus.value = await convert(
offer.offersFullTime.totalCompensation.value,
offer.offersFullTime.totalCompensation.currency,
offer.offersFullTime.bonus.value = await convertWithDate(
offer.offersFullTime.bonus.value,
offer.offersFullTime.bonus.currency,
currency,
offer.offersFullTime.bonus.updatedAt,
);
offer.offersFullTime.bonus.currency = currency;
} else if (offer.offersIntern?.monthlySalary) {
offer.offersIntern.monthlySalary.value = await convert(
} else if (offer.offersIntern?.monthlySalary != null) {
offer.offersIntern.monthlySalary.value = await convertWithDate(
offer.offersIntern.monthlySalary.value,
offer.offersIntern.monthlySalary.currency,
currency,
offer.offersIntern.monthlySalary.updatedAt,
);
offer.offersIntern.monthlySalary.currency = currency;
} else {

@ -1,4 +1,5 @@
// API from https://github.com/fawazahmed0/currency-api#readme
export const convert = async (
value: number,
fromCurrency: string,
@ -16,3 +17,33 @@ export const convert = async (
.then((res) => res.json())
.then((data) => value * data[toCurrency]);
};
// https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@{apiVersion}/{date}/{endpoint}
export const convertWithDate = async (
value: number,
fromCurrency: string,
toCurrency: string,
date: Date,
) => {
if (new Date().toDateString === date.toDateString) {
return await convert(value, fromCurrency, toCurrency);
}
fromCurrency = fromCurrency.trim().toLowerCase();
toCurrency = toCurrency.trim().toLowerCase();
// Format date to YYYY-MM-DD
const formattedDate = date.toJSON().substring(0, 10);
const url = [
'https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1',
formattedDate,
'currencies',
fromCurrency,
toCurrency,
].join('/');
return await fetch(url + '.json')
.then((res) => res.json())
.then((data) => value * data[toCurrency]);
};

Loading…
Cancel
Save