- Merge client update into test-beta

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-01-18 19:20:08 -05:00
696 changed files with 92291 additions and 107075 deletions

View File

@@ -1,135 +1,136 @@
import { Form, Input, Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import {Form, Input, Table} from "antd";
import React, {useState} from "react";
import {useTranslation} from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { alphaSort } from "../../utils/sorters";
import {alphaSort} from "../../utils/sorters";
import BillFormItemsExtendedFormItem from "./bill-form-lines.extended.formitem.component";
export default function BillFormLinesExtended({
lineData,
discount,
form,
responsibilityCenters,
disabled,
}) {
const [search, setSearch] = useState("");
const { t } = useTranslation();
const columns = [
{
title: t("joblines.fields.line_desc"),
dataIndex: "line_desc",
key: "line_desc",
width: "10%",
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
},
{
title: t("joblines.fields.oem_partno"),
dataIndex: "oem_partno",
key: "oem_partno",
width: "10%",
sorter: (a, b) => alphaSort(a.oem_partno, b.oem_partno),
},
{
title: t("joblines.fields.part_type"),
dataIndex: "part_type",
key: "part_type",
width: "10%",
filters: [
lineData,
discount,
form,
responsibilityCenters,
disabled,
}) {
const [search, setSearch] = useState("");
const {t} = useTranslation();
const columns = [
{
text: t("jobs.labels.partsfilter"),
value: ["PAN", "PAP", "PAL", "PAA", "PAS", "PASL"],
title: t("joblines.fields.line_desc"),
dataIndex: "line_desc",
key: "line_desc",
width: "10%",
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
},
{
text: t("joblines.fields.part_types.PAN"),
value: ["PAN", "PAP"],
title: t("joblines.fields.oem_partno"),
dataIndex: "oem_partno",
key: "oem_partno",
width: "10%",
sorter: (a, b) => alphaSort(a.oem_partno, b.oem_partno),
},
{
text: t("joblines.fields.part_types.PAL"),
value: ["PAL"],
title: t("joblines.fields.part_type"),
dataIndex: "part_type",
key: "part_type",
width: "10%",
filters: [
{
text: t("jobs.labels.partsfilter"),
value: ["PAN", "PAP", "PAL", "PAA", "PAS", "PASL"],
},
{
text: t("joblines.fields.part_types.PAN"),
value: ["PAN", "PAP"],
},
{
text: t("joblines.fields.part_types.PAL"),
value: ["PAL"],
},
{
text: t("joblines.fields.part_types.PAA"),
value: ["PAA"],
},
{
text: t("joblines.fields.part_types.PAS"),
value: ["PAS", "PASL"],
},
],
onFilter: (value, record) => value.includes(record.part_type),
render: (text, record) =>
record.part_type
? t(`joblines.fields.part_types.${record.part_type}`)
: null,
},
{
text: t("joblines.fields.part_types.PAA"),
value: ["PAA"],
},
{
text: t("joblines.fields.part_types.PAS"),
value: ["PAS", "PASL"],
},
],
onFilter: (value, record) => value.includes(record.part_type),
render: (text, record) =>
record.part_type
? t(`joblines.fields.part_types.${record.part_type}`)
: null,
},
{
title: t("joblines.fields.act_price"),
dataIndex: "act_price",
key: "act_price",
width: "10%",
sorter: (a, b) => a.act_price - b.act_price,
shouldCellUpdate: false,
render: (text, record) => (
<>
<CurrencyFormatter>
{record.db_ref === "900510" || record.db_ref === "900511"
? record.prt_dsmk_m
: record.act_price}
</CurrencyFormatter>
{record.part_qty ? `(x ${record.part_qty})` : null}
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
<span
style={{ marginLeft: ".2rem" }}
>{`(${record.prt_dsmk_p}%)`}</span>
) : (
<></>
)}
</>
),
},
{
title: t("billlines.fields.posting"),
dataIndex: "posting",
key: "posting",
{
title: t("joblines.fields.act_price"),
dataIndex: "act_price",
key: "act_price",
width: "10%",
sorter: (a, b) => a.act_price - b.act_price,
shouldCellUpdate: false,
render: (text, record) => (
<>
<CurrencyFormatter>
{record.db_ref === "900510" || record.db_ref === "900511"
? record.prt_dsmk_m
: record.act_price}
</CurrencyFormatter>
{record.part_qty ? `(x ${record.part_qty})` : null}
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
<span
style={{marginLeft: ".2rem"}}
>{`(${record.prt_dsmk_p}%)`}</span>
) : (
<></>
)}
</>
),
},
{
title: t("billlines.fields.posting"),
dataIndex: "posting",
key: "posting",
render: (text, record, index) => (
<Form.Item noStyle name={["billlineskeys", record.id]}>
<BillFormItemsExtendedFormItem
form={form}
record={record}
index={index}
responsibilityCenters={responsibilityCenters}
discount={discount}
/>
render: (text, record, index) => (
<Form.Item noStyle name={["billlineskeys", record.id]}>
<BillFormItemsExtendedFormItem
form={form}
record={record}
index={index}
responsibilityCenters={responsibilityCenters}
discount={discount}
/>
</Form.Item>
),
},
];
const data =
search === ""
? lineData
: lineData.filter(
(l) =>
(l.line_desc &&
l.line_desc.toLowerCase().includes(search.toLowerCase())) ||
(l.oem_partno &&
l.oem_partno.toLowerCase().includes(search.toLowerCase())) ||
(l.act_price &&
l.act_price.toString().startsWith(search.toString()))
);
return (
<Form.Item noStyle name="billlineskeys">
<button onClick={() => console.log(form.getFieldsValue())}>form</button>
<Input onChange={(e) => setSearch(e.target.value)} allowClear/>
<Table
pagination={false}
size="small"
columns={columns}
rowKey="id"
dataSource={data}
/>
</Form.Item>
),
},
];
const data =
search === ""
? lineData
: lineData.filter(
(l) =>
(l.line_desc &&
l.line_desc.toLowerCase().includes(search.toLowerCase())) ||
(l.oem_partno &&
l.oem_partno.toLowerCase().includes(search.toLowerCase())) ||
(l.act_price &&
l.act_price.toString().startsWith(search.toString()))
);
return (
<Form.Item noStyle name="billlineskeys">
<button onClick={() => console.log(form.getFieldsValue())}>form</button>
<Input onChange={(e) => setSearch(e.target.value)} allowClear />
<Table
pagination={false}
size="small"
columns={columns}
rowKey="id"
dataSource={data}
/>
</Form.Item>
);
);
}

