Added parts backorder + receiving for orders BOD-159
This commit is contained in:
@@ -8,6 +8,8 @@ import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import queryString from "query-string";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setPartsOrderContext: (context) =>
|
||||
@@ -22,7 +24,6 @@ export function InvoicesListTableComponent({
|
||||
job,
|
||||
loading,
|
||||
invoicesQuery,
|
||||
selectedInvoice,
|
||||
handleOnRowClick,
|
||||
setPartsOrderContext,
|
||||
setInvoiceEnterContext,
|
||||
@@ -32,6 +33,8 @@ export function InvoicesListTableComponent({
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
});
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const selectedInvoice = search.invoiceid;
|
||||
|
||||
const invoices = invoicesQuery.data ? invoicesQuery.data.invoices : [];
|
||||
const { refetch } = invoicesQuery;
|
||||
@@ -91,7 +94,8 @@ export function InvoicesListTableComponent({
|
||||
render: (text, record) => (
|
||||
<div>
|
||||
<Link
|
||||
to={`/manage/invoices?invoiceid=${record.id}&vendorid=${record.vendorid}`}>
|
||||
to={`/manage/invoices?invoiceid=${record.id}&vendorid=${record.vendorid}`}
|
||||
>
|
||||
<Button>{t("invoices.actions.edit")}</Button>
|
||||
</Link>
|
||||
<Button
|
||||
@@ -116,7 +120,8 @@ export function InvoicesListTableComponent({
|
||||
isReturn: true,
|
||||
},
|
||||
})
|
||||
}>
|
||||
}
|
||||
>
|
||||
{t("invoices.actions.return")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -232,11 +237,11 @@ export function InvoicesListTableComponent({
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<Table
|
||||
size='small'
|
||||
size="small"
|
||||
scroll={{ x: "50%", y: "40rem" }}
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
columns={columns}
|
||||
rowKey='id'
|
||||
rowKey="id"
|
||||
dataSource={record.invoicelines}
|
||||
/>
|
||||
</div>
|
||||
@@ -246,9 +251,9 @@ export function InvoicesListTableComponent({
|
||||
return (
|
||||
<Table
|
||||
loading={loading}
|
||||
size='small'
|
||||
size="small"
|
||||
title={() => (
|
||||
<div className='imex-table-header'>
|
||||
<div className="imex-table-header">
|
||||
<Button onClick={() => refetch()}>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
@@ -260,7 +265,8 @@ export function InvoicesListTableComponent({
|
||||
job,
|
||||
},
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("jobs.actions.postInvoices")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -273,10 +279,11 @@ export function InvoicesListTableComponent({
|
||||
(invoicesQuery.data && invoicesQuery.data.invoices) || [],
|
||||
},
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("jobs.actions.reconcile")}
|
||||
</Button>{" "}
|
||||
<div className='imex-table-header__search'>
|
||||
<div className="imex-table-header__search">
|
||||
<Input.Search
|
||||
placeholder={t("general.labels.search")}
|
||||
onChange={(e) => {
|
||||
@@ -290,7 +297,7 @@ export function InvoicesListTableComponent({
|
||||
expandedRowRender={rowExpander}
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
columns={columns}
|
||||
rowKey='id'
|
||||
rowKey="id"
|
||||
dataSource={invoices}
|
||||
onChange={handleTableChange}
|
||||
expandable={{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Dropdown, Input, Menu, Table } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -11,6 +12,8 @@ import AllocationsAssignmentContainer from "../allocations-assignment/allocation
|
||||
import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
|
||||
import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
|
||||
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
||||
import queryString from "query-string";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setJobLineEditContext: (context) =>
|
||||
@@ -35,6 +38,9 @@ export function JobLinesComponent({
|
||||
});
|
||||
const { t } = useTranslation();
|
||||
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "#",
|
||||
@@ -213,7 +219,8 @@ export function JobLinesComponent({
|
||||
actions: { refetch: refetch },
|
||||
context: record,
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("general.actions.edit")}
|
||||
</Button>
|
||||
<AllocationsAssignmentContainer
|
||||
@@ -237,9 +244,9 @@ export function JobLinesComponent({
|
||||
|
||||
const markMenu = (
|
||||
<Menu onClick={handleMark}>
|
||||
<Menu.Item key='PAA'>PAA</Menu.Item>
|
||||
<Menu.Item key='PAN'>PAN</Menu.Item>
|
||||
<Menu.Item key='PAL'>PAL</Menu.Item>
|
||||
<Menu.Item key="PAA">PAA</Menu.Item>
|
||||
<Menu.Item key="PAN">PAN</Menu.Item>
|
||||
<Menu.Item key="PAL">PAL</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@@ -248,16 +255,19 @@ export function JobLinesComponent({
|
||||
<PartsOrderModalContainer />
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey='id'
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
size='small'
|
||||
size="small"
|
||||
pagination={{ position: "top", defaultPageSize: 50 }}
|
||||
dataSource={jobLines}
|
||||
onChange={handleTableChange}
|
||||
scroll={{ x: true, y: "40rem" }}
|
||||
title={() => {
|
||||
return (
|
||||
<div className='imex-table-header'>
|
||||
<div className="imex-table-header">
|
||||
<Button onClick={() => refetch()}>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
<Button
|
||||
disabled={selectedLines.length > 0 ? false : true}
|
||||
onClick={() => {
|
||||
@@ -268,7 +278,8 @@ export function JobLinesComponent({
|
||||
linesToOrder: selectedLines,
|
||||
},
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("parts.actions.order")}
|
||||
</Button>
|
||||
<Dropdown overlay={markMenu} trigger={["click"]}>
|
||||
@@ -284,10 +295,11 @@ export function JobLinesComponent({
|
||||
actions: { refetch: refetch },
|
||||
context: { jobid: jobId },
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("joblines.actions.new")}
|
||||
</Button>
|
||||
<div className='imex-table-header__search'>
|
||||
<div className="imex-table-header__search">
|
||||
<Input.Search
|
||||
placeholder={t("general.labels.search")}
|
||||
onChange={(e) => {
|
||||
@@ -300,11 +312,16 @@ export function JobLinesComponent({
|
||||
);
|
||||
}}
|
||||
expandedRowRender={(record) => (
|
||||
<div style={{ margin: 0 }}>
|
||||
<div>
|
||||
<strong>{t("parts_orders.labels.orderhistory")}</strong>
|
||||
{record.parts_order_lines.map((item) => (
|
||||
<div key={item.id}>
|
||||
{`${item.parts_order.order_number || ""} from `}
|
||||
<Link
|
||||
to={`/manage/jobs/${jobId}?tab=partssublet&partsorderid=${item.parts_order.id}`}
|
||||
>
|
||||
{item.parts_order.order_number || ""}
|
||||
</Link>
|
||||
-
|
||||
<Link to={`/manage/shop/vendors/${item.parts_order.vendor.id}`}>
|
||||
{item.parts_order.vendor.name || ""}
|
||||
</Link>
|
||||
|
||||
@@ -44,7 +44,8 @@ export function JobsCloseExportButton({ bodyshop, jobId, disabled }) {
|
||||
let PartnerResponse;
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://localhost:1337/qb/",
|
||||
"http://b47e67f9cbe3.ngrok.io/qb/",
|
||||
QbXmlResponse.data,
|
||||
{
|
||||
headers: {
|
||||
|
||||
@@ -21,6 +21,8 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
dispatch(setModalContext({ context: context, modal: "schedule" })),
|
||||
setInvoiceEnterContext: (context) =>
|
||||
dispatch(setModalContext({ context: context, modal: "invoiceEnter" })),
|
||||
setPaymentContext: (context) =>
|
||||
dispatch(setModalContext({ context: context, modal: "payment" })),
|
||||
});
|
||||
|
||||
export function JobsDetailHeaderActions({
|
||||
@@ -29,12 +31,13 @@ export function JobsDetailHeaderActions({
|
||||
refetch,
|
||||
setScheduleContext,
|
||||
setInvoiceEnterContext,
|
||||
setPaymentContext,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const client = useApolloClient();
|
||||
const history = useHistory();
|
||||
const statusmenu = (
|
||||
<Menu key='popovermenu'>
|
||||
<Menu key="popovermenu">
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setScheduleContext({
|
||||
@@ -44,30 +47,43 @@ export function JobsDetailHeaderActions({
|
||||
job: job,
|
||||
},
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("jobs.actions.schedule")}
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key='cccontract'>
|
||||
<Menu.Item
|
||||
key="enterpayments"
|
||||
onClick={() => {
|
||||
setPaymentContext({
|
||||
actions: {},
|
||||
context: { jobId: job.id },
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("menus.header.enterpayment")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key="cccontract">
|
||||
<Link
|
||||
to={{
|
||||
pathname: "/manage/courtesycars/contracts/new",
|
||||
state: { jobId: job.id },
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("menus.jobsactions.newcccontract")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key='addtoproduction'
|
||||
key="addtoproduction"
|
||||
disabled={!!!job.converted || !!job.inproduction}
|
||||
onClick={() => AddToProduction(client, job.id, refetch)}>
|
||||
onClick={() => AddToProduction(client, job.id, refetch)}
|
||||
>
|
||||
{t("jobs.actions.addtoproduction")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key='duplicatejob'>
|
||||
<Menu.Item key="duplicatejob">
|
||||
<Popconfirm
|
||||
title={t("jobs.labels.duplicateconfirm")}
|
||||
okText='Yes'
|
||||
cancelText='No'
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onConfirm={() =>
|
||||
DuplicateJob(
|
||||
@@ -79,12 +95,13 @@ export function JobsDetailHeaderActions({
|
||||
}
|
||||
)
|
||||
}
|
||||
getPopupContainer={(trigger) => trigger.parentNode}>
|
||||
getPopupContainer={(trigger) => trigger.parentNode}
|
||||
>
|
||||
{t("menus.jobsactions.duplicate")}
|
||||
</Popconfirm>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key='postinvoices'
|
||||
key="postinvoices"
|
||||
onClick={() => {
|
||||
setInvoiceEnterContext({
|
||||
actions: { refetch: refetch },
|
||||
@@ -92,14 +109,16 @@ export function JobsDetailHeaderActions({
|
||||
job: job,
|
||||
},
|
||||
});
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("jobs.actions.postInvoices")}
|
||||
</Menu.Item>
|
||||
<Menu.Item key='closejob'>
|
||||
<Menu.Item key="closejob">
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/manage/jobs/${job.id}/close`,
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t("menus.jobsactions.closejob")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
@@ -108,10 +127,11 @@ export function JobsDetailHeaderActions({
|
||||
);
|
||||
return (
|
||||
<Dropdown
|
||||
className='imex-flex-row__margin'
|
||||
className="imex-flex-row__margin"
|
||||
overlay={statusmenu}
|
||||
trigger={["click"]}
|
||||
key='changestatus'>
|
||||
key="changestatus"
|
||||
>
|
||||
<Button>
|
||||
{t("general.labels.actions")} <DownCircleFilled />
|
||||
</Button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import AlertComponent from "../alert/alert.component";
|
||||
import InvoicesListTableComponent from "../invoices-list-table/invoices-list-table.component";
|
||||
import JobInvoicesTotalsComponent from "../job-invoices-total/job-invoices-total.component";
|
||||
import PartsOrderModal from "../parts-order-modal/parts-order-modal.container";
|
||||
import { PartsOrderListTableComponent } from "../parts-order-list-table/parts-order-list-table.component";
|
||||
const tableCol = {
|
||||
xs: {
|
||||
span: 24,
|
||||
@@ -25,22 +26,29 @@ const totalsCol = {
|
||||
export default function JobsDetailPliComponent({
|
||||
job,
|
||||
invoicesQuery,
|
||||
handleOnRowClick,
|
||||
handleInvoiceOnRowClick,
|
||||
handlePartsOrderOnRowClick,
|
||||
selectedInvoice,
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<PartsOrderModal />
|
||||
{invoicesQuery.error ? (
|
||||
<AlertComponent message={invoicesQuery.error.message} type='error' />
|
||||
<AlertComponent message={invoicesQuery.error.message} type="error" />
|
||||
) : null}
|
||||
<Row>
|
||||
<Col {...tableCol}>
|
||||
<PartsOrderListTableComponent
|
||||
job={job}
|
||||
loading={invoicesQuery.loading}
|
||||
handleOnRowClick={handlePartsOrderOnRowClick}
|
||||
selectedInvoice={selectedInvoice}
|
||||
invoicesQuery={invoicesQuery}
|
||||
/>
|
||||
<InvoicesListTableComponent
|
||||
job={job}
|
||||
loading={invoicesQuery.loading}
|
||||
handleOnRowClick={handleOnRowClick}
|
||||
selectedInvoice={selectedInvoice}
|
||||
handleOnRowClick={handleInvoiceOnRowClick}
|
||||
invoicesQuery={invoicesQuery}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function JobsDetailPliContainer({ job }) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
|
||||
const handleOnRowClick = (record) => {
|
||||
const handleInvoiceOnRowClick = (record) => {
|
||||
if (record) {
|
||||
if (record.id) {
|
||||
search.invoiceid = record.id;
|
||||
@@ -25,12 +25,24 @@ export default function JobsDetailPliContainer({ job }) {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePartsOrderOnRowClick = (record) => {
|
||||
if (record) {
|
||||
if (record.id) {
|
||||
search.partsorderid = record.id;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}
|
||||
} else {
|
||||
delete search.partsorderid;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<JobsDetailPliComponent
|
||||
job={job}
|
||||
invoicesQuery={invoicesQuery}
|
||||
handleOnRowClick={handleOnRowClick}
|
||||
selectedInvoice={search.invoiceid}
|
||||
handleInvoiceOnRowClick={handleInvoiceOnRowClick}
|
||||
handlePartsOrderOnRowClick={handlePartsOrderOnRowClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "antd";
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { MUTATION_BACKORDER_PART_LINE } from "../../graphql/parts-orders.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function PartsOrderLineBackorderButton({
|
||||
partsOrderStatus,
|
||||
partsLineId,
|
||||
jobLineId,
|
||||
bodyshop,
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [backorderLine] = useMutation(MUTATION_BACKORDER_PART_LINE);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const isAlreadyBackordered =
|
||||
bodyshop.md_order_statuses.default_bo === partsOrderStatus;
|
||||
|
||||
const handleOnClick = async () => {
|
||||
setLoading(true);
|
||||
|
||||
const result = await backorderLine({
|
||||
variables: {
|
||||
jobLineId,
|
||||
partsLineId,
|
||||
status: isAlreadyBackordered
|
||||
? bodyshop.md_order_statuses.default_received || "Received*"
|
||||
: bodyshop.md_order_statuses.default_bo || "Backordered*",
|
||||
},
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button loading={loading} onClick={handleOnClick}>
|
||||
{isAlreadyBackordered
|
||||
? t("parts_orders.actions.receive")
|
||||
: t("parts_orders.actions.backordered")}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(PartsOrderLineBackorderButton);
|
||||
@@ -0,0 +1,215 @@
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Input, Table } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function PartsOrderListTableComponent({
|
||||
job,
|
||||
loading,
|
||||
invoicesQuery,
|
||||
|
||||
handleOnRowClick,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
});
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const selectedpartsorder = search.partsorderid;
|
||||
|
||||
const parts_orders = invoicesQuery.data
|
||||
? invoicesQuery.data.parts_orders
|
||||
: [];
|
||||
const { refetch } = invoicesQuery;
|
||||
const columns = [
|
||||
{
|
||||
title: t("vendors.fields.name"),
|
||||
dataIndex: "vendorname",
|
||||
key: "vendorname",
|
||||
sorter: (a, b) => alphaSort(a.vendor.name, b.vendor.name),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "vendorname" && state.sortedInfo.order,
|
||||
render: (text, record) => <span>{record.vendor.name}</span>,
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.order_number"),
|
||||
dataIndex: "order_number",
|
||||
key: "order_number",
|
||||
sorter: (a, b) => alphaSort(a.invoice_number, b.invoice_number),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "invoice_number" &&
|
||||
state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.order_date"),
|
||||
dataIndex: "order_date",
|
||||
key: "order_date",
|
||||
sorter: (a, b) => a.order_date - b.order_date,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "order_date" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<DateFormatter>{record.order_date}</DateFormatter>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.deliver_by"),
|
||||
dataIndex: "deliver_by",
|
||||
key: "deliver_by",
|
||||
sorter: (a, b) => a.deliver_by - b.deliver_by,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "deliver_by" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<DateFormatter>{record.deliver_by}</DateFormatter>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
||||
};
|
||||
|
||||
const rowExpander = (record) => {
|
||||
const columns = [
|
||||
{
|
||||
title: t("parts_orders.fields.line_desc"),
|
||||
dataIndex: "line_desc",
|
||||
key: "line_desc",
|
||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.db_price"),
|
||||
dataIndex: "db_price",
|
||||
key: "db_price",
|
||||
sorter: (a, b) => a.db_price - b.db_price,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "db_price" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<CurrencyFormatter>{record.db_price}</CurrencyFormatter>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.act_price"),
|
||||
dataIndex: "act_price",
|
||||
key: "act_price",
|
||||
sorter: (a, b) => a.act_price - b.act_price,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
title: t("parts_orders.fields.oem_partno"),
|
||||
dataIndex: "oem_partno",
|
||||
key: "oem_partno",
|
||||
sorter: (a, b) => alphaSort(a.oem_partno, b.oem_partno),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.line_remarks"),
|
||||
dataIndex: "line_remarks",
|
||||
key: "line_remarks",
|
||||
},
|
||||
{
|
||||
title: t("parts_orders.fields.status"),
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
render: (text, record) => (
|
||||
<div>
|
||||
<PartsOrderLineBackorderButton
|
||||
partsOrderStatus={record.status}
|
||||
partsLineId={record.id}
|
||||
jobLineId={record.job_line_id}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
size="small"
|
||||
scroll={{ x: "50%", y: "40rem" }}
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={record.parts_order_lines}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Table
|
||||
loading={loading}
|
||||
size="small"
|
||||
title={() => (
|
||||
<div className="imex-table-header">
|
||||
<Button onClick={() => refetch()}>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
|
||||
<div className="imex-table-header__search">
|
||||
<Input.Search
|
||||
placeholder={t("general.labels.search")}
|
||||
onChange={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
scroll={{ x: "50%", y: "40rem" }}
|
||||
expandedRowRender={rowExpander}
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={parts_orders}
|
||||
onChange={handleTableChange}
|
||||
expandable={{
|
||||
expandedRowKeys: [selectedpartsorder],
|
||||
onExpand: (expanded, record) => {
|
||||
handleOnRowClick(expanded ? record : null);
|
||||
},
|
||||
}}
|
||||
rowSelection={{
|
||||
onSelect: (record) => {
|
||||
handleOnRowClick(record);
|
||||
},
|
||||
selectedRowKeys: [selectedpartsorder],
|
||||
type: "radio",
|
||||
}}
|
||||
onRow={(record, rowIndex) => {
|
||||
return {
|
||||
onClick: (event) => {
|
||||
handleOnRowClick(record);
|
||||
}, // click row
|
||||
onDoubleClick: (event) => {}, // double click row
|
||||
onContextMenu: (event) => {}, // right button click row
|
||||
onMouseEnter: (event) => {}, // mouse enter row
|
||||
onMouseLeave: (event) => {}, // mouse leave row
|
||||
};
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default connect(null, mapDispatchToProps)(PartsOrderListTableComponent);
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useElements, useStripe, CardElement } from "@stripe/react-stripe-js";
|
||||
import { Form, Modal, notification } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
@@ -37,6 +37,7 @@ function InvoiceEnterModalContainer({
|
||||
const elements = useElements();
|
||||
const { t } = useTranslation();
|
||||
const { context, actions, visible } = paymentModal;
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const stripeStateArr = useState({
|
||||
error: null,
|
||||
@@ -118,6 +119,10 @@ function InvoiceEnterModalContainer({
|
||||
toggleModalVisible();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) form.resetFields();
|
||||
}, [visible, form]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t("payments.labels.new")}
|
||||
|
||||
@@ -36,11 +36,6 @@ export function ProductionBoardKanbanComponent({ data, bodyshop }) {
|
||||
bodyshop.md_ro_statuses.production_statuses,
|
||||
]);
|
||||
|
||||
const findById = (id) => {
|
||||
return id;
|
||||
//return (data && data.find((x) => x.id === id).ro_number) || null;
|
||||
};
|
||||
|
||||
const client = useApolloClient();
|
||||
|
||||
const handleDragEnd = async (card, source, destination) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { Button, Form, Input, InputNumber, Select, Row, Col } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { Button, Col, Form, Input, InputNumber, Row } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
//TODO Fix up styles.
|
||||
export default function ShopInfoSchedulingComponent({ form }) {
|
||||
|
||||
Reference in New Issue
Block a user