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>
|
</LayoutFormRow>
|
||||||
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
|
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
|
||||||
|
|||||||
@@ -205,21 +205,49 @@ async function InsertVendorRecord(oauthClient, qbo_realmId, req, bill) {
|
|||||||
|
|
||||||
async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop) {
|
async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop) {
|
||||||
const { accounts, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req, bill.job.shopid);
|
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]) {
|
||||||
generateBillLine(
|
acc[cost_center] = { ...il, actual_cost: 0, quantity: 1 };
|
||||||
il,
|
}
|
||||||
accounts,
|
|
||||||
bill.job.class,
|
|
||||||
bodyshop.md_responsibility_centers.sales_tax_codes,
|
|
||||||
classes,
|
|
||||||
taxCodes,
|
|
||||||
bodyshop.md_responsibility_centers.costs,
|
|
||||||
bodyshop.accountingconfig,
|
|
||||||
bodyshop.region_config
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
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
|
//QB USA with GST
|
||||||
//This was required for the No. 1 Collision Group.
|
//This was required for the No. 1 Collision Group.
|
||||||
if (
|
if (
|
||||||
@@ -241,7 +269,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop)
|
|||||||
Amount: Dinero({
|
Amount: Dinero({
|
||||||
amount: Math.round(
|
amount: Math.round(
|
||||||
bill.billlines.reduce((acc, val) => {
|
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
|
}, 0) * 100
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -46,6 +46,28 @@ exports.default = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const generateBill = (bill, bodyshop) => {
|
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 = {
|
const billQbxmlObj = {
|
||||||
QBXML: {
|
QBXML: {
|
||||||
QBXMLMsgsRq: {
|
QBXMLMsgsRq: {
|
||||||
@@ -67,9 +89,7 @@ const generateBill = (bill, bodyshop) => {
|
|||||||
}),
|
}),
|
||||||
RefNumber: bill.invoice_number,
|
RefNumber: bill.invoice_number,
|
||||||
Memo: `RO ${bill.job.ro_number || ""}`,
|
Memo: `RO ${bill.job.ro_number || ""}`,
|
||||||
ExpenseLineAdd: bill.billlines.map((il) =>
|
ExpenseLineAdd: lines
|
||||||
generateBillLine(il, bodyshop.md_responsibility_centers, bill.job.class)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user