Files
optima/dalpuri/src/translations/opportunity.ts
T
HoloPanio 32bba31e72 fix(dalpuri): populate locationId and fix closedFlag on opportunities
- Add ownerLevelRecId -> locationId mapping to opportunity translation
- Include soOppStatus in opportunity query and derive closedFlag from
  status.closedFlag (with fallback to legacy oldCloseFlag field)
- Add locationId sanitization guard in both sync.ts and sync-by-table.ts

Note: departmentId is not available in CW SO_Opportunity table and
remains null for synced records.
2026-04-09 00:22:41 +00:00

153 lines
4.5 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;
};
const toInterest = (value: number | null): OpportunityInterest | null => {
if (value == null) return null;
if (value <= 1) return OpportunityInterest.COLD;
if (value === 2) return OpportunityInterest.WARM;
return OpportunityInterest.HOT;
};
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: "soInterestRecId",
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" },
],
};