IO-1573 CDK Job costing updates
This commit is contained in:
@@ -1030,6 +1030,7 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
|
|||||||
status
|
status
|
||||||
ca_bc_pvrt
|
ca_bc_pvrt
|
||||||
ca_customer_gst
|
ca_customer_gst
|
||||||
|
dms_allocation
|
||||||
joblines(where: { removed: { _eq: false } }) {
|
joblines(where: { removed: { _eq: false } }) {
|
||||||
id
|
id
|
||||||
db_ref
|
db_ref
|
||||||
@@ -1073,11 +1074,14 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
|
|||||||
actualhrs
|
actualhrs
|
||||||
productivehrs
|
productivehrs
|
||||||
flat_rate
|
flat_rate
|
||||||
|
ciecacode
|
||||||
}
|
}
|
||||||
bodyshop{
|
bodyshop{
|
||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
|
cdk_dealerid
|
||||||
|
pbs_serialnumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
@@ -1133,6 +1137,7 @@ exports.QUERY_JOB_COSTING_DETAILS_MULTI = ` query QUERY_JOB_COSTING_DETAILS_MULT
|
|||||||
status
|
status
|
||||||
ca_bc_pvrt
|
ca_bc_pvrt
|
||||||
ca_customer_gst
|
ca_customer_gst
|
||||||
|
dms_allocation
|
||||||
joblines(where: {removed: {_eq: false}}) {
|
joblines(where: {removed: {_eq: false}}) {
|
||||||
id
|
id
|
||||||
db_ref
|
db_ref
|
||||||
@@ -1176,11 +1181,14 @@ exports.QUERY_JOB_COSTING_DETAILS_MULTI = ` query QUERY_JOB_COSTING_DETAILS_MULT
|
|||||||
actualhrs
|
actualhrs
|
||||||
productivehrs
|
productivehrs
|
||||||
flat_rate
|
flat_rate
|
||||||
|
ciecacode
|
||||||
}
|
}
|
||||||
bodyshop {
|
bodyshop {
|
||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
|
cdk_dealerid
|
||||||
|
pbs_serialnumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ function GenerateCostingData(job) {
|
|||||||
val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "?";
|
val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "?";
|
||||||
|
|
||||||
if (laborProfitCenter === "?")
|
if (laborProfitCenter === "?")
|
||||||
console.log("Unknown type", val.mod_lbr_ty);
|
console.log("Unknown type", val.line_desc, val.mod_lbr_ty);
|
||||||
|
|
||||||
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
|
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
|
||||||
const laborAmount = Dinero({
|
const laborAmount = Dinero({
|
||||||
@@ -285,11 +285,12 @@ function GenerateCostingData(job) {
|
|||||||
val.profitcenter_part || defaultProfits[val.part_type] || "?";
|
val.profitcenter_part || defaultProfits[val.part_type] || "?";
|
||||||
|
|
||||||
if (partsProfitCenter === "?")
|
if (partsProfitCenter === "?")
|
||||||
console.log("Unknown type", val.part_type);
|
console.log("Unknown type", val.line_desc, val.part_type);
|
||||||
|
|
||||||
if (!partsProfitCenter)
|
if (!partsProfitCenter)
|
||||||
console.log(
|
console.log(
|
||||||
"Unknown cost/profit center mapping for parts.",
|
"Unknown cost/profit center mapping for parts.",
|
||||||
|
val.line_desc,
|
||||||
val.part_type
|
val.part_type
|
||||||
);
|
);
|
||||||
const partsAmount = Dinero({
|
const partsAmount = Dinero({
|
||||||
@@ -298,13 +299,13 @@ function GenerateCostingData(job) {
|
|||||||
.multiply(val.part_qty || 1)
|
.multiply(val.part_qty || 1)
|
||||||
.add(
|
.add(
|
||||||
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
||||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||||
: Dinero({
|
: Dinero({
|
||||||
amount: Math.round(val.act_price * 100),
|
amount: Math.round(val.act_price * 100),
|
||||||
})
|
})
|
||||||
.multiply(val.part_qty || 0)
|
.multiply(val.part_qty || 0)
|
||||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||||
);
|
);
|
||||||
if (!acc.parts[partsProfitCenter])
|
if (!acc.parts[partsProfitCenter])
|
||||||
acc.parts[partsProfitCenter] = Dinero();
|
acc.parts[partsProfitCenter] = Dinero();
|
||||||
@@ -322,7 +323,7 @@ function GenerateCostingData(job) {
|
|||||||
"?";
|
"?";
|
||||||
|
|
||||||
if (partsProfitCenter === "?") {
|
if (partsProfitCenter === "?") {
|
||||||
console.log("Unknown type", val.part_type);
|
console.log("Unknown type", val.line_desc, val.part_type);
|
||||||
} else {
|
} else {
|
||||||
const partsAmount = Dinero({
|
const partsAmount = Dinero({
|
||||||
amount: Math.round((val.act_price || 0) * 100),
|
amount: Math.round((val.act_price || 0) * 100),
|
||||||
@@ -330,13 +331,13 @@ function GenerateCostingData(job) {
|
|||||||
.multiply(val.part_qty || 1)
|
.multiply(val.part_qty || 1)
|
||||||
.add(
|
.add(
|
||||||
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
val.prt_dsmk_m && val.prt_dsmk_m !== 0
|
||||||
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
|
||||||
: Dinero({
|
: Dinero({
|
||||||
amount: Math.round(val.act_price * 100),
|
amount: Math.round(val.act_price * 100),
|
||||||
})
|
})
|
||||||
.multiply(val.part_qty || 0)
|
.multiply(val.part_qty || 0)
|
||||||
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
.percentage(Math.abs(val.prt_dsmk_p || 0))
|
||||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!acc.parts[partsProfitCenter])
|
if (!acc.parts[partsProfitCenter])
|
||||||
@@ -372,21 +373,41 @@ function GenerateCostingData(job) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Is it a DMS Setup?
|
||||||
|
const selectedDmsAllocationConfig =
|
||||||
|
job.bodyshop.md_responsibility_centers.dms_defaults.find(
|
||||||
|
(d) => d.name === job.dms_allocation
|
||||||
|
) || job.bodyshop.md_responsibility_centers.defaults;
|
||||||
|
|
||||||
const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => {
|
const billTotalsByCostCenters = job.bills.reduce((bill_acc, bill_val) => {
|
||||||
//At the bill level.
|
//At the bill level.
|
||||||
bill_val.billlines.map((line_val) => {
|
bill_val.billlines.map((line_val) => {
|
||||||
//At the bill line level.
|
//At the bill line level.
|
||||||
//console.log("JobCostingPartsTable -> line_val", line_val);
|
if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) {
|
||||||
if (!bill_acc[line_val.cost_center])
|
if (!bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]])
|
||||||
bill_acc[line_val.cost_center] = Dinero();
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] =
|
||||||
|
Dinero();
|
||||||
|
|
||||||
bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]] =
|
||||||
Dinero({
|
bill_acc[selectedDmsAllocationConfig.costs[line_val.cost_center]].add(
|
||||||
amount: Math.round((line_val.actual_cost || 0) * 100),
|
Dinero({
|
||||||
})
|
amount: Math.round((line_val.actual_cost || 0) * 100),
|
||||||
.multiply(line_val.quantity)
|
})
|
||||||
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
.multiply(line_val.quantity)
|
||||||
);
|
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
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 null;
|
||||||
});
|
});
|
||||||
@@ -443,20 +464,38 @@ function GenerateCostingData(job) {
|
|||||||
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
||||||
(ticket_acc, ticket_val) => {
|
(ticket_acc, ticket_val) => {
|
||||||
//At the invoice level.
|
//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[
|
if (job.bodyshop.pbs_serialnumber || job.bodyshop.cdk_dealerid) {
|
||||||
ticket_val.cost_center
|
if (!ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]])
|
||||||
].add(
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]] =
|
||||||
Dinero({
|
Dinero();
|
||||||
amount: Math.round((ticket_val.rate || 0) * 100),
|
|
||||||
}).multiply(
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]] =
|
||||||
ticket_val.flat_rate
|
ticket_acc[selectedDmsAllocationConfig.costs[ticket_val.ciecacode]].add(
|
||||||
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
Dinero({
|
||||||
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
amount: Math.round((ticket_val.rate || 0) * 100),
|
||||||
) //Should base this on the employee.
|
}).multiply(
|
||||||
);
|
ticket_val.flat_rate
|
||||||
|
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
||||||
|
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
||||||
|
) //Should base this on the employee.
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
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.flat_rate
|
||||||
|
? ticket_val.productivehrs || ticket_val.actualhrs || 0
|
||||||
|
: ticket_val.actualhrs || ticket_val.productivehrs || 0
|
||||||
|
) //Should base this on the employee.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ticket_acc;
|
return ticket_acc;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user