Merged in feature/IO-3499-React-19 (pull request #2834)

feature/IO-3499-React-19: Fix bill edit
This commit is contained in:
Dave Richer
2026-01-16 17:29:37 +00:00
2 changed files with 43 additions and 32 deletions

View File

@@ -56,7 +56,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
const handleSave = () => { const handleSave = () => {
//It's got a previously deducted bill line! //It's got a previously deducted bill line!
if ( if (
data.bills_by_pk.billlines.filter((b) => b.deductedfromlbr).length > 0 || data?.bills_by_pk?.billlines.filter((b) => b.deductedfromlbr).length > 0 ||
form.getFieldValue("billlines").filter((b) => b.deductedfromlbr).length > 0 form.getFieldValue("billlines").filter((b) => b.deductedfromlbr).length > 0
) )
setOpen(true); setOpen(true);
@@ -84,7 +84,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
//Find bill lines that were deleted. //Find bill lines that were deleted.
const deletedJobLines = []; const deletedJobLines = [];
data.bills_by_pk.billlines.forEach((a) => { data?.bills_by_pk?.billlines.forEach((a) => {
const matchingRecord = billlines.find((b) => b.id === a.id); const matchingRecord = billlines.find((b) => b.id === a.id);
if (!matchingRecord) { if (!matchingRecord) {
deletedJobLines.push(a); deletedJobLines.push(a);
@@ -151,8 +151,8 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
if (error) return <AlertComponent title={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>; if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>;
const exported = data?.bills_by_pk && data.bills_by_pk.exported; const exported = data?.bills_by_pk && data?.bills_by_pk?.exported;
const isinhouse = data?.bills_by_pk && data.bills_by_pk.isinhouse; const isinhouse = data?.bills_by_pk && data?.bills_by_pk?.isinhouse;
return ( return (
<> <>
@@ -160,7 +160,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
{data && ( {data && (
<> <>
<PageHeader <PageHeader
title={data && `${data.bills_by_pk.invoice_number} - ${data.bills_by_pk.vendor.name}`} title={data && `${data?.bills_by_pk?.invoice_number} - ${data?.bills_by_pk?.vendor?.name}`}
extra={ extra={
<Space> <Space>
<BillDetailEditReturn data={data} /> <BillDetailEditReturn data={data} />
@@ -192,15 +192,15 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
<Divider titlePlacement="left">{t("general.labels.media")}</Divider> <Divider titlePlacement="left">{t("general.labels.media")}</Divider>
{bodyshop.uselocalmediaserver ? ( {bodyshop.uselocalmediaserver ? (
<JobsDocumentsLocalGallery <JobsDocumentsLocalGallery
job={{ id: data ? data.bills_by_pk.jobid : null }} job={{ id: data ? data?.bills_by_pk?.jobid : null }}
invoice_number={data ? data.bills_by_pk.invoice_number : null} invoice_number={data ? data?.bills_by_pk?.invoice_number : null}
vendorid={data ? data.bills_by_pk.vendorid : null} vendorid={data ? data?.bills_by_pk?.vendorid : null}
/> />
) : ( ) : (
<JobDocumentsGallery <JobDocumentsGallery
jobId={data ? data.bills_by_pk.jobid : null} jobId={data ? data?.bills_by_pk?.jobid : null}
billId={search.billid} billId={search.billid}
documentsList={data ? data.bills_by_pk.documents : []} documentsList={data ? data?.bills_by_pk?.documents : []}
billsCallback={refetch} billsCallback={refetch}
/> />
)} )}
@@ -212,7 +212,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
} }
const transformData = (data) => { const transformData = (data) => {
return data return data?.bills_by_pk
? { ? {
...data.bills_by_pk, ...data.bills_by_pk,

View File

@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import { selectDarkMode } from "../../redux/application/application.selectors";
import CiecaSelect from "../../utils/Ciecaselect"; import CiecaSelect from "../../utils/Ciecaselect";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import InstanceRenderManager from "../../utils/instanceRenderMgr";
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component"; import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
@@ -14,7 +15,8 @@ import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
bodyshop: selectBodyshop bodyshop: selectBodyshop,
isDarkMode: selectDarkMode
}); });
const mapDispatchToProps = () => ({ const mapDispatchToProps = () => ({
//setUserLanguage: language => dispatch(setUserLanguage(language)) //setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -22,6 +24,7 @@ const mapDispatchToProps = () => ({
export function BillEnterModalLinesComponent({ export function BillEnterModalLinesComponent({
bodyshop, bodyshop,
isDarkMode,
disabled, disabled,
lineData, lineData,
discount, discount,
@@ -249,19 +252,26 @@ export function BillEnterModalLinesComponent({
}; };
}, },
formInput: (record, index) => ( formInput: (record, index) => (
<CurrencyInput <Space.Compact style={{ width: "100%" }}>
min={0} <CurrencyInput min={0} disabled={disabled} controls={false} style={{ width: "100%" }} />
disabled={disabled} <Form.Item shouldUpdate noStyle>
controls={false} {() => {
addonAfter={ const line = getFieldsValue(["billlines"]).billlines[index];
<Form.Item shouldUpdate noStyle> if (!line) return null;
{() => { let lineDiscount = 1 - line.actual_cost / line.actual_price;
const line = getFieldsValue(["billlines"]).billlines[index]; if (isNaN(lineDiscount)) lineDiscount = 0;
if (!line) return null; return (
let lineDiscount = 1 - line.actual_cost / line.actual_price; <Tooltip title={`${(lineDiscount * 100).toFixed(2) || 0}%`}>
if (isNaN(lineDiscount)) lineDiscount = 0; <div
return ( style={{
<Tooltip title={`${(lineDiscount * 100).toFixed(2) || 0}%`}> padding: "4px 11px",
display: "flex",
alignItems: "center",
background: isDarkMode ? "#141414" : "#fafafa",
border: isDarkMode ? "1px solid #424242" : "1px solid #d9d9d9",
borderLeft: 0
}}
>
<DollarCircleFilled <DollarCircleFilled
style={{ style={{
color: color:
@@ -272,12 +282,12 @@ export function BillEnterModalLinesComponent({
: "green" : "green"
}} }}
/> />
</Tooltip> </div>
); </Tooltip>
}} );
</Form.Item> }}
} </Form.Item>
/> </Space.Compact>
) )
// additional: (record, index) => ( // additional: (record, index) => (
// <Form.Item shouldUpdate> // <Form.Item shouldUpdate>
@@ -627,7 +637,8 @@ const EditableCell = ({
// DO NOT mutate rawProps; omit `key` immutably // DO NOT mutate rawProps; omit `key` immutably
const propsFinal = rawProps const propsFinal = rawProps
? (() => { ? (() => {
const { ...rest } = rawProps; // eslint-disable-next-line no-unused-vars
const { key, ...rest } = rawProps;
return rest; return rest;
})() })()
: undefined; : undefined;