Merge branch 'release/2021-10-29' into test

This commit is contained in:
Patrick Fic
2021-10-29 11:19:36 -07:00
6 changed files with 4255 additions and 5 deletions

View File

@@ -6,6 +6,7 @@ import {
Row, Row,
Select, Select,
Space, Space,
Statistic,
Switch, Switch,
Typography, Typography,
} from "antd"; } from "antd";
@@ -75,6 +76,12 @@ export function ScheduleJobModalComponent({
return ( return (
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col span={12}> <Col span={12}>
<Space>
<Typography.Title level={3}>{lbrHrsData?.jobs_by_pk?.ro_number}</Typography.Title>
<Typography.Title
level={4}
>{`B/R Hrs:${lbrHrsData?.jobs_by_pk.labhrs?.aggregate.sum.mod_lb_hrs}/${lbrHrsData?.jobs_by_pk.larhrs?.aggregate.sum.mod_lb_hrs}`}</Typography.Title>
</Space>
<LayoutFormRow grow> <LayoutFormRow grow>
<Form.Item <Form.Item
name="start" name="start"

View File

@@ -208,6 +208,7 @@ export const QUERY_LBR_HRS_BY_PK = gql`
query QUERY_LBR_HRS_BY_PK($id: uuid!) { query QUERY_LBR_HRS_BY_PK($id: uuid!) {
jobs_by_pk(id: $id) { jobs_by_pk(id: $id) {
id id
ro_number
labhrs: joblines_aggregate( labhrs: joblines_aggregate(
where: { where: {
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]

File diff suppressed because one or more lines are too long

View File

@@ -76,7 +76,7 @@ exports.default = function ({
{ {
local: false, local: false,
federal: true, federal: true,
state: jobline.tax_part, state: (jobline.db_ref === "900511" || jobline.db_ref === "900510") ? true: jobline.tax_part,
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );

View File

@@ -27,6 +27,7 @@ const {
} = require("../qbo/qbo-receivables"); } = require("../qbo/qbo-receivables");
const { urlBuilder } = require("./qbo"); const { urlBuilder } = require("./qbo");
const { DineroQbFormat } = require("../accounting-constants"); const { DineroQbFormat } = require("../accounting-constants");
const { findTaxCode } = require("../qb-receivables-lines");
exports.default = async (req, res) => { exports.default = async (req, res) => {
const oauthClient = new OAuthClient({ const oauthClient = new OAuthClient({
@@ -135,7 +136,17 @@ exports.default = async (req, res) => {
); );
} }
await InsertPayment(oauthClient, qbo_realmId, req, payment, jobTier); if (payment.amount > 0) {
await InsertPayment(oauthClient, qbo_realmId, req, payment, jobTier);
} else {
await InsertCreditMemo(
oauthClient,
qbo_realmId,
req,
payment,
jobTier
);
}
ret.push({ paymentid: payment.id, success: true }); ret.push({ paymentid: payment.id, success: true });
} catch (error) { } catch (error) {
logger.log("qbo-payment-create-error", "ERROR", req.user.email, { logger.log("qbo-payment-create-error", "ERROR", req.user.email, {
@@ -173,7 +184,8 @@ async function InsertPayment(
oauthClient, oauthClient,
qbo_realmId, qbo_realmId,
req, req,
payment.job.ro_number payment.job.ro_number,
false
); );
if (invoices && invoices.length !== 1) { if (invoices && invoices.length !== 1) {
@@ -235,7 +247,13 @@ async function InsertPayment(
throw error; throw error;
} }
} }
async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) { async function QueryMetaData(
oauthClient,
qbo_realmId,
req,
ro_number,
isCreditMemo
) {
const invoice = await oauthClient.makeApiCall({ const invoice = await oauthClient.makeApiCall({
url: urlBuilder( url: urlBuilder(
qbo_realmId, qbo_realmId,
@@ -288,8 +306,50 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) {
// classes.json.QueryResponse.Class.forEach((t) => { // classes.json.QueryResponse.Class.forEach((t) => {
// accountMapping[t.Name] = t.Id; // accountMapping[t.Name] = t.Id;
// }); // });
let ret = {};
if (isCreditMemo) {
const taxCodes = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From TaxCode`),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const items = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Item`),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
setNewRefreshToken(req.user.email, items);
const itemMapping = {};
items.json &&
items.json.QueryResponse &&
items.json.QueryResponse.Item &&
items.json.QueryResponse.Item.forEach((t) => {
itemMapping[t.Name] = t.Id;
});
const taxCodeMapping = {};
taxCodes.json &&
taxCodes.json.QueryResponse &&
taxCodes.json.QueryResponse.TaxCode &&
taxCodes.json.QueryResponse.TaxCode.forEach((t) => {
taxCodeMapping[t.Name] = t.Id;
});
ret = {
...ret,
items: itemMapping,
taxCodes: taxCodeMapping,
};
}
return { return {
...ret,
paymentMethods: paymentMethodMapping, paymentMethods: paymentMethodMapping,
invoices: invoices:
invoice.json && invoice.json &&
@@ -297,3 +357,85 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) {
invoice.json.QueryResponse.Invoice, invoice.json.QueryResponse.Invoice,
}; };
} }
async function InsertCreditMemo(
oauthClient,
qbo_realmId,
req,
payment,
parentRef
) {
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData(
oauthClient,
qbo_realmId,
req,
payment.job.ro_number,
true
);
if (invoices && invoices.length !== 1) {
throw new Error(
`More than 1 invoice with DocNumber ${payment.ro_number} found.`
);
}
const paymentQbo = {
CustomerRef: {
value: parentRef.Id,
},
TxnDate: moment(payment.date).format("YYYY-MM-DD"),
DocNumber: payment.paymentnum,
...(invoices[0] ? { InvoiceRef: { value: invoices[0].Id } } : {}),
Line: [
{
DetailType: "SalesItemLineDetail",
Amount: Dinero({ amount: Math.round(payment.amount * -100) }).toFormat(
DineroQbFormat
),
SalesItemLineDetail: {
ItemRef: {
value:
items[
payment.job.bodyshop.md_responsibility_centers.refund
.accountitem
],
},
Qty: 1,
TaxCodeRef: {
value:
taxCodes[
findTaxCode(
{
local: false,
federal: false,
state: false,
},
payment.job.bodyshop.md_responsibility_centers.sales_tax_codes
)
],
},
},
},
],
};
logger.log("qbo-payments-objectlog", "DEBUG", req.user.email, payment.id, {
paymentQbo,
});
try {
const result = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "creditmemo"),
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(paymentQbo),
});
setNewRefreshToken(req.user.email, result);
return result && result.Bill;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, payment.id, {
error: error && error.message,
method: "InsertCreditMemo",
});
throw error;
}
}

View File

@@ -152,7 +152,7 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
QBXML: { QBXML: {
QBXMLMsgsRq: { QBXMLMsgsRq: {
"@onError": "continueOnError", "@onError": "continueOnError",
CreditMemoAddRq: { wMemoAddRq: {
CreditMemoAdd: { CreditMemoAdd: {
CustomerRef: { CustomerRef: {
FullName: (payment.job.bodyshop.accountingconfig.tiers === 3 FullName: (payment.job.bodyshop.accountingconfig.tiers === 3