Merged in feature/IO-3368-QB-Bill-Accumulator (pull request #2607)
Feature/IO-3368 QB Bill Accumulator Approved-by: Patrick Fic
This commit is contained in:
@@ -425,7 +425,15 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
]
|
||||
: [])
|
||||
]
|
||||
: [])
|
||||
: []),
|
||||
<Form.Item
|
||||
key="accumulatePayableLines"
|
||||
name={["accountingconfig", "accumulatePayableLines"]}
|
||||
label={t("bodyshop.fields.accumulatePayableLines")}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
]}
|
||||
</LayoutFormRow>
|
||||
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "QBO Receivable Custom Field {{number}}",
|
||||
"accumulatePayableLines": "Accumulate Payable Lines",
|
||||
"address1": "Address 1",
|
||||
"address2": "Address 2",
|
||||
"appt_alt_transport": "Appointment Alternative Transportation Options",
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "",
|
||||
"accumulatePayableLines": "",
|
||||
"address1": "",
|
||||
"address2": "",
|
||||
"appt_alt_transport": "",
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "",
|
||||
"accumulatePayableLines": "",
|
||||
"address1": "",
|
||||
"address2": "",
|
||||
"appt_alt_transport": "",
|
||||
|
||||
@@ -205,21 +205,49 @@ async function InsertVendorRecord(oauthClient, qbo_realmId, req, bill) {
|
||||
|
||||
async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop) {
|
||||
const { accounts, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req, bill.job.shopid);
|
||||
let lines;
|
||||
if (bodyshop.accountingconfig.accumulatePayableLines === true) {
|
||||
lines = Object.values(
|
||||
bill.billlines.reduce((acc, il) => {
|
||||
const { cost_center, actual_cost, quantity = 1 } = il;
|
||||
|
||||
const lines = bill.billlines.map((il) =>
|
||||
generateBillLine(
|
||||
il,
|
||||
accounts,
|
||||
bill.job.class,
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||
classes,
|
||||
taxCodes,
|
||||
bodyshop.md_responsibility_centers.costs,
|
||||
bodyshop.accountingconfig,
|
||||
bodyshop.region_config
|
||||
)
|
||||
);
|
||||
if (!acc[cost_center]) {
|
||||
acc[cost_center] = { ...il, actual_cost: 0, quantity: 1 };
|
||||
}
|
||||
|
||||
acc[cost_center].actual_cost += Math.round(actual_cost * quantity * 100);
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
).map((il) => {
|
||||
il.actual_cost /= 100;
|
||||
return generateBillLine(
|
||||
il,
|
||||
accounts,
|
||||
bill.job.class,
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||
classes,
|
||||
taxCodes,
|
||||
bodyshop.md_responsibility_centers.costs,
|
||||
bodyshop.accountingconfig,
|
||||
bodyshop.region_config
|
||||
);
|
||||
});
|
||||
} else {
|
||||
lines = bill.billlines.map((il) =>
|
||||
generateBillLine(
|
||||
il,
|
||||
accounts,
|
||||
bill.job.class,
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||
classes,
|
||||
taxCodes,
|
||||
bodyshop.md_responsibility_centers.costs,
|
||||
bodyshop.accountingconfig,
|
||||
bodyshop.region_config
|
||||
)
|
||||
);
|
||||
}
|
||||
//QB USA with GST
|
||||
//This was required for the No. 1 Collision Group.
|
||||
if (
|
||||
@@ -241,7 +269,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop)
|
||||
Amount: Dinero({
|
||||
amount: Math.round(
|
||||
bill.billlines.reduce((acc, val) => {
|
||||
return acc + (val.applicable_taxes?.federal ? (val.actual_cost * val.quantity ?? 0) : 0);
|
||||
return acc + (val.applicable_taxes?.federal ? val.actual_cost * val.quantity || 0 : 0);
|
||||
}, 0) * 100
|
||||
)
|
||||
})
|
||||
|
||||
@@ -46,6 +46,28 @@ exports.default = async (req, res) => {
|
||||
};
|
||||
|
||||
const generateBill = (bill, bodyshop) => {
|
||||
let lines;
|
||||
if (bodyshop.accountingconfig.accumulatePayableLines === true) {
|
||||
lines = Object.values(
|
||||
bill.billlines.reduce((acc, il) => {
|
||||
const { cost_center, actual_cost, quantity = 1 } = il;
|
||||
|
||||
if (!acc[cost_center]) {
|
||||
acc[cost_center] = { ...il, actual_cost: 0, quantity: 1 };
|
||||
}
|
||||
|
||||
acc[cost_center].actual_cost += Math.round(actual_cost * quantity * 100);
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
).map((il) => {
|
||||
il.actual_cost /= 100;
|
||||
return generateBillLine(il, bodyshop.md_responsibility_centers, bill.job.class);
|
||||
});
|
||||
} else {
|
||||
lines = bill.billlines.map((il) => generateBillLine(il, bodyshop.md_responsibility_centers, bill.job.class));
|
||||
}
|
||||
|
||||
const billQbxmlObj = {
|
||||
QBXML: {
|
||||
QBXMLMsgsRq: {
|
||||
@@ -67,9 +89,7 @@ const generateBill = (bill, bodyshop) => {
|
||||
}),
|
||||
RefNumber: bill.invoice_number,
|
||||
Memo: `RO ${bill.job.ro_number || ""}`,
|
||||
ExpenseLineAdd: bill.billlines.map((il) =>
|
||||
generateBillLine(il, bodyshop.md_responsibility_centers, bill.job.class)
|
||||
)
|
||||
ExpenseLineAdd: lines
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user