From 88951da11d7d3ae4d68f7cae39f312ac516560e7 Mon Sep 17 00:00:00 2001
From: Patrick Fic <>
Date: Thu, 1 Oct 2020 09:21:22 -0700
Subject: [PATCH] Started refactoring parts order reconciliation BOD-406
---
client/src/App/App.styles.scss | 2 +-
...b-reconciliation-bills-table.component.jsx | 40 +++-----
.../job-reconciliation-modal.component.jsx | 17 +++-
.../job-reconciliation.modal.container.jsx | 3 +-
...b-reconciliation-parts-table.component.jsx | 99 ++++++-------------
.../job-reconciliation-totals.component.jsx | 52 ++++++++++
client/src/graphql/bills.queries.js | 2 +-
7 files changed, 117 insertions(+), 98 deletions(-)
create mode 100644 client/src/components/job-reconciliation-totals/job-reconciliation-totals.component.jsx
diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss
index e4e62f8d0..ae71f13fa 100644
--- a/client/src/App/App.styles.scss
+++ b/client/src/App/App.styles.scss
@@ -68,5 +68,5 @@
.ant-table-cell {
// background-color: red;
- padding: 0.2rem !important;
+ //padding: 0.2rem !important;
}
diff --git a/client/src/components/job-reconciliation-bills-table/job-reconciliation-bills-table.component.jsx b/client/src/components/job-reconciliation-bills-table/job-reconciliation-bills-table.component.jsx
index 71320353e..f028cb87b 100644
--- a/client/src/components/job-reconciliation-bills-table/job-reconciliation-bills-table.component.jsx
+++ b/client/src/components/job-reconciliation-bills-table/job-reconciliation-bills-table.component.jsx
@@ -1,5 +1,4 @@
-import { Checkbox, Statistic, Table } from "antd";
-import Dinero from "dinero.js";
+import { Checkbox, Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -16,7 +15,6 @@ export default function JobReconciliationBillsTable({
});
const [selectedLines, setSelectedLines] = billLineState;
- const [total, setTotal] = useState(Dinero({ amount: 0 }).toFormat());
const columns = [
{
@@ -27,6 +25,15 @@ export default function JobReconciliationBillsTable({
sortOrder:
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
},
+ {
+ title: t("billlines.labels.from"),
+ dataIndex: "from",
+ key: "from",
+ render: (text, record) =>
+ `${record.bill.vendor && record.bill.vendor.name} / ${
+ record.bill.invoice_number
+ }`,
+ },
{
title: t("billlines.fields.retail"),
dataIndex: "actual_price",
@@ -61,11 +68,13 @@ export default function JobReconciliationBillsTable({
title: t("bills.fields.is_credit_memo"),
dataIndex: "is_credit_memo",
key: "is_credit_memo",
- sorter: (a, b) => a.is_credit_memo - b.is_credit_memo,
+ sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
sortOrder:
state.sortedInfo.columnKey === "is_credit_memo" &&
state.sortedInfo.order,
- render: (text, record) => ,
+ render: (text, record) => (
+
+ ),
},
];
@@ -74,30 +83,14 @@ export default function JobReconciliationBillsTable({
};
const handleOnRowClick = (selectedRecordKeys, selectedRecords) => {
setSelectedLines(selectedRecordKeys);
- calculateTotal(selectedRecords);
- };
-
- const calculateTotal = (selectedRecords) => {
- let total = Dinero({ amount: 0 });
- selectedRecords.forEach(
- (record) =>
- (total = total.add(
- Dinero({
- amount:
- record.actual_price * 100 * (record.is_credit_memo ? -1 : 1),
- }).multiply(record.quantity)
- ))
- );
-
- setTotal(total.toFormat());
};
return (
}
- pagination={{ position: "top", defaultPageSize: 25 }}
+ pagination={false}
+ scroll={{ y: "40vh", x: true }}
columns={columns}
rowKey="id"
dataSource={invoiceLineData}
@@ -107,7 +100,6 @@ export default function JobReconciliationBillsTable({
selectedRowKeys: selectedLines,
}}
/>
-
);
}
diff --git a/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx b/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx
index 0f358e0a5..1ca03da2c 100644
--- a/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx
+++ b/client/src/components/job-reconciliation-modal/job-reconciliation-modal.component.jsx
@@ -2,6 +2,7 @@ import { Col, Row } from "antd";
import React, { useState } from "react";
import JobReconciliationBillsTable from "../job-reconciliation-bills-table/job-reconciliation-bills-table.component";
import JobReconciliationPartsTable from "../job-reconciliation-parts-table/job-reconciliation-parts-table.component";
+import JobReconciliationTotals from "../job-reconciliation-totals/job-reconciliation-totals.component";
export default function JobReconciliationModalComponent({ job, bills }) {
const jobLineState = useState([]);
@@ -11,16 +12,18 @@ export default function JobReconciliationModalComponent({ job, bills }) {
bills
.map((i) =>
i.billlines.map((il) => {
- return { ...il, is_credit_memo: i.is_credit_memo };
+ return { ...il, bill: i };
})
)
.flat() || [];
- const jobLineData = job.joblines.filter((j) => j.part_type !== null);
+ const jobLineData = job.joblines.filter(
+ (j) => j.part_type !== null && j.part_type !== "PAE"
+ );
return (
-
+
+
+
+
);
}
diff --git a/client/src/components/job-reconciliation-modal/job-reconciliation.modal.container.jsx b/client/src/components/job-reconciliation-modal/job-reconciliation.modal.container.jsx
index 085c55d2b..cd45c8722 100644
--- a/client/src/components/job-reconciliation-modal/job-reconciliation.modal.container.jsx
+++ b/client/src/components/job-reconciliation-modal/job-reconciliation.modal.container.jsx
@@ -31,9 +31,10 @@ function JobReconciliationModalContainer({
title={t("jobs.labels.reconciliationheader")}
width={"90%"}
visible={visible}
- okText={t("general.actions.save")}
+ okText={t("general.actions.close")}
onOk={handleCancel}
onCancel={handleCancel}
+ cancelButtonProps={{ display: "none" }}
destroyOnClose
>
diff --git a/client/src/components/job-reconciliation-parts-table/job-reconciliation-parts-table.component.jsx b/client/src/components/job-reconciliation-parts-table/job-reconciliation-parts-table.component.jsx
index a37862440..089dfe1d4 100644
--- a/client/src/components/job-reconciliation-parts-table/job-reconciliation-parts-table.component.jsx
+++ b/client/src/components/job-reconciliation-parts-table/job-reconciliation-parts-table.component.jsx
@@ -1,5 +1,4 @@
-import { Statistic, Table } from "antd";
-import Dinero from "dinero.js";
+import { Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -16,20 +15,8 @@ export default function JobReconcilitionPartsTable({
});
const [selectedLines, setSelectedLines] = jobLineState;
- const [total, setTotal] = useState(Dinero({ amount: 0 }).toFormat());
const columns = [
- // {
- // title: t("joblines.fields.line_no"),
- // dataIndex: "line_no",
- // key: "line_no",
- // sorter: (a, b) => a.line_no - b.line_no,
- // sortOrder:
- // state.sortedInfo.columnKey === "line_no" && state.sortedInfo.order,
- // //ellipsis: true,
- // editable: true,
- // width: 75,
- // },
{
title: t("joblines.fields.line_desc"),
dataIndex: "line_desc",
@@ -38,32 +25,32 @@ export default function JobReconcilitionPartsTable({
sortOrder:
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
},
- {
- title: t("joblines.fields.oem_partno"),
- dataIndex: "oem_partno",
- key: "oem_partno",
- sorter: (a, b) =>
- alphaSort(
- a.oem_partno ? a.oem_partno : a.op_code_desc,
- b.oem_partno ? b.oem_partno : b.op_code_desc
- ),
- sortOrder:
- state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
+ // {
+ // title: t("joblines.fields.oem_partno"),
+ // dataIndex: "oem_partno",
+ // key: "oem_partno",
+ // sorter: (a, b) =>
+ // alphaSort(
+ // a.oem_partno ? a.oem_partno : a.op_code_desc,
+ // b.oem_partno ? b.oem_partno : b.op_code_desc
+ // ),
+ // sortOrder:
+ // state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
- render: (text, record) => (
-
- {record.oem_partno ? record.oem_partno : record.op_code_desc}
-
- ),
- },
- {
- title: t("joblines.fields.part_type"),
- dataIndex: "part_type",
- key: "part_type",
- sorter: (a, b) => alphaSort(a.part_type, b.part_type),
- sortOrder:
- state.sortedInfo.columnKey === "part_type" && state.sortedInfo.order,
- },
+ // render: (text, record) => (
+ //
+ // {record.oem_partno ? record.oem_partno : record.op_code_desc}
+ //
+ // ),
+ // },
+ // {
+ // title: t("joblines.fields.part_type"),
+ // dataIndex: "part_type",
+ // key: "part_type",
+ // sorter: (a, b) => alphaSort(a.part_type, b.part_type),
+ // sortOrder:
+ // state.sortedInfo.columnKey === "part_type" && state.sortedInfo.order,
+ // },
{
title: t("joblines.fields.act_price"),
dataIndex: "act_price",
@@ -95,14 +82,7 @@ export default function JobReconcilitionPartsTable({
),
},
- {
- title: t("joblines.fields.mod_lb_hrs"),
- dataIndex: "mod_lb_hrs",
- key: "mod_lb_hrs",
- sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs,
- sortOrder:
- state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order,
- },
+
{
title: t("joblines.fields.status"),
dataIndex: "status",
@@ -118,32 +98,16 @@ export default function JobReconcilitionPartsTable({
};
const handleOnRowClick = (selectedRecordKeys, selectedRecords) => {
setSelectedLines(selectedRecordKeys);
- calculateTotal(selectedRecords);
- };
-
- const calculateTotal = (selectedRecords) => {
- let total = Dinero({ amount: 0 });
- selectedRecords.forEach(
- (record) =>
- (total = total.add(
- Dinero({ amount: record.act_price * 100 }).multiply(record.part_qty)
- ))
- );
-
- setTotal(total.toFormat());
};
return (
(
-
-
- )}
- pagination={{ position: "top", defaultPageSize: 25 }}
+ size="small"
+ pagination={false}
columns={columns}
- rowKey='id'
+ scroll={{ y: "40vh", x: true }}
+ rowKey="id"
dataSource={jobLineData}
onChange={handleTableChange}
rowSelection={{
@@ -151,7 +115,6 @@ export default function JobReconcilitionPartsTable({
selectedRowKeys: selectedLines,
}}
/>
-
);
}
diff --git a/client/src/components/job-reconciliation-totals/job-reconciliation-totals.component.jsx b/client/src/components/job-reconciliation-totals/job-reconciliation-totals.component.jsx
new file mode 100644
index 000000000..adf49953a
--- /dev/null
+++ b/client/src/components/job-reconciliation-totals/job-reconciliation-totals.component.jsx
@@ -0,0 +1,52 @@
+import React, { useMemo } from "react";
+import Dinero from "dinero.js";
+import _ from "lodash";
+import { Space, Statistic } from "antd";
+import { useTranslation } from "react-i18next";
+
+export default function JobReconciliationTotals({
+ billLines,
+ jobLines,
+ selectedBillLines,
+ selectedJobLines,
+}) {
+ const { t } = useTranslation();
+
+ const totals = useMemo(() => {
+ const jlLookup = _.keyBy(selectedJobLines, (i) => i);
+ const billLookup = _.keyBy(selectedBillLines, (i) => i);
+
+ return {
+ joblinesTotal: jobLines
+ .filter((jl) => !!jlLookup[jl.id])
+ .reduce((acc, val) => {
+ console.log("acc :>> ", val);
+ return acc.add(
+ Dinero({ amount: val.act_price * 100 }).multiply(val.part_qty || 1)
+ );
+ }, Dinero()),
+ billLinesTotal: billLines
+ .filter((bl) => !!billLookup[bl.id])
+ .reduce((acc, val) => {
+ return acc.add(
+ Dinero({ amount: val.actual_price * 100 }).multiply(
+ val.quantity || 1
+ )
+ );
+ }, Dinero()),
+ };
+ }, [billLines, jobLines, selectedBillLines, selectedJobLines]);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/client/src/graphql/bills.queries.js b/client/src/graphql/bills.queries.js
index 73f689816..dbd16e0bf 100644
--- a/client/src/graphql/bills.queries.js
+++ b/client/src/graphql/bills.queries.js
@@ -70,7 +70,6 @@ export const QUERY_BILLS_BY_JOBID = gql`
}
order_date
deliver_by
- exported
parts_order_lines {
id
act_price
@@ -105,6 +104,7 @@ export const QUERY_BILLS_BY_JOBID = gql`
state_tax_rate
local_tax_rate
is_credit_memo
+ exported
billlines {
actual_price
quantity