IO-594 additional autohouse improvements.

This commit is contained in:
Patrick Fic
2021-06-15 13:32:17 -07:00
parent a42da5b6da
commit b12ad405c3
2 changed files with 159 additions and 12 deletions

View File

@@ -31,13 +31,17 @@ exports.default = async (req, res) => {
}, },
}; };
console.log("***Number of Failed jobs***: ", erroredJobs.length); console.log(
"***Number of Failed jobs***: ",
erroredJobs.length,
JSON.stringify(erroredJobs.map((x) => x.error))
);
var ret = builder var ret = builder
.create(autoHouseObject, { .create(autoHouseObject, {
version: "1.0", version: "1.0",
encoding: "UTF-8", encoding: "UTF-8",
}) })
.end({ pretty: true }); .end({ pretty: true, allowEmptyTags: true });
//***TODO Change filing naming when creating the cron job. IM_ShopInternalName_DDMMYYYY_HHMMSS.xml //***TODO Change filing naming when creating the cron job. IM_ShopInternalName_DDMMYYYY_HHMMSS.xml
res.type("application/xml"); res.type("application/xml");
@@ -48,6 +52,8 @@ exports.default = async (req, res) => {
const CreateRepairOrderTag = (job, errorCallback) => { const CreateRepairOrderTag = (job, errorCallback) => {
//Level 2 //Level 2
const repairCosts = CreateCosts(job);
try { try {
const ret = { const ret = {
RepairOrderInformation: { RepairOrderInformation: {
@@ -63,8 +69,8 @@ const CreateRepairOrderTag = (job, errorCallback) => {
ShopState: job.bodyshop.state, ShopState: job.bodyshop.state,
ShopZip: job.bodyshop.zip_post, ShopZip: job.bodyshop.zip_post,
ShopPhone: job.bodyshop.phone, ShopPhone: job.bodyshop.phone,
EstimatorID: `${job.est_ct_fn} ${job.est_ct_ln}`, EstimatorID: `${job.est_ct_fn || ""} ${job.est_ct_ln || ""}`,
EstimatorName: `${job.est_ct_fn} ${job.est_ct_ln}`, EstimatorName: `${job.est_ct_fn || ""} ${job.est_ct_ln || ""}`,
}, },
CustomerInformation: { CustomerInformation: {
FirstName: job.ownr_fn, FirstName: job.ownr_fn,
@@ -97,7 +103,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
VehiclePaintCode: null, VehiclePaintCode: null,
VehicleTrimCode: null, VehicleTrimCode: null,
VehicleBodyStyle: null, VehicleBodyStyle: null,
DriveableFlag: job.tlos_ind ? "Y" : "N", DriveableFlag: job.driveable ? "Y" : "N",
}, },
InsuranceInformation: { InsuranceInformation: {
@@ -251,25 +257,39 @@ const CreateRepairOrderTag = (job, errorCallback) => {
}, },
RevisedTotals: { RevisedTotals: {
BodyHours: job.job_totals.rates.lab.hours, BodyHours: job.job_totals.rates.lab.hours,
BodyRepairHours: job.joblines
.filter((line) => repairOpCodes.includes(line.lbr_op))
.reduce((acc, val) => acc + val.mod_lb_hrs, 0),
BodyReplaceHours: job.joblines
.filter((line) => replaceOpCodes.includes(line.lbr_op))
.reduce((acc, val) => acc + val.mod_lb_hrs, 0),
RefinishHours: job.job_totals.rates.lar.hours, RefinishHours: job.job_totals.rates.lar.hours,
MechanicalHours: job.job_totals.rates.lam.hours, MechanicalHours: job.job_totals.rates.lam.hours,
StructuralHours: job.job_totals.rates.las.hours, StructuralHours: job.job_totals.rates.las.hours,
PartsTotal: Dinero(job.job_totals.parts.parts.total).toFormat( PartsTotal: Dinero(job.job_totals.parts.parts.total).toFormat(
AHDineroFormat AHDineroFormat
), ),
PartsTotalCost: 0, PartsTotalCost: repairCosts.PartsTotalCost.toFormat(AHDineroFormat),
PartsOEM: Dinero( PartsOEM: Dinero(
job.job_totals.parts.parts.list.PAN && job.job_totals.parts.parts.list.PAN &&
job.job_totals.parts.parts.list.PAN.total job.job_totals.parts.parts.list.PAN.total
).toFormat(AHDineroFormat), )
PartsOEMCost: 0, .add(
Dinero(
job.job_totals.parts.parts.list.PAP &&
job.job_totals.parts.parts.list.PAP.total
)
)
.toFormat(AHDineroFormat),
PartsOEMCost: repairCosts.PartsOemCost.toFormat(AHDineroFormat),
PartsAM: Dinero( PartsAM: Dinero(
job.job_totals.parts.parts.list.PAA && job.job_totals.parts.parts.list.PAA &&
job.job_totals.parts.parts.list.PAA.total job.job_totals.parts.parts.list.PAA.total
).toFormat(AHDineroFormat), ).toFormat(AHDineroFormat),
PartsAMCost: 0, PartsAMCost: repairCosts.PartsAMCost.toFormat(AHDineroFormat),
PartsReconditioned: null, PartsReconditioned: null,
PartsReconditionedCost: null, PartsReconditionedCost:
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
PartsRecycled: Dinero( PartsRecycled: Dinero(
job.job_totals.parts.parts.list.PAR && job.job_totals.parts.parts.list.PAR &&
job.job_totals.parts.parts.list.PAR.total job.job_totals.parts.parts.list.PAR.total
@@ -389,10 +409,108 @@ const CreateRepairOrderTag = (job, errorCallback) => {
}; };
return ret; return ret;
} catch (error) { } catch (error) {
console.log("Error calculating job", error);
errorCallback(job, error); errorCallback(job, error);
} }
}; };
const CreateCosts = (job) => {
//Create a mapping based on AH Requirements
const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => {
//At the bill level.
bill_val.billlines.map((line_val) => {
//At the bill line level.
//console.log("JobCostingPartsTable -> line_val", line_val);
if (!bill_acc[line_val.cost_center])
bill_acc[line_val.cost_center] = Dinero();
bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
Dinero({
amount: Math.round((line_val.actual_cost || 0) * 100),
})
.multiply(line_val.quantity)
.multiply(bill_val.is_credit_memo ? -1 : 1)
);
return null;
});
return bill_acc;
}, {});
const materialsHours = { mapaHrs: 0, mashHrs: 0 };
//If the hourly rates for job costing are set, add them in.
if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mapa) {
if (
!billTotalsByCostCenters[
job.bodyshop.md_responsibility_centers.defaults.costs.MAPA
]
)
billTotalsByCostCenters[
job.bodyshop.md_responsibility_centers.defaults.costs.MAPA
] = Dinero();
billTotalsByCostCenters[
job.bodyshop.md_responsibility_centers.defaults.costs.MAPA
] = billTotalsByCostCenters[
job.bodyshop.md_responsibility_centers.defaults.costs.MAPA
].add(
Dinero({
amount:
(job.bodyshop.jc_hourly_rates &&
job.bodyshop.jc_hourly_rates.mapa * 100) ||
0,
}).multiply(materialsHours.mapaHrs)
);
}
const ticketTotalsByCostCenter = job.timetickets.reduce(
(ticket_acc, ticket_val) => {
//At the invoice level.
if (!ticket_acc[ticket_val.cost_center])
ticket_acc[ticket_val.cost_center] = Dinero();
ticket_acc[ticket_val.cost_center] = ticket_acc[
ticket_val.cost_center
].add(
Dinero({
amount: Math.round((ticket_val.rate || 0) * 100),
}).multiply(ticket_val.actualhrs || ticket_val.productivehrs || 0)
);
return ticket_acc;
},
{}
);
const defaultCosts = job.bodyshop.md_responsibility_centers.defaults.costs;
return {
PartsTotalCost: Object.keys(billTotalsByCostCenters).reduce((acc, key) => {
return acc.add(billTotalsByCostCenters[key]);
}, Dinero()),
PartsOemCost: (billTotalsByCostCenters[defaultCosts.PAN] || Dinero()).add(
billTotalsByCostCenters[defaultCosts.PAP] || Dinero()
),
PartsAMCost: billTotalsByCostCenters[defaultCosts.PAA] || Dinero(),
PartsReconditionedCost: Dinero(),
PartsRecycledCost: billTotalsByCostCenters[defaultCosts.PAR] || Dinero(),
PartsOtherCost: billTotalsByCostCenters[defaultCosts.PAO] || Dinero(),
SubletTotalCost: billTotalsByCostCenters[defaultCosts.PAS] || Dinero(),
BodyLaborTotalCost: ticketTotalsByCostCenter[defaultCosts.LAB] || Dinero(),
RefinishLaborTotalCost:
ticketTotalsByCostCenter[defaultCosts.LAR] || Dinero(),
MechanicalLaborTotalCost:
ticketTotalsByCostCenter[defaultCosts.LAM] || Dinero(),
StructuralLaborTotalCost:
ticketTotalsByCostCenter[defaultCosts.LAS] || Dinero(),
PMTotalCost: billTotalsByCostCenters[defaultCosts.MAPA] || Dinero(),
BMTotalCost: billTotalsByCostCenters[defaultCosts.MASH] || Dinero(),
MiscTotalCost: billTotalsByCostCenters[defaultCosts.PAO] || Dinero(),
TowingTotalCost: billTotalsByCostCenters[defaultCosts.TOW] || Dinero(),
StorageTotalCost: Dinero(),
DetailTotal: Dinero(),
DetailTotalCost: Dinero(),
SalesTaxTotalCost: Dinero(),
};
};
const StatusMapping = (status, md_ro_statuses) => { const StatusMapping = (status, md_ro_statuses) => {
//EST, SCH, ARR, IPR, RDY, DEL, CLO, CAN, UNDEFINED. //EST, SCH, ARR, IPR, RDY, DEL, CLO, CAN, UNDEFINED.
const { const {
@@ -493,3 +611,6 @@ const generateNullDetailLine = () => {
EstimateAmount: null, EstimateAmount: null,
}; };
}; };
const repairOpCodes = ["OP4", "OP9", "OP10"];
const replaceOpCodes = ["OP2", "OP5", "OP11", "OP12"];

View File

@@ -338,6 +338,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz) {
rate_mapa rate_mapa
rate_mash rate_mash
job_totals job_totals
driveable
bodyshop { bodyshop {
id id
shopname shopname
@@ -350,6 +351,8 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz) {
md_ro_statuses md_ro_statuses
md_order_statuses md_order_statuses
autohouseid autohouseid
md_responsibility_centers
jc_hourly_rates
} }
joblines (where:{removed: {_eq:false}}){ joblines (where:{removed: {_eq:false}}){
id id
@@ -366,7 +369,10 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz) {
part_qty part_qty
part_type part_type
oem_partno oem_partno
billlines (order_by:{bill:{date:desc_nulls_last}}) { lbr_op
profitcenter_part
profitcenter_labor
billlines (order_by:{bill:{date:desc_nulls_last}}) {
actual_cost actual_cost
actual_price actual_price
quantity quantity
@@ -377,7 +383,27 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz) {
invoice_number invoice_number
} }
} }
}
} bills {
id
federal_tax_rate
local_tax_rate
state_tax_rate
is_credit_memo
billlines {
actual_cost
cost_center
id
quantity
}
}
timetickets {
id
rate
cost_center
actualhrs
productivehrs
}
area_of_damage area_of_damage
employee_prep_rel { employee_prep_rel {
first_name first_name