From 32bba31e721b54eae5c9ecf4d9684d669a854333 Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Thu, 9 Apr 2026 00:22:41 +0000 Subject: [PATCH] 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. --- dalpuri/src/sync-by-table.ts | 11 +++++++++++ dalpuri/src/sync.ts | 12 ++++++++++++ dalpuri/src/translations/opportunity.ts | 11 ++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/dalpuri/src/sync-by-table.ts b/dalpuri/src/sync-by-table.ts index a5ea391..ca18bb2 100644 --- a/dalpuri/src/sync-by-table.ts +++ b/dalpuri/src/sync-by-table.ts @@ -442,6 +442,12 @@ const sanitizeModelData = ( ) { sanitized.statusId = null; } + if ( + sanitized.locationId != null && + !context.corporateLocationIds.has(sanitized.locationId as number) + ) { + sanitized.locationId = null; + } } if (targetModel === "schedule") { @@ -750,6 +756,11 @@ const getConfigForTable = (table: string): SyncTableConfig | null => { secondarySalesFlag: true, }, }, + soOppStatus: { + select: { + closedFlag: true, + }, + }, }, }, }, diff --git a/dalpuri/src/sync.ts b/dalpuri/src/sync.ts index 7d59f50..2f9c222 100644 --- a/dalpuri/src/sync.ts +++ b/dalpuri/src/sync.ts @@ -652,6 +652,13 @@ const sanitizeModelData = ( ) { sanitized.stageId = null; } + // Nullify locationId if the corporate location doesn't exist + if ( + sanitized.locationId != null && + !context.corporateLocationIds.has(sanitized.locationId as number) + ) { + sanitized.locationId = null; + } // Nullify taxCodeId if the tax code hasn't synced yet if ( sanitized.taxCodeId != null && @@ -1601,6 +1608,11 @@ export const executeFullDalpuriSync = async (options?: { secondarySalesFlag: true, }, }, + soOppStatus: { + select: { + closedFlag: true, + }, + }, }, }, }, diff --git a/dalpuri/src/translations/opportunity.ts b/dalpuri/src/translations/opportunity.ts index 3623219..24ccb7d 100644 --- a/dalpuri/src/translations/opportunity.ts +++ b/dalpuri/src/translations/opportunity.ts @@ -1,6 +1,7 @@ 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"; @@ -30,6 +31,7 @@ type ApiOpportunityRecord = { dateBecameLead?: Date | null; closedDate?: Date | null; closedFlag: boolean; + locationId?: number | null; closedById?: string | null; updatedBy: string; eneteredBy: string; @@ -42,6 +44,7 @@ type CwOpportunityWithMembers = CwOpportunity & { CwOpportunityMember, "memberRecId" | "primarySalesFlag" | "secondarySalesFlag" >[]; + soOppStatus?: Pick | null; }; const toInterest = (value: number | null): OpportunityInterest | null => { @@ -119,13 +122,19 @@ export const opportunityTranslation: Translation< }, { 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" }, + { + from: "oldCloseFlag", + to: "closedFlag", + process: (_value, _context, row) => + row.soOppStatus?.closedFlag ?? row.oldCloseFlag ?? false, + }, { from: "closedBy", to: "closedById" }, { from: "updatedBy",