IO-3368 QB Bill Accumulator
Signed-off-by: Allan Carr <allan@imexsystems.ca>
This commit is contained in:
@@ -425,7 +425,15 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
]
|
||||
: [])
|
||||
]
|
||||
: [])
|
||||
: []),
|
||||
<Form.Item
|
||||
key="accumulatePayableLines"
|
||||
name={["accountingconfig", "accumulatePayableLines"]}
|
||||
label="Accumulate Payable Lines" //{t("bodyshop.fields.accumulatePayableLines")}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
]}
|
||||
</LayoutFormRow>
|
||||
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
|
||||
|
||||
@@ -205,8 +205,36 @@ 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) =>
|
||||
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,
|
||||
@@ -219,7 +247,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop)
|
||||
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