View File

@@ -1,288 +1,284 @@
import React from "react";
import {
PlusCircleFilled,
MinusCircleFilled,
WarningOutlined,
} from "@ant-design/icons";
import { Form, Button, InputNumber, Input, Select, Switch, Space } from "antd";
import { useTranslation } from "react-i18next";
import {MinusCircleFilled, PlusCircleFilled, WarningOutlined,} from "@ant-design/icons";
import {Button, Form, Input, InputNumber, Select, Space, Switch} from "antd";
import {useTranslation} from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {selectBodyshop} from "../../redux/user/user.selectors";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import CiecaSelect from "../../utils/Ciecaselect";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
mapStateToProps,
mapDispatchToProps
)(BillFormItemsExtendedFormItem);
export function BillFormItemsExtendedFormItem({
value,
bodyshop,
form,
record,
index,
disabled,
responsibilityCenters,
discount,
}) {
// const { billlineskeys } = form.getFieldsValue("billlineskeys");
value,
bodyshop,
form,
record,
index,
disabled,
responsibilityCenters,
discount,
}) {
// const { billlineskeys } = form.getFieldsValue("billlineskeys");
const {t} = useTranslation();
if (!value)
return (
<Button
onClick={() => {
const values = form.getFieldsValue("billlineskeys");
form.setFieldsValue({
...values,
billlineskeys: {
...(values.billlineskeys || {}),
[record.id]: {
joblineid: record.id,
line_desc: record.line_desc,
quantity: record.part_qty || 1,
actual_price: record.act_price,
cost_center: record.part_type
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
? record.part_type
: responsibilityCenters.defaults &&
(responsibilityCenters.defaults.costs[record.part_type] ||
null)
: null,
},
},
});
}}
>
<PlusCircleFilled/>
</Button>
);
const { t } = useTranslation();
if (!value)
return (
<Button
onClick={() => {
const values = form.getFieldsValue("billlineskeys");
<Space wrap>
<Form.Item
label={t("billlines.fields.line_desc")}
name={["billlineskeys", record.id, "line_desc"]}
>
<Input disabled={disabled}/>
</Form.Item>
<Form.Item
label={t("billlines.fields.quantity")}
name={["billlineskeys", record.id, "quantity"]}
>
<InputNumber precision={0} min={0} disabled={disabled}/>
</Form.Item>
<Form.Item
label={t("billlines.fields.actual_price")}
name={["billlineskeys", record.id, "actual_price"]}
>
<CurrencyInput
min={0}
disabled={disabled}
onBlur={(e) => {
const {billlineskeys} = form.getFieldsValue("billlineskeys");
form.setFieldsValue({
billlineskeys: {
...billlineskeys,
[record.id]: {
...billlineskeys[billlineskeys],
actual_cost: !!billlineskeys[billlineskeys].actual_cost
? billlineskeys[billlineskeys].actual_cost
: Math.round(
(parseFloat(e.target.value) * (1 - discount) +
Number.EPSILON) *
100
) / 100,
},
},
});
}}
/>
</Form.Item>
<Form.Item
label={t("billlines.fields.actual_cost")}
name={["billlineskeys", record.id, "actual_cost"]}
>
<CurrencyInput min={0} disabled={disabled}/>
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const line = value;
if (!!!line) return null;
const lineDiscount = (
1 -
Math.round((line.actual_cost / line.actual_price) * 100) / 100
).toPrecision(2);
form.setFieldsValue({
...values,
billlineskeys: {
...(values.billlineskeys || {}),
[record.id]: {
joblineid: record.id,
line_desc: record.line_desc,
quantity: record.part_qty || 1,
actual_price: record.act_price,
cost_center: record.part_type
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
? record.part_type
: responsibilityCenters.defaults &&
(responsibilityCenters.defaults.costs[record.part_type] ||
null)
: null,
},
},
});
}}
>
<PlusCircleFilled />
</Button>
if (lineDiscount - discount === 0) return <div/>;
return <WarningOutlined style={{color: "red"}}/>;
}}
</Form.Item>
<Form.Item
label={t("billlines.fields.cost_center")}
name={["billlineskeys", record.id, "cost_center"]}
>
<Select showSearch style={{minWidth: "3rem"}} disabled={disabled}>
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
? CiecaSelect(true, false)
: responsibilityCenters.costs.map((item) => (
<Select.Option key={item.name}>{item.name}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("billlines.fields.location")}
name={["billlineskeys", record.id, "location"]}
>
<Select disabled={disabled}>
{bodyshop.md_parts_locations.map((loc, idx) => (
<Select.Option key={idx} value={loc}>
{loc}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("billlines.fields.deductedfromlbr")}
name={["billlineskeys", record.id, "deductedfromlbr"]}
valuePropName="checked"
>
<Switch disabled={disabled}/>
</Form.Item>
<Form.Item shouldUpdate style={{display: "inline-block"}}>
{() => {
if (
form.getFieldsValue("billlineskeys").billlineskeys[record.id]
.deductedfromlbr
)
return (
<div>
<Form.Item
label={t("joblines.fields.mod_lbr_ty")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={[
"billlineskeys",
record.id,
"lbr_adjustment",
"mod_lbr_ty",
]}
>
<Select allowClear>
<Select.Option value="LAA">
{t("joblines.fields.lbr_types.LAA")}
</Select.Option>
<Select.Option value="LAB">
{t("joblines.fields.lbr_types.LAB")}
</Select.Option>
<Select.Option value="LAD">
{t("joblines.fields.lbr_types.LAD")}
</Select.Option>
<Select.Option value="LAE">
{t("joblines.fields.lbr_types.LAE")}
</Select.Option>
<Select.Option value="LAF">
{t("joblines.fields.lbr_types.LAF")}
</Select.Option>
<Select.Option value="LAG">
{t("joblines.fields.lbr_types.LAG")}
</Select.Option>
<Select.Option value="LAM">
{t("joblines.fields.lbr_types.LAM")}
</Select.Option>
<Select.Option value="LAR">
{t("joblines.fields.lbr_types.LAR")}
</Select.Option>
<Select.Option value="LAS">
{t("joblines.fields.lbr_types.LAS")}
</Select.Option>
<Select.Option value="LAU">
{t("joblines.fields.lbr_types.LAU")}
</Select.Option>
<Select.Option value="LA1">
{t("joblines.fields.lbr_types.LA1")}
</Select.Option>
<Select.Option value="LA2">
{t("joblines.fields.lbr_types.LA2")}
</Select.Option>
<Select.Option value="LA3">
{t("joblines.fields.lbr_types.LA3")}
</Select.Option>
<Select.Option value="LA4">
{t("joblines.fields.lbr_types.LA4")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item
label={t("jobs.labels.adjustmentrate")}
name={["billlineskeys", record.id, "lbr_adjustment", "rate"]}
initialValue={bodyshop.default_adjustment_rate}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<InputNumber precision={2} min={0.01}/>
</Form.Item>
</div>
);
return <></>;
}}
</Form.Item>
<Form.Item
label={t("billlines.fields.federal_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "federal"]}
valuePropName="checked"
>
<Switch disabled={disabled}/>
</Form.Item>
<Form.Item
label={t("billlines.fields.state_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "state"]}
valuePropName="checked"
>
<Switch disabled={disabled}/>
</Form.Item>
<Form.Item
label={t("billlines.fields.local_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "local"]}
valuePropName="checked"
>
<Switch disabled={disabled}/>
</Form.Item>
<Button
onClick={() => {
const values = form.getFieldsValue("billlineskeys");
form.setFieldsValue({
...values,
billlineskeys: {
...(values.billlineskeys || {}),
[record.id]: null,
},
});
}}
>
<MinusCircleFilled/>
</Button>
</Space>
);
return (
<Space wrap>
<Form.Item
label={t("billlines.fields.line_desc")}
name={["billlineskeys", record.id, "line_desc"]}
>
<Input disabled={disabled} />
</Form.Item>
<Form.Item
label={t("billlines.fields.quantity")}
name={["billlineskeys", record.id, "quantity"]}
>
<InputNumber precision={0} min={0} disabled={disabled} />
</Form.Item>
<Form.Item
label={t("billlines.fields.actual_price")}
name={["billlineskeys", record.id, "actual_price"]}
>
<CurrencyInput
min={0}
disabled={disabled}
onBlur={(e) => {
const { billlineskeys } = form.getFieldsValue("billlineskeys");
form.setFieldsValue({
billlineskeys: {
...billlineskeys,
[record.id]: {
...billlineskeys[billlineskeys],
actual_cost: !!billlineskeys[billlineskeys].actual_cost
? billlineskeys[billlineskeys].actual_cost
: Math.round(
(parseFloat(e.target.value) * (1 - discount) +
Number.EPSILON) *
100
) / 100,
},
},
});
}}
/>
</Form.Item>
<Form.Item
label={t("billlines.fields.actual_cost")}
name={["billlineskeys", record.id, "actual_cost"]}
>
<CurrencyInput min={0} disabled={disabled} />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const line = value;
if (!!!line) return null;
const lineDiscount = (
1 -
Math.round((line.actual_cost / line.actual_price) * 100) / 100
).toPrecision(2);
if (lineDiscount - discount === 0) return <div />;
return <WarningOutlined style={{ color: "red" }} />;
}}
</Form.Item>
<Form.Item
label={t("billlines.fields.cost_center")}
name={["billlineskeys", record.id, "cost_center"]}
>
<Select showSearch style={{ minWidth: "3rem" }} disabled={disabled}>
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
? CiecaSelect(true, false)
: responsibilityCenters.costs.map((item) => (
<Select.Option key={item.name}>{item.name}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("billlines.fields.location")}
name={["billlineskeys", record.id, "location"]}
>
<Select disabled={disabled}>
{bodyshop.md_parts_locations.map((loc, idx) => (
<Select.Option key={idx} value={loc}>
{loc}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("billlines.fields.deductedfromlbr")}
name={["billlineskeys", record.id, "deductedfromlbr"]}
valuePropName="checked"
>
<Switch disabled={disabled} />
</Form.Item>
<Form.Item shouldUpdate style={{ display: "inline-block" }}>
{() => {
if (
form.getFieldsValue("billlineskeys").billlineskeys[record.id]
.deductedfromlbr
)
return (
<div>
<Form.Item
label={t("joblines.fields.mod_lbr_ty")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={[
"billlineskeys",
record.id,
"lbr_adjustment",
"mod_lbr_ty",
]}
>
<Select allowClear>
<Select.Option value="LAA">
{t("joblines.fields.lbr_types.LAA")}
</Select.Option>
<Select.Option value="LAB">
{t("joblines.fields.lbr_types.LAB")}
</Select.Option>
<Select.Option value="LAD">
{t("joblines.fields.lbr_types.LAD")}
</Select.Option>
<Select.Option value="LAE">
{t("joblines.fields.lbr_types.LAE")}
</Select.Option>
<Select.Option value="LAF">
{t("joblines.fields.lbr_types.LAF")}
</Select.Option>
<Select.Option value="LAG">
{t("joblines.fields.lbr_types.LAG")}
</Select.Option>
<Select.Option value="LAM">
{t("joblines.fields.lbr_types.LAM")}
</Select.Option>
<Select.Option value="LAR">
{t("joblines.fields.lbr_types.LAR")}
</Select.Option>
<Select.Option value="LAS">
{t("joblines.fields.lbr_types.LAS")}
</Select.Option>
<Select.Option value="LAU">
{t("joblines.fields.lbr_types.LAU")}
</Select.Option>
<Select.Option value="LA1">
{t("joblines.fields.lbr_types.LA1")}
</Select.Option>
<Select.Option value="LA2">
{t("joblines.fields.lbr_types.LA2")}
</Select.Option>
<Select.Option value="LA3">
{t("joblines.fields.lbr_types.LA3")}
</Select.Option>
<Select.Option value="LA4">
{t("joblines.fields.lbr_types.LA4")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item
label={t("jobs.labels.adjustmentrate")}
name={["billlineskeys", record.id, "lbr_adjustment", "rate"]}
initialValue={bodyshop.default_adjustment_rate}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<InputNumber precision={2} min={0.01} />
</Form.Item>
</div>
);
return <></>;
}}
</Form.Item>
<Form.Item
label={t("billlines.fields.federal_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "federal"]}
valuePropName="checked"
>
<Switch disabled={disabled} />
</Form.Item>
<Form.Item
label={t("billlines.fields.state_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "state"]}
valuePropName="checked"
>
<Switch disabled={disabled} />
</Form.Item>
<Form.Item
label={t("billlines.fields.local_tax_applicable")}
name={["billlineskeys", record.id, "applicable_taxes", "local"]}
valuePropName="checked"
>
<Switch disabled={disabled} />
</Form.Item>
<Button
onClick={() => {
const values = form.getFieldsValue("billlineskeys");
form.setFieldsValue({
...values,
billlineskeys: {
...(values.billlineskeys || {}),
[record.id]: null,
},
});
}}
>
<MinusCircleFilled />
</Button>
</Space>
);
}