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