const { GraphQLClient } = require("graphql-request"); const Dinero = require("dinero.js"); const _ = require("lodash"); const queries = require("../graphql-client/queries"); const CreateRRLogEvent = require("./rr-logger-event"); const InstanceManager = require("../utils/instanceMgr").default; const { DiscountNotAlreadyCounted } = InstanceManager({ imex: require("../job/job-totals"), rome: require("../job/job-totals-USA") }); /** * Dinero helpers for safe, compact logging. */ const summarizeMoney = (dinero) => { if (!dinero || typeof dinero.getAmount !== "function") return { cents: null }; return { cents: dinero.getAmount() }; }; const summarizeHash = (hash) => Object.entries(hash || {}).map(([center, dinero]) => ({ center, ...summarizeMoney(dinero) })); const summarizeTaxAllocations = (tax) => Object.entries(tax || {}).map(([key, entry]) => ({ key, sale: summarizeMoney(entry?.sale), cost: summarizeMoney(entry?.cost) })); const summarizeAllocationsArray = (arr) => (arr || []).map((a) => ({ center: a.center || a.tax || null, tax: a.tax || null, sale: summarizeMoney(a.sale), cost: summarizeMoney(a.cost) })); /** * Thin logger wrapper: always uses CreateRRLogEvent, * with structured data passed via meta arg. */ function createDebugLogger(connectionData) { return (msg, meta, level = "DEBUG") => { const baseMsg = `[CdkCalculateAllocations] ${msg}`; CreateRRLogEvent(connectionData, level, baseMsg, meta !== undefined ? meta : undefined); }; } /** * Query job data for allocations. */ async function QueryJobData(connectionData, token, jobid) { CreateRRLogEvent(connectionData, "DEBUG", "Querying job data for allocations", { jobid }); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); const result = await client.setHeaders({ Authorization: token }).request(queries.GET_CDK_ALLOCATIONS, { id: jobid }); return result.jobs_by_pk; } /** * Build tax allocation object depending on environment (imex vs rome). */ function buildTaxAllocations(bodyshop, job) { return InstanceManager({ executeFunction: true, deubg: true, args: [], imex: () => ({ state: { center: bodyshop.md_responsibility_centers.taxes.state.name, sale: Dinero(job.job_totals.totals.state_tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.state, costCenter: bodyshop.md_responsibility_centers.taxes.state }, federal: { center: bodyshop.md_responsibility_centers.taxes.federal.name, sale: Dinero(job.job_totals.totals.federal_tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.federal, costCenter: bodyshop.md_responsibility_centers.taxes.federal } }), rome: () => ({ tax_ty1: { center: bodyshop.md_responsibility_centers.taxes.tax_ty1.name, sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.tax_ty1, costCenter: bodyshop.md_responsibility_centers.taxes.tax_ty1 }, tax_ty2: { center: bodyshop.md_responsibility_centers.taxes.tax_ty2.name, sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.tax_ty2, costCenter: bodyshop.md_responsibility_centers.taxes.tax_ty2 }, tax_ty3: { center: bodyshop.md_responsibility_centers.taxes.tax_ty3.name, sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.tax_ty3, costCenter: bodyshop.md_responsibility_centers.taxes.tax_ty3 }, tax_ty4: { center: bodyshop.md_responsibility_centers.taxes.tax_ty4.name, sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.tax_ty4, costCenter: bodyshop.md_responsibility_centers.taxes.tax_ty4 }, tax_ty5: { center: bodyshop.md_responsibility_centers.taxes.tax_ty5.name, sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.tax_ty5, costCenter: bodyshop.md_responsibility_centers.taxes.tax_ty5 } }) }); } /** * Build profitCenterHash from joblines (parts + labor) and detect MAPA/MASH presence. */ function buildProfitCenterHash(job, debugLog) { let hasMapaLine = false; let hasMashLine = false; const profitCenterHash = job.joblines.reduce((acc, val) => { // MAPA line? if (val.db_ref === "936008") { if (!hasMapaLine) { debugLog("Detected existing MAPA line in joblines", { joblineId: val.id, db_ref: val.db_ref }); } hasMapaLine = true; } // MASH line? if (val.db_ref === "936007") { if (!hasMashLine) { debugLog("Detected existing MASH line in joblines", { joblineId: val.id, db_ref: val.db_ref }); } hasMashLine = true; } // Parts if (val.profitcenter_part) { if (!acc[val.profitcenter_part]) acc[val.profitcenter_part] = Dinero(); let dineroAmount = Dinero({ amount: Math.round(val.act_price * 100) }).multiply(val.part_qty || 1); const hasDiscount = (val.prt_dsmk_m && val.prt_dsmk_m !== 0) || (val.prt_dsmk_p && val.prt_dsmk_p !== 0); if (hasDiscount && DiscountNotAlreadyCounted(val, job.joblines)) { const moneyDiscount = val.prt_dsmk_m ? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) }) : Dinero({ amount: Math.round(val.act_price * 100) }) .multiply(val.part_qty || 0) .percentage(Math.abs(val.prt_dsmk_p || 0)) .multiply(val.prt_dsmk_p > 0 ? 1 : -1); dineroAmount = dineroAmount.add(moneyDiscount); } acc[val.profitcenter_part] = acc[val.profitcenter_part].add(dineroAmount); } // Labor if (val.profitcenter_labor && val.mod_lbr_ty) { if (!acc[val.profitcenter_labor]) acc[val.profitcenter_labor] = Dinero(); const rateKey = `rate_${val.mod_lbr_ty.toLowerCase()}`; const rate = job[rateKey]; acc[val.profitcenter_labor] = acc[val.profitcenter_labor].add( Dinero({ amount: Math.round(rate * 100) }).multiply(val.mod_lb_hrs) ); } return acc; }, {}); debugLog("profitCenterHash after joblines", { hasMapaLine, hasMashLine, centers: summarizeHash(profitCenterHash) }); return { profitCenterHash, hasMapaLine, hasMashLine }; } /** * Build costCenterHash from bills and timetickets. */ function buildCostCenterHash(job, selectedDmsAllocationConfig, disablebillwip, debugLog) { let costCenterHash = {}; // 1) Bills -> costs debugLog("disablebillwip flag", { disablebillwip }); if (!disablebillwip) { costCenterHash = job.bills.reduce((billAcc, bill) => { bill.billlines.forEach((line) => { const targetCenter = selectedDmsAllocationConfig.costs[line.cost_center]; if (!targetCenter) return; if (!billAcc[targetCenter]) billAcc[targetCenter] = Dinero(); const lineDinero = Dinero({ amount: Math.round((line.actual_cost || 0) * 100) }) .multiply(line.quantity) .multiply(bill.is_credit_memo ? -1 : 1); billAcc[targetCenter] = billAcc[targetCenter].add(lineDinero); }); return billAcc; }, {}); } debugLog("costCenterHash after bills (pre-timetickets)", { centers: summarizeHash(costCenterHash) }); // 2) Timetickets -> costs job.timetickets.forEach((ticket) => { const effectiveHours = ticket.employee && ticket.employee.flat_rate ? ticket.productivehrs || 0 : ticket.actualhrs || 0; const ticketTotal = Dinero({ amount: Math.round(ticket.rate * effectiveHours * 100) }); const targetCenter = selectedDmsAllocationConfig.costs[ticket.ciecacode]; if (!targetCenter) return; if (!costCenterHash[targetCenter]) costCenterHash[targetCenter] = Dinero(); costCenterHash[targetCenter] = costCenterHash[targetCenter].add(ticketTotal); }); debugLog("costCenterHash after timetickets", { centers: summarizeHash(costCenterHash) }); return costCenterHash; } /** * Add manual MAPA / MASH sales where needed. */ function applyMapaMashManualLines({ job, selectedDmsAllocationConfig, bodyshop, profitCenterHash, hasMapaLine, hasMashLine, debugLog }) { // MAPA if (!hasMapaLine && job.job_totals.rates.mapa.total.amount > 0) { const mapaAccountName = selectedDmsAllocationConfig.profits.MAPA; const mapaAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === mapaAccountName); if (mapaAccount) { debugLog("Adding MAPA Line Manually", { mapaAccountName, amount: summarizeMoney(Dinero(job.job_totals.rates.mapa.total)) }); if (!profitCenterHash[mapaAccountName]) profitCenterHash[mapaAccountName] = Dinero(); profitCenterHash[mapaAccountName] = profitCenterHash[mapaAccountName].add( Dinero(job.job_totals.rates.mapa.total) ); } else { debugLog("NO MAPA ACCOUNT FOUND!!", { mapaAccountName }); } } // MASH if (!hasMashLine && job.job_totals.rates.mash.total.amount > 0) { const mashAccountName = selectedDmsAllocationConfig.profits.MASH; const mashAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === mashAccountName); if (mashAccount) { debugLog("Adding MASH Line Manually", { mashAccountName, amount: summarizeMoney(Dinero(job.job_totals.rates.mash.total)) }); if (!profitCenterHash[mashAccountName]) profitCenterHash[mashAccountName] = Dinero(); profitCenterHash[mashAccountName] = profitCenterHash[mashAccountName].add( Dinero(job.job_totals.rates.mash.total) ); } else { debugLog("NO MASH ACCOUNT FOUND!!", { mashAccountName }); } } return profitCenterHash; } /** * Apply materials costing (MAPA/MASH cost side) when configured. */ function applyMaterialsCosting({ job, bodyshop, selectedDmsAllocationConfig, costCenterHash, debugLog }) { const { cdk_configuration } = bodyshop || {}; if (!cdk_configuration?.sendmaterialscosting) return costCenterHash; debugLog("sendmaterialscosting enabled", { sendmaterialscosting: cdk_configuration.sendmaterialscosting, use_paint_scale_data: job.bodyshop.use_paint_scale_data, mixdataLength: job.mixdata?.length || 0 }); const percent = cdk_configuration.sendmaterialscosting; // Paint Mat (MAPA) const mapaAccountName = selectedDmsAllocationConfig.costs.MAPA; const mapaAccount = bodyshop.md_responsibility_centers.costs.find((c) => c.name === mapaAccountName); if (mapaAccount) { if (!costCenterHash[mapaAccountName]) costCenterHash[mapaAccountName] = Dinero(); if (job.bodyshop.use_paint_scale_data === true) { if (job.mixdata.length > 0) { debugLog("Using mixdata for MAPA cost", { mapaAccountName, totalliquidcost: job.mixdata[0] && job.mixdata[0].totalliquidcost }); costCenterHash[mapaAccountName] = costCenterHash[mapaAccountName].add( Dinero({ amount: Math.round(((job.mixdata[0] && job.mixdata[0].totalliquidcost) || 0) * 100) }) ); } else { debugLog("Using percentage of MAPA total (no mixdata)", { mapaAccountName }); costCenterHash[mapaAccountName] = costCenterHash[mapaAccountName].add( Dinero(job.job_totals.rates.mapa.total).percentage(percent) ); } } else { debugLog("Using percentage of MAPA total (no paint scale data)", { mapaAccountName }); costCenterHash[mapaAccountName] = costCenterHash[mapaAccountName].add( Dinero(job.job_totals.rates.mapa.total).percentage(percent) ); } } else { debugLog("NO MAPA ACCOUNT FOUND (costs)!!", { mapaAccountName }); } // Shop Mat (MASH) const mashAccountName = selectedDmsAllocationConfig.costs.MASH; const mashAccount = bodyshop.md_responsibility_centers.costs.find((c) => c.name === mashAccountName); if (mashAccount) { debugLog("Adding MASH material costing", { mashAccountName }); if (!costCenterHash[mashAccountName]) costCenterHash[mashAccountName] = Dinero(); costCenterHash[mashAccountName] = costCenterHash[mashAccountName].add( Dinero(job.job_totals.rates.mash.total).percentage(percent) ); } else { debugLog("NO MASH ACCOUNT FOUND (costs)!!", { mashAccountName }); } return costCenterHash; } /** * Apply non-tax extras (PVRT, towing, storage, PAO). */ function applyExtras({ job, bodyshop, selectedDmsAllocationConfig, profitCenterHash, taxAllocations, debugLog }) { const { ca_bc_pvrt } = job; // BC PVRT -> state tax if (ca_bc_pvrt) { debugLog("Adding PVRT to state tax allocation", { ca_bc_pvrt }); taxAllocations.state.sale = taxAllocations.state.sale.add(Dinero({ amount: Math.round((ca_bc_pvrt || 0) * 100) })); } // Towing if (job.towing_payable && job.towing_payable !== 0) { const towAccountName = selectedDmsAllocationConfig.profits.TOW; const towAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === towAccountName); if (towAccount) { debugLog("Adding towing_payable to TOW account", { towAccountName, towing_payable: job.towing_payable }); if (!profitCenterHash[towAccountName]) profitCenterHash[towAccountName] = Dinero(); profitCenterHash[towAccountName] = profitCenterHash[towAccountName].add( Dinero({ amount: Math.round((job.towing_payable || 0) * 100) }) ); } else { debugLog("NO TOW ACCOUNT FOUND!!", { towAccountName }); } } // Storage (shares TOW account) if (job.storage_payable && job.storage_payable !== 0) { const storageAccountName = selectedDmsAllocationConfig.profits.TOW; const towAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === storageAccountName); if (towAccount) { debugLog("Adding storage_payable to TOW account", { storageAccountName, storage_payable: job.storage_payable }); if (!profitCenterHash[storageAccountName]) profitCenterHash[storageAccountName] = Dinero(); profitCenterHash[storageAccountName] = profitCenterHash[storageAccountName].add( Dinero({ amount: Math.round((job.storage_payable || 0) * 100) }) ); } else { debugLog("NO STORAGE/TOW ACCOUNT FOUND!!", { storageAccountName }); } } // Bottom line adjustment -> PAO if (job.adjustment_bottom_line && job.adjustment_bottom_line !== 0) { const otherAccountName = selectedDmsAllocationConfig.profits.PAO; const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === otherAccountName); if (otherAccount) { debugLog("Adding adjustment_bottom_line to PAO", { otherAccountName, adjustment_bottom_line: job.adjustment_bottom_line }); if (!profitCenterHash[otherAccountName]) profitCenterHash[otherAccountName] = Dinero(); profitCenterHash[otherAccountName] = profitCenterHash[otherAccountName].add( Dinero({ amount: Math.round((job.adjustment_bottom_line || 0) * 100) }) ); } else { debugLog("NO PAO ACCOUNT FOUND!!", { otherAccountName }); } } return { profitCenterHash, taxAllocations }; } /** * Apply Rome-specific profile adjustments (parts + rates). */ function applyRomeProfileAdjustments({ job, bodyshop, selectedDmsAllocationConfig, profitCenterHash, debugLog, connectionData }) { if (!InstanceManager({ rome: true })) return profitCenterHash; debugLog("ROME profile adjustments block entered", { partAdjustmentKeys: Object.keys(job.job_totals.parts.adjustments || {}), rateKeys: Object.keys(job.job_totals.rates || {}) }); // Parts adjustments Object.keys(job.job_totals.parts.adjustments).forEach((key) => { const accountName = selectedDmsAllocationConfig.profits[key]; const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName); if (otherAccount) { if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero(); profitCenterHash[accountName] = profitCenterHash[accountName].add(Dinero(job.job_totals.parts.adjustments[key])); debugLog("Added parts adjustment", { key, accountName, adjustment: summarizeMoney(Dinero(job.job_totals.parts.adjustments[key])) }); } else { CreateRRLogEvent( connectionData, "ERROR", "Error encountered in CdkCalculateAllocations. Unable to find parts adjustment account.", { accountName, key } ); debugLog("Missing parts adjustment account", { key, accountName }); } }); // Labor / materials adjustments Object.keys(job.job_totals.rates).forEach((key) => { const rate = job.job_totals.rates[key]; if (!rate || !rate.adjustment) return; if (Dinero(rate.adjustment).isZero()) return; const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()]; const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName); if (otherAccount) { if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero(); profitCenterHash[accountName] = profitCenterHash[accountName].add(Dinero(job.job_totals.rates[key].adjustments)); debugLog("Added rate adjustment", { key, accountName }); } else { CreateRRLogEvent( connectionData, "ERROR", "Error encountered in CdkCalculateAllocations. Unable to find rate adjustment account.", { accountName, key } ); debugLog("Missing rate adjustment account", { key, accountName }); } }); return profitCenterHash; } /** * Build job-level profit/cost allocations for each center. */ function buildJobAllocations(bodyshop, profitCenterHash, costCenterHash, debugLog) { const centers = _.union(Object.keys(profitCenterHash), Object.keys(costCenterHash)); const jobAllocations = centers.map((key) => { const profitCenter = bodyshop.md_responsibility_centers.profits.find((c) => c.name === key); const costCenter = bodyshop.md_responsibility_centers.costs.find((c) => c.name === key); return { center: key, sale: profitCenterHash[key] || Dinero(), cost: costCenterHash[key] || Dinero(), profitCenter, costCenter }; }); debugLog("jobAllocations built", summarizeAllocationsArray(jobAllocations)); return jobAllocations; } /** * Build tax allocations array from taxAllocations hash. */ function buildTaxAllocArray(taxAllocations, selectedDmsAllocationConfig, debugLog) { const taxAllocArray = Object.keys(taxAllocations) .filter((key) => taxAllocations[key].sale.getAmount() > 0 || taxAllocations[key].cost.getAmount() > 0) .map((key) => { if ( key === "federal" && selectedDmsAllocationConfig.gst_override && selectedDmsAllocationConfig.gst_override !== "" ) { const ret = { ...taxAllocations[key], tax: key }; ret.costCenter.dms_acctnumber = selectedDmsAllocationConfig.gst_override; ret.profitCenter.dms_acctnumber = selectedDmsAllocationConfig.gst_override; return ret; } return { ...taxAllocations[key], tax: key }; }); debugLog("taxAllocArray built", summarizeAllocationsArray(taxAllocArray)); return taxAllocArray; } /** * Build adjustment allocations (ttl_adjustment + ttl_tax_adjustment). */ function buildAdjustmentAllocations(job, bodyshop, debugLog) { const ttlAdjArray = job.job_totals.totals.ttl_adjustment ? [ { center: "SUB ADJ", sale: Dinero(job.job_totals.totals.ttl_adjustment), cost: Dinero(), profitCenter: { name: "SUB ADJ", accountdesc: "SUB ADJ", accountitem: "SUB ADJ", accountname: "SUB ADJ", dms_acctnumber: bodyshop.md_responsibility_centers.ttl_adjustment.dms_acctnumber }, costCenter: {} } ] : []; const ttlTaxAdjArray = job.job_totals.totals.ttl_tax_adjustment ? [ { center: "TAX ADJ", sale: Dinero(job.job_totals.totals.ttl_tax_adjustment), cost: Dinero(), profitCenter: { name: "TAX ADJ", accountdesc: "TAX ADJ", accountitem: "TAX ADJ", accountname: "TAX ADJ", dms_acctnumber: bodyshop.md_responsibility_centers.ttl_tax_adjustment.dms_acctnumber }, costCenter: {} } ] : []; if (ttlAdjArray.length) { debugLog("ttl_adjustment allocation added", summarizeAllocationsArray(ttlAdjArray)); } if (ttlTaxAdjArray.length) { debugLog("ttl_tax_adjustment allocation added", summarizeAllocationsArray(ttlTaxAdjArray)); } return { ttlAdjArray, ttlTaxAdjArray }; } /** * Core allocation calculation – Reynolds-only, Reynolds-logging only. */ function calculateAllocations(connectionData, job) { const { bodyshop } = job; const debugLog = createDebugLogger(connectionData); debugLog("ENTER", { bodyshopId: bodyshop?.id, bodyshopName: bodyshop?.name, dms_allocation: job.dms_allocation, hasBills: Array.isArray(job.bills) ? job.bills.length : 0, joblines: Array.isArray(job.joblines) ? job.joblines.length : 0, timetickets: Array.isArray(job.timetickets) ? job.timetickets.length : 0 }); // 1) Tax allocations let taxAllocations = buildTaxAllocations(bodyshop, job); debugLog("Initial taxAllocations", summarizeTaxAllocations(taxAllocations)); // 2) Profit centers from job lines + MAPA/MASH detection const { profitCenterHash: initialProfitHash, hasMapaLine, hasMashLine } = buildProfitCenterHash(job, debugLog); // 3) DMS allocation config const selectedDmsAllocationConfig = bodyshop.md_responsibility_centers.dms_defaults.find((d) => d.name === job.dms_allocation) || null; CreateRRLogEvent(connectionData, "DEBUG", "Using DMS Allocation for cost export", { allocationName: selectedDmsAllocationConfig && selectedDmsAllocationConfig.name }); debugLog("Selected DMS allocation config", { name: selectedDmsAllocationConfig && selectedDmsAllocationConfig.name }); // 4) Cost centers from bills and timetickets const disablebillwip = !!bodyshop?.pbs_configuration?.disablebillwip; let costCenterHash = buildCostCenterHash(job, selectedDmsAllocationConfig, disablebillwip, debugLog); // 5) Manual MAPA/MASH sales (when needed) let profitCenterHash = applyMapaMashManualLines({ job, selectedDmsAllocationConfig, bodyshop, profitCenterHash: initialProfitHash, hasMapaLine, hasMashLine, debugLog }); // 6) Materials costing (MAPA/MASH cost side) costCenterHash = applyMaterialsCosting({ job, bodyshop, selectedDmsAllocationConfig, costCenterHash, debugLog }); // 7) PVRT / towing / storage / PAO extras ({ profitCenterHash, taxAllocations } = applyExtras({ job, bodyshop, selectedDmsAllocationConfig, profitCenterHash, taxAllocations, debugLog })); // 8) Rome-only profile-level adjustments profitCenterHash = applyRomeProfileAdjustments({ job, bodyshop, selectedDmsAllocationConfig, profitCenterHash, debugLog, connectionData }); debugLog("profitCenterHash before jobAllocations build", { centers: summarizeHash(profitCenterHash) }); debugLog("costCenterHash before jobAllocations build", { centers: summarizeHash(costCenterHash) }); // 9) Build job-level allocations & tax allocations const jobAllocations = buildJobAllocations(bodyshop, profitCenterHash, costCenterHash, debugLog); const taxAllocArray = buildTaxAllocArray(taxAllocations, selectedDmsAllocationConfig, debugLog); const { ttlAdjArray, ttlTaxAdjArray } = buildAdjustmentAllocations(job, bodyshop, debugLog); // 10) Final combined array const allocations = [...jobAllocations, ...taxAllocArray, ...ttlAdjArray, ...ttlTaxAdjArray]; debugLog("FINAL allocations summary", { count: allocations.length, allocations: summarizeAllocationsArray(allocations) }); debugLog("EXIT"); return allocations; } /** * HTTP route wrapper (kept for compatibility; still logs via RR logger). */ exports.defaultRoute = async function (req, res) { try { CreateRRLogEvent(req, "DEBUG", "Received request to calculate allocations", { jobid: req.body.jobid }); const jobData = await QueryJobData(req, req.BearerToken, req.body.jobid); const data = calculateAllocations(req, jobData); return res.status(200).json({ data }); } catch (error) { CreateRRLogEvent(req, "ERROR", "Error encountered in CdkCalculateAllocations.", { message: error?.message || String(error), stack: error?.stack }); res.status(500).json({ error: `Error encountered in CdkCalculateAllocations. ${error}` }); } }; /** * Socket entry point (what rr-job-export & rr-register-socket-events call). * Reynolds-only: WSS + RR logger. */ exports.default = async function (socket, jobid) { try { const token = `Bearer ${socket.handshake.auth.token}`; const jobData = await QueryJobData(socket, token, jobid); return calculateAllocations(socket, jobData); } catch (error) { CreateRRLogEvent(socket, "ERROR", "Error encountered in CdkCalculateAllocations.", { message: error?.message || String(error), stack: error?.stack }); return null; } };