159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
import {
|
|
Opportunity as CwOpportunity,
|
|
OpportunityMember as CwOpportunityMember,
|
|
SoOppStatus as CwSoOppStatus,
|
|
} from "../../generated/prisma/client";
|
|
import { OpportunityInterest } from "../../../api/generated/prisma/client";
|
|
import { Translation, skipRow } from "./types";
|
|
import { TranslationContext } from "./context";
|
|
|
|
type ApiOpportunityRecord = {
|
|
id: number;
|
|
name: string;
|
|
notes?: string | null;
|
|
oppNarrative?: string | null;
|
|
typeId: number;
|
|
stageCwId?: number | null;
|
|
stageId?: number | null;
|
|
statusId?: number | null;
|
|
taxCodeId?: number | null;
|
|
interest?: OpportunityInterest | null;
|
|
probability: number;
|
|
source?: string | null;
|
|
primarySalesRepId?: string | null;
|
|
secondarySalesRepId?: string | null;
|
|
companyId?: number | null;
|
|
contactId?: number | null;
|
|
siteId?: number | null;
|
|
customerPO?: string | null;
|
|
expectedCloseDate?: Date | null;
|
|
pipelineChangeDate?: Date | null;
|
|
dateBecameLead?: Date | null;
|
|
closedDate?: Date | null;
|
|
closedFlag: boolean;
|
|
locationId?: number | null;
|
|
closedById?: string | null;
|
|
updatedBy: string;
|
|
eneteredBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
type CwOpportunityWithMembers = CwOpportunity & {
|
|
members?: Pick<
|
|
CwOpportunityMember,
|
|
"memberRecId" | "primarySalesFlag" | "secondarySalesFlag"
|
|
>[];
|
|
soOppStatus?: Pick<CwSoOppStatus, "closedFlag"> | null;
|
|
soInterest?: { description: string | null } | null;
|
|
};
|
|
|
|
const toInterest = (
|
|
value: { description: string | null } | null
|
|
): OpportunityInterest | null => {
|
|
if (value == null) return null;
|
|
const desc = value.description?.toLowerCase() ?? "";
|
|
if (desc.includes("cold")) return OpportunityInterest.COLD;
|
|
if (desc.includes("warm") || desc.includes("medium"))
|
|
return OpportunityInterest.WARM;
|
|
if (desc.includes("hot")) return OpportunityInterest.HOT;
|
|
return null;
|
|
};
|
|
|
|
export const opportunityTranslation: Translation<
|
|
CwOpportunityWithMembers,
|
|
ApiOpportunityRecord,
|
|
TranslationContext
|
|
> = {
|
|
values: [
|
|
{ from: "opportunityRecId", to: "id" },
|
|
{ from: "opportunityName", to: "name" },
|
|
{ from: "notes", to: "notes" },
|
|
{
|
|
from: "opportunityRecId",
|
|
to: "oppNarrative",
|
|
process: (value, context) => {
|
|
if (value == null) return null;
|
|
return context.opportunityNarrativeByOpportunityId.get(value) ?? null;
|
|
},
|
|
},
|
|
{
|
|
from: "soTypeRecId",
|
|
to: "typeId",
|
|
process: (value, context) => {
|
|
if (value != null) return value;
|
|
if (context.defaultOpportunityTypeId != null)
|
|
return context.defaultOpportunityTypeId;
|
|
skipRow("Opportunity missing type and no default type available");
|
|
},
|
|
},
|
|
{ from: "soPipelineRecId", to: "stageId" },
|
|
{ from: "soOppStatusRecId", to: "statusId" },
|
|
{ from: "taxCodeRecId", to: "taxCodeId" },
|
|
{
|
|
from: "soInterest",
|
|
to: "interest",
|
|
process: toInterest,
|
|
},
|
|
{
|
|
from: "probabilityToClose",
|
|
to: "probability",
|
|
process: (value) => (value == null ? 0 : value),
|
|
},
|
|
{ from: "source", to: "source" },
|
|
{
|
|
from: "opportunityRecId",
|
|
to: "primarySalesRepId",
|
|
process: (_value, context, row) => {
|
|
const primary = row.members?.find((member) => member.primarySalesFlag);
|
|
if (!primary) return null;
|
|
return (
|
|
context.userIdentifiersByMemberRecId.get(primary.memberRecId) ?? null
|
|
);
|
|
},
|
|
},
|
|
{
|
|
from: "opportunityRecId",
|
|
to: "secondarySalesRepId",
|
|
process: (_value, context, row) => {
|
|
const secondary = row.members?.find(
|
|
(member) => member.secondarySalesFlag
|
|
);
|
|
if (!secondary) return null;
|
|
return (
|
|
context.userIdentifiersByMemberRecId.get(secondary.memberRecId) ??
|
|
null
|
|
);
|
|
},
|
|
},
|
|
{ from: "companyRecId", to: "companyId" },
|
|
{ from: "contactRecId", to: "contactId" },
|
|
{ from: "ownerLevelRecId", to: "locationId" },
|
|
{ from: "companyAddressRecId", to: "siteId" },
|
|
{ from: "poNumber", to: "customerPO" },
|
|
{ from: "dateCloseExpected", to: "expectedCloseDate" },
|
|
{ from: "datePipelineChange", to: "pipelineChangeDate" },
|
|
{ from: "dateBecameLead", to: "dateBecameLead" },
|
|
{ from: "dateClosed", to: "closedDate" },
|
|
{
|
|
from: "oldCloseFlag",
|
|
to: "closedFlag",
|
|
process: (_value, _context, row) =>
|
|
row.soOppStatus?.closedFlag ?? row.oldCloseFlag ?? false,
|
|
},
|
|
{ from: "closedBy", to: "closedById" },
|
|
{
|
|
from: "updatedBy",
|
|
to: "updatedBy",
|
|
process: (value) => (value ? value : "system"),
|
|
},
|
|
{
|
|
from: "enteredBy",
|
|
to: "eneteredBy",
|
|
process: (value) => (value ? value : "system"),
|
|
},
|
|
{ from: "dateBecameLeadUtc", to: "createdAt" },
|
|
{ from: "lastUpdatedUtc", to: "updatedAt" },
|
|
],
|
|
};
|