diff --git a/client/src/components/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx
index 165e133a2..97df97c80 100644
--- a/client/src/components/shop-info/shop-info.general.component.jsx
+++ b/client/src/components/shop-info/shop-info.general.component.jsx
@@ -425,7 +425,15 @@ export function ShopInfoGeneral({ form, bodyshop }) {
]
: [])
]
- : [])
+ : []),
+
+
+
]}
null}>
diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js
index 9f0aacc42..a21e8ebc0 100644
--- a/server/accounting/qbo/qbo-payables.js
+++ b/server/accounting/qbo/qbo-payables.js
@@ -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
)
})
diff --git a/server/accounting/qbxml/qbxml-payables.js b/server/accounting/qbxml/qbxml-payables.js
index 9e658ecea..2b5efaf18 100644
--- a/server/accounting/qbxml/qbxml-payables.js
+++ b/server/accounting/qbxml/qbxml-payables.js
@@ -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
}
}
}