132 lines
4.3 KiB
JavaScript
132 lines
4.3 KiB
JavaScript
// Helpers to use md_responsibility_centers (including RR GOG metadata)
|
|
// to build the data needed for ROLABOR + ROGOG lines.
|
|
|
|
/**
|
|
* Extracts responsibility center configuration into a convenient structure.
|
|
*
|
|
* Expects bodyshop.md_responsibility_centers to look like:
|
|
*
|
|
* {
|
|
* costs: [{ name, ... }],
|
|
* profits: [{ name, rr_gogcode, rr_item_type, rr_cust_txbl_flag, ... }],
|
|
* dms_defaults: {
|
|
* costs: { LAB: "Body Labor Cost", ... },
|
|
* profits: { LAB: "Body Labor Sales", ... }
|
|
* },
|
|
* defaults: {
|
|
* costs: { LAB: "Some Cost Center", ... },
|
|
* profits: { LAB: "Some Profit Center", ... }
|
|
* }
|
|
* }
|
|
*/
|
|
function extractRrResponsibilityCenters(bodyshop = {}) {
|
|
const centers = bodyshop.md_responsibility_centers || {};
|
|
const { costs = [], profits = [], dms_defaults = {}, defaults = {} } = centers;
|
|
|
|
const indexByName = (arr = []) =>
|
|
(arr || []).reduce((acc, center) => {
|
|
if (center && center.name) {
|
|
acc[center.name] = center;
|
|
}
|
|
return acc;
|
|
}, {});
|
|
|
|
return {
|
|
costsByName: indexByName(costs),
|
|
profitsByName: indexByName(profits),
|
|
dmsCostDefaults: (dms_defaults && dms_defaults.costs) || {},
|
|
dmsProfitDefaults: (dms_defaults && dms_defaults.profits) || {},
|
|
defaultCosts: defaults.costs || {},
|
|
defaultProfits: defaults.profits || {}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Resolve cost + profit centers for a given internal code (ATS/LAB/etc.).
|
|
* Prioritizes dms_defaults, then defaults.
|
|
*
|
|
* @param {string} code
|
|
* @param {ReturnType<typeof extractRrResponsibilityCenters>} cfg
|
|
* @returns {{ costCenter: object|null, profitCenter: object|null }}
|
|
*/
|
|
function resolveCentersForCode(code, cfg) {
|
|
if (!code || !cfg) return { costCenter: null, profitCenter: null };
|
|
|
|
const costCenterName = cfg.dmsCostDefaults[code] || cfg.defaultCosts[code] || null;
|
|
const profitCenterName = cfg.dmsProfitDefaults[code] || cfg.defaultProfits[code] || null;
|
|
|
|
const costCenter = costCenterName && cfg.costsByName[costCenterName] ? cfg.costsByName[costCenterName] : null;
|
|
const profitCenter =
|
|
profitCenterName && cfg.profitsByName[profitCenterName] ? cfg.profitsByName[profitCenterName] : null;
|
|
|
|
return { costCenter, profitCenter };
|
|
}
|
|
|
|
/**
|
|
* Build a single RR GOG line payload from a jobline + code.
|
|
*
|
|
* NOTE: This returns a neutral JS object. You still need to map it into
|
|
* the exact Mustache / XML shape used for AllGogLineItmInfo.
|
|
*
|
|
* @param {Object} params
|
|
* @param {Object} params.jobline // jobline record from Hasura
|
|
* @param {string} params.code // e.g. "LAB", "ATS", ...
|
|
* @param {object} params.centersConfig // result of extractRrResponsibilityCenters()
|
|
* @param {number} params.sale // CustPrice
|
|
* @param {number} params.cost // DollarCost
|
|
*/
|
|
function buildRrGogLine({ jobline, code, centersConfig, sale, cost }) {
|
|
const { profitCenter } = resolveCentersForCode(code, centersConfig);
|
|
|
|
if (!profitCenter || !profitCenter.rr_gogcode) {
|
|
throw new Error('RR: missing rr_gogcode for profit center mapping of code "' + code + '"');
|
|
}
|
|
|
|
return {
|
|
// For your own reference:
|
|
code,
|
|
joblineId: jobline && jobline.id,
|
|
|
|
// Fields you ultimately care about for ROGOG:
|
|
BreakOut: profitCenter.rr_gogcode, // GOG code / BreakOut
|
|
ItemType: profitCenter.rr_item_type || "G", // P / G / F / ...
|
|
CustTxblNTxblFlag: profitCenter.rr_cust_txbl_flag || "T", // T/N
|
|
CustPrice: Number(sale || 0),
|
|
DollarCost: Number(cost || 0),
|
|
|
|
// Surface full profit center in case templates / logs need it:
|
|
profitCenter
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Build a minimal RR labor (ROLABOR) line "shell".
|
|
* Amounts are zero if all financials are in GOG.
|
|
*
|
|
* @param {Object} params
|
|
* @param {Object} params.job // job record (for RO header context)
|
|
* @param {string} params.opCode // global opcode (already resolved)
|
|
* @param {Object} [params.profitCenter] // optional profit center for context
|
|
*/
|
|
function buildRrLaborLine({ job, opCode, profitCenter }) {
|
|
if (!opCode) {
|
|
throw new Error("RR: opCode is required to build ROLABOR line");
|
|
}
|
|
|
|
return {
|
|
jobId: job && job.id,
|
|
OpCode: opCode,
|
|
PayType: "Cust", // always Cust per your notes
|
|
CustPrice: 0,
|
|
DollarCost: 0,
|
|
profitCenter
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
extractRrResponsibilityCenters,
|
|
resolveCentersForCode,
|
|
buildRrGogLine,
|
|
buildRrLaborLine
|
|
};
|