Successful 2tier and 3 tier export of invoices. BOD-83 BOD-131

This commit is contained in:
Patrick Fic
2020-06-02 09:19:46 -07:00
parent 5564b5dc4a
commit 73040064d4
16 changed files with 265 additions and 112 deletions

View File

@@ -68,7 +68,7 @@ export default connect(
try {
const response2 = await axios.post(
"http://localhost:1337/qb/receivables",
"http://e9c5a8ed9079.ngrok.io/qb/receivables",
response.data,
{
headers: {

View File

@@ -19,6 +19,7 @@ export function JobsCloseLabmatAllocationButton({
allocation,
setAllocations,
bodyshop,
invoiced
}) {
const [visible, setVisible] = useState(false);
const [state, setState] = useState({ center: "", amount: 0 });
@@ -87,7 +88,7 @@ export function JobsCloseLabmatAllocationButton({
<Button
onClick={handleAllocate}
disabled={
state.amount === 0 || state.center === "" || remainingAmount === 0
state.amount === 0 || state.center === "" || remainingAmount === 0 || invoiced
}
>
{t("jobs.actions.allocate")}
@@ -95,9 +96,9 @@ export function JobsCloseLabmatAllocationButton({
</div>
<div>
{visible ? (
<CloseCircleFilled onClick={() => setVisible(false)} />
<CloseCircleFilled onClick={() => setVisible(false)} disabled={invoiced} />
) : (
<PlusCircleFilled onClick={() => setVisible(true)} />
<PlusCircleFilled onClick={() => setVisible(true)} disabled={invoiced}/>
)}
</div>
</div>

View File

@@ -4,14 +4,15 @@ export default function JobsCloseLabMatAllocationTags({
allocationKey,
allocation,
setAllocations,
invoiced,
}) {
return (
<div>
{allocation.allocations.map((a, idx) => (
<Tag
closable
closable={!invoiced} //Value is whether it is invoiced.
visible
color='green'
color="green"
onClose={() => {
setAllocations((state) => {
return {

View File

@@ -14,6 +14,7 @@ export function JobsCloseAutoAllocate({
setLabmatAllocations,
partsAllocations,
setPartsAllocations,
invoiced
}) {
const { t } = useTranslation();
const handleAllocate = () => {
@@ -62,6 +63,6 @@ export function JobsCloseAutoAllocate({
});
};
return <Button onClick={handleAllocate}>{t("jobs.actions.autoallocate")}</Button>;
return <Button onClick={handleAllocate} disabled={invoiced}>{t("jobs.actions.autoallocate")}</Button>;
}
export default connect(mapStateToProps, null)(JobsCloseAutoAllocate);

View File

@@ -0,0 +1,43 @@
import { Button } from "antd";
import axios from "axios";
import React from "react";
import { useTranslation } from "react-i18next";
import { auth } from "../../firebase/firebase.utils";
export default function JobsCloseExportButton({ jobId, disabled }) {
const { t } = useTranslation();
const handleQbxml = async () => {
const response = await axios.post(
"/accounting/qbxml/receivables",
{ jobId: jobId },
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken(true)}`,
},
}
);
console.log("handle -> XML", response);
try {
const response2 = await axios.post(
"http://e9c5a8ed9079.ngrok.io/qb/receivables",
response.data,
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken(true)}`,
},
}
);
console.log("handle -> result", response2);
} catch (error) {
console.log("error", error, JSON.stringify(error));
}
};
return (
<Button onClick={handleQbxml} disabled={disabled} type="dashed">
{t("jobs.actions.export")}
</Button>
);
}

View File

@@ -8,6 +8,7 @@ export default function JobCloseLabMatAllocation({
labmatAllocations,
setLabmatAllocations,
labMatTotalAllocation,
invoiced
}) {
const { t } = useTranslation();
@@ -50,6 +51,7 @@ export default function JobCloseLabMatAllocation({
<td>
<AllocationButton
allocationKey={alloc}
invoiced={invoiced}
remainingAmount={labmatAllocations[alloc].total
.subtract(
Dinero({
@@ -69,6 +71,7 @@ export default function JobCloseLabMatAllocation({
<td>
<AllocationTags
allocationKey={alloc}
invoiced={invoiced}
allocation={labmatAllocations[alloc]}
setAllocations={setLabmatAllocations}
/>

View File

@@ -8,6 +8,7 @@ export default function JobsClosePartsAllocation({
partsAllocations,
setPartsAllocations,
partsAllocatedTotal,
invoiced,
}) {
const { t } = useTranslation();
@@ -50,6 +51,7 @@ export default function JobsClosePartsAllocation({
<td>
<AllocationButton
allocationKey={alloc}
invoiced={invoiced}
remainingAmount={partsAllocations[alloc].total
.subtract(
Dinero({
@@ -68,6 +70,7 @@ export default function JobsClosePartsAllocation({
</td>
<td>
<AllocationTags
invoiced={invoiced}
allocationKey={alloc}
allocation={partsAllocations[alloc]}
setAllocations={setPartsAllocations}

View File

@@ -18,6 +18,8 @@ export function JobsCloseSaveButton({
jobTotals,
labMatAllocations,
partsAllocations,
setInvoicedState,
disabled,
}) {
const [loading, setLoading] = useState(false);
const { t } = useTranslation();
@@ -38,9 +40,23 @@ export function JobsCloseSaveButton({
},
},
},
optimisticResponse: {
update_jobs: {
returning: {
id: jobId,
date_invoiced: new Date(),
status: bodyshop.md_ro_statuses.default_invoiced || "Invoiced*",
invoice_allocation: {
labMatAllocations,
partsAllocations,
},
},
},
},
});
if (!!!result.errors) {
notification["success"]({ message: t("jobs.successes.invoiced") });
setInvoicedState(true);
} else {
notification["error"]({
message: t("jobs.errors.invoicing", {
@@ -50,14 +66,14 @@ export function JobsCloseSaveButton({
}
setLoading(false);
};
return (
<Button
onClick={handleSave}
disabled={suspenseAmount > 0}
disabled={suspenseAmount > 0 || disabled}
loading={loading}
>
{t("general.actions.close")}
{t("general.actions.save")}
</Button>
);
}

View File

@@ -755,11 +755,6 @@ export const QUERY_ALL_JOBS_PAGINATED = gql`
export const QUERY_JOB_CLOSE_DETAILS = gql`
query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
jobs_by_pk(id: $id) {
po_number
special_coverage_policy
scheduled_delivery
converted
est_number
ro_number
clm_total
inproduction
@@ -769,26 +764,12 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
v_model_desc
v_make_desc
v_color
invoice_allocation
ins_co_id
policy_no
loss_date
clm_no
area_of_damage
ins_co_nm
ins_addr1
ins_city
ins_ct_ln
ins_ct_fn
ins_ea
ins_ph1
est_co_nm
est_ct_fn
est_ct_ln
pay_date
est_ph1
est_ea
regie_number
scheduled_completion
id
ded_amt
ded_status
@@ -819,20 +800,6 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
ownr_zip
ownr_ctry
ownr_ph1
owner {
id
ownr_fn
ownr_ln
ownr_ea
ownr_addr1
ownr_addr2
ownr_city
ownr_st
ownr_zip
ownr_ctry
ownr_ph1
}
labor_rate_desc
rate_atp
rate_la1
rate_la2
@@ -857,18 +824,10 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
rate_mapa
rate_mash
rate_matd
actual_completion
scheduled_delivery
actual_delivery
date_invoiced
date_closed
date_exported
status
status
owner_owing
joblines {
id
unq_seq
line_ind
tax_part
line_desc
prt_dsmk_p
@@ -885,7 +844,6 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
lbr_amt
op_code_desc
}
cieca_ttl
}
}
`;

View File

@@ -8,33 +8,76 @@ import Dinero from "dinero.js";
import JobsCloseTotals from "../../components/jobs-close-totals/jobs-close-totals.component";
import JobsCloseAutoAllocate from "../../components/jobs-close-auto-allocate/jobs-close-auto-allocate.component";
import JobsCloseSaveButton from "../../components/jobs-close-save-button/jobs-close-save-button.component";
import JobsCloseExportButton from "../../components/jobs-close-export-button/jobs-close-export-button.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsCloseComponent({ job, bodyshop, jobTotals }) {
const [invoiced, setInvoiced] = useState(!!job.invoice_allocation);
const [labmatAllocations, setLabmatAllocations] = useState(
Object.keys(jobTotals.rates).reduce((acc, val) => {
acc[val] = jobTotals.rates[val];
if (val.includes("subtotal")) return acc;
//Not a subtotal - therefore can be allocated.
acc[val].allocations = [];
return acc;
}, {})
!!job.invoice_allocation && !!job.invoice_allocation.labMatAllocations
? Object.keys(job.invoice_allocation.labMatAllocations).reduce(
(acc, val) => {
if (val.includes("subtotal")) {
acc[val] = Dinero(job.invoice_allocation.labMatAllocations[val]);
} else {
acc[val] = {
...job.invoice_allocation.labMatAllocations[val],
total: Dinero(
job.invoice_allocation.labMatAllocations[val].total
),
allocations: job.invoice_allocation.labMatAllocations[
val
].allocations.map((item) => {
return { ...item, amount: Dinero(item.amount) };
}),
};
}
return acc;
},
{}
)
: Object.keys(jobTotals.rates).reduce((acc, val) => {
acc[val] = jobTotals.rates[val];
if (val.includes("subtotal")) return acc;
//Not a subtotal - therefore can be allocated.
acc[val].allocations = [];
return acc;
}, {})
);
const [partsAllocations, setPartsAllocations] = useState({
...Object.keys(jobTotals.parts.parts.list).reduce((acc, val) => {
acc[val] = { ...jobTotals.parts.parts.list[val], allocations: [] };
const [partsAllocations, setPartsAllocations] = useState(
!!job.invoice_allocation && !!job.invoice_allocation.partsAllocations
? Object.keys(job.invoice_allocation.partsAllocations).reduce(
(acc, val) => {
acc[val] = {
...job.invoice_allocation.partsAllocations[val],
total: Dinero(job.invoice_allocation.partsAllocations[val].total),
allocations: job.invoice_allocation.partsAllocations[
val
].allocations.map((item) => {
return { ...item, amount: Dinero(item.amount) };
}),
};
return acc;
},
{}
)
: {
...Object.keys(jobTotals.parts.parts.list).reduce((acc, val) => {
acc[val] = { ...jobTotals.parts.parts.list[val], allocations: [] };
return acc;
}, {}),
pas: {
...jobTotals.parts.sublets,
allocations: [],
},
});
return acc;
}, {}),
pas: {
...jobTotals.parts.sublets,
allocations: [],
},
}
);
const labmatAllocatedTotalsArray = Object.keys(labmatAllocations)
.filter((i) => !i.includes("subtotal"))
@@ -61,6 +104,8 @@ export function JobsCloseComponent({ job, bodyshop, jobTotals }) {
<div>
<JobsCloseSaveButton
jobId={job.id}
invoiced={invoiced}
setInvoicedState={setInvoiced}
partsAllocations={partsAllocations}
labMatAllocations={labmatAllocations}
jobTotals={jobTotals}
@@ -69,6 +114,7 @@ export function JobsCloseComponent({ job, bodyshop, jobTotals }) {
.subtract(partsAllocatedTotal)
.getAmount()}
/>
<JobsCloseExportButton jobId={job.id} disabled={!invoiced} />
<JobsCloseTotals
jobTotals={jobTotals}
labMatTotal={labmatAllocatedTotal}
@@ -79,16 +125,19 @@ export function JobsCloseComponent({ job, bodyshop, jobTotals }) {
setLabmatAllocations={setLabmatAllocations}
partsAllocations={partsAllocations}
setPartsAllocations={setPartsAllocations}
invoiced={invoiced}
/>
<JobsCloseLaborMaterialAllocation
labmatAllocations={labmatAllocations}
setLabmatAllocations={setLabmatAllocations}
labMatTotalAllocation={labmatAllocatedTotal}
invoiced={invoiced}
/>
<JobsClosePartsAllocation
partsAllocations={partsAllocations}
setPartsAllocations={setPartsAllocations}
partsAllocatedTotal={partsAllocatedTotal}
invoiced={invoiced}
/>
</div>
);

View File

@@ -500,6 +500,7 @@
"autoallocate": "Auto Allocate",
"changestatus": "Change Status",
"convert": "Convert",
"export": "Export",
"gotojob": "Go to Job",
"manualnew": "Create New Job Manually",
"postInvoices": "Post Invoices",

View File

@@ -500,6 +500,7 @@
"autoallocate": "",
"changestatus": "Cambiar Estado",
"convert": "Convertir",
"export": "",
"gotojob": "",
"manualnew": "",
"postInvoices": "Contabilizar facturas",

View File

@@ -500,6 +500,7 @@
"autoallocate": "",
"changestatus": "Changer le statut",
"convert": "Convertir",
"export": "",
"gotojob": "",
"manualnew": "",
"postInvoices": "Poster des factures",