From 5afb0506d2658737dfc9e7349d00c8b95ad9fdc6 Mon Sep 17 00:00:00 2001
From: Bryann Yeap Kok Keong <bryannyeapkk@gmail.com>
Date: Mon, 7 Nov 2022 04:07:14 +0800
Subject: [PATCH] [offers][refactor] Abstract generation of analysis unit into
 a function

---
 .../offers/analysis/analysisGeneration.ts     | 110 ++++++++++--------
 1 file changed, 60 insertions(+), 50 deletions(-)

diff --git a/apps/portal/src/utils/offers/analysis/analysisGeneration.ts b/apps/portal/src/utils/offers/analysis/analysisGeneration.ts
index ecaed697..392bb876 100644
--- a/apps/portal/src/utils/offers/analysis/analysisGeneration.ts
+++ b/apps/portal/src/utils/offers/analysis/analysisGeneration.ts
@@ -225,6 +225,55 @@ const getSalary = (offer: Offer | SimilarOffer, defaultSalary = 0) => {
     : defaultSalary;
 };
 
+const getTopOffers = (
+  similarOffers: Array<SimilarOffer>,
+  noOfSimilarOffers: number,
+) => {
+  const similarOffers90PercentileIndex = Math.ceil(noOfSimilarOffers * 0.1);
+  const topPercentileOffers =
+    noOfSimilarOffers > 2
+      ? similarOffers.slice(
+          similarOffers90PercentileIndex,
+          similarOffers90PercentileIndex + 2,
+        )
+      : similarOffers;
+
+  return topPercentileOffers;
+};
+
+const generateAnalysisUnit = async (
+  prisma: PrismaClient<
+    Prisma.PrismaClientOptions,
+    never,
+    Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
+  >,
+  analysedOffer: Offer,
+  usersOfferIds: Array<string>,
+  isCompanyAnalysisUnit = false,
+) => {
+  let similarOffers = await getSimilarOffers(
+    prisma,
+    analysedOffer,
+    isCompanyAnalysisUnit ? analysedOffer.companyId : undefined,
+  );
+
+  const percentile = calculatePercentile(similarOffers, analysedOffer);
+
+  similarOffers = similarOffers.filter(
+    (offer) => !usersOfferIds.includes(offer.id),
+  );
+  const noOfSimilarOffers = similarOffers.length;
+
+  const topSimilarOffers = getTopOffers(similarOffers, noOfSimilarOffers);
+
+  return {
+    analysedOfferId: analysedOffer.id,
+    noOfSimilarOffers,
+    percentile,
+    topSimilarOffers,
+  };
+};
+
 export const generateAnalysis = async (params: {
   ctx: {
     prisma: PrismaClient<
@@ -304,27 +353,15 @@ export const generateAnalysis = async (params: {
 
   const overallHighestOffer = offers[0];
 
-  const offerIds = offers.map((offer) => offer.id);
+  const usersOfferIds = offers.map((offer) => offer.id);
 
   // OVERALL ANALYSIS
-  let similarOffers = await getSimilarOffers(ctx.prisma, overallHighestOffer);
-  const overallPercentile = calculatePercentile(
-    similarOffers,
+  const overallAnalysisUnit = await generateAnalysisUnit(
+    ctx.prisma,
     overallHighestOffer,
+    usersOfferIds,
   );
 
-  // Get top offers (excluding user's offers)
-  similarOffers = similarOffers.filter((offer) => !offerIds.includes(offer.id));
-  const noOfSimilarOffers = similarOffers.length;
-  const similarOffers90PercentileIndex = Math.ceil(noOfSimilarOffers * 0.1);
-  const topPercentileOffers =
-    noOfSimilarOffers > 2
-      ? similarOffers.slice(
-          similarOffers90PercentileIndex,
-          similarOffers90PercentileIndex + 2,
-        )
-      : similarOffers;
-
   // COMPANY ANALYSIS
   const companyMap = new Map<string, Offer>();
   offers.forEach((offer) => {
@@ -335,39 +372,12 @@ export const generateAnalysis = async (params: {
 
   const companyAnalysis = await Promise.all(
     Array.from(companyMap.values()).map(async (companyOffer) => {
-      // TODO: Refactor calculating analysis into a function
-      let similarCompanyOffers = await getSimilarOffers(
+      return await generateAnalysisUnit(
         ctx.prisma,
         companyOffer,
-        companyOffer.companyId,
+        usersOfferIds,
+        true,
       );
-      const companyPercentile = calculatePercentile(
-        similarCompanyOffers,
-        companyOffer,
-      );
-
-      // Get top offers (excluding user's offers)
-      similarCompanyOffers = similarCompanyOffers.filter(
-        (offer) => !offerIds.includes(offer.id),
-      );
-      const noOfSimilarCompanyOffers = similarCompanyOffers.length;
-      const similarCompanyOffers90PercentileIndex = Math.ceil(
-        noOfSimilarCompanyOffers * 0.1,
-      );
-      const topPercentileCompanyOffers =
-        noOfSimilarCompanyOffers > 2
-          ? similarCompanyOffers.slice(
-              similarCompanyOffers90PercentileIndex,
-              similarCompanyOffers90PercentileIndex + 2,
-            )
-          : similarCompanyOffers;
-
-      return {
-        analysedOfferId: companyOffer.id,
-        noOfSimilarOffers: noOfSimilarCompanyOffers,
-        percentile: companyPercentile,
-        topSimilarOffers: topPercentileCompanyOffers,
-      };
     }),
   );
 
@@ -395,13 +405,13 @@ export const generateAnalysis = async (params: {
         create: {
           analysedOffer: {
             connect: {
-              id: overallHighestOffer.id,
+              id: overallAnalysisUnit.analysedOfferId,
             },
           },
-          noOfSimilarOffers,
-          percentile: overallPercentile,
+          noOfSimilarOffers: overallAnalysisUnit.noOfSimilarOffers,
+          percentile: overallAnalysisUnit.percentile,
           topSimilarOffers: {
-            connect: topPercentileOffers.map((offer) => {
+            connect: overallAnalysisUnit.topSimilarOffers.map((offer) => {
               return { id: offer.id };
             }),
           },