Merge branch 'release/2026-02-27' into feature/IO-3537-Bill-Entry-Scroll-to-Top-for-Errors
Signed-off-by: Allan Carr <allan@imexsystems.ca> # Conflicts: # client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
This commit is contained in:
@@ -6,6 +6,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { INSERT_NEW_BILL } from "../../graphql/bills.queries";
|
||||
import { UPDATE_INVENTORY_LINES } from "../../graphql/inventory.queries";
|
||||
@@ -21,12 +22,12 @@ import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import confirmDialog from "../../utils/asyncConfirm";
|
||||
import useLocalStorage from "../../utils/useLocalStorage";
|
||||
import BillEnterAiScan from "../bill-enter-ai-scan/bill-enter-ai-scan.component.jsx";
|
||||
import BillFormContainer from "../bill-form/bill-form.container";
|
||||
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
||||
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
|
||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||
import { handleUpload as handleUploadToImageProxy } from "../documents-upload-imgproxy/documents-upload-imgproxy.utility";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
billEnterModal: selectBillEnterModal,
|
||||
@@ -50,16 +51,20 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
const [updatePartsOrderLines] = useMutation(MUTATION_MARK_RETURN_RECEIVED);
|
||||
const [updateInventoryLines] = useMutation(UPDATE_INVENTORY_LINES);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [scanLoading, setScanLoading] = useState(false);
|
||||
const [isAiScan, setIsAiScan] = useState(false);
|
||||
const client = useApolloClient();
|
||||
const [generateLabel, setGenerateLabel] = useLocalStorage("enter_bill_generate_label", false);
|
||||
const notification = useNotification();
|
||||
const fileInputRef = useRef(null);
|
||||
const pollingIntervalRef = useRef(null);
|
||||
const formTopRef = useRef(null);
|
||||
|
||||
const {
|
||||
treatments: { Enhanced_Payroll, Imgproxy }
|
||||
treatments: { Enhanced_Payroll, Imgproxy, Bill_OCR_AI }
|
||||
} = useTreatmentsWithConfig({
|
||||
attributes: {},
|
||||
names: ["Enhanced_Payroll", "Imgproxy"],
|
||||
names: ["Enhanced_Payroll", "Imgproxy", "Bill_OCR_AI"],
|
||||
splitKey: bodyshop.imexshopid
|
||||
});
|
||||
|
||||
@@ -114,6 +119,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
create_ppc,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
original_actual_price,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
confidence,
|
||||
...restI
|
||||
} = i;
|
||||
|
||||
@@ -379,6 +386,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
vendorid: values.vendorid,
|
||||
billlines: []
|
||||
});
|
||||
setIsAiScan(false);
|
||||
// form.resetFields();
|
||||
} else {
|
||||
toggleModalVisible();
|
||||
@@ -389,10 +397,22 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
const handleCancel = () => {
|
||||
const r = window.confirm(t("general.labels.cancel"));
|
||||
if (r === true) {
|
||||
// Clean up polling on cancel
|
||||
if (pollingIntervalRef.current) {
|
||||
clearInterval(pollingIntervalRef.current);
|
||||
pollingIntervalRef.current = null;
|
||||
}
|
||||
setScanLoading(false);
|
||||
setIsAiScan(false);
|
||||
toggleModalVisible();
|
||||
}
|
||||
};
|
||||
|
||||
//Workaround needed to bypass react-compiler error about manipulating refs in child components. Refactor may be needed in the future to clean this up.
|
||||
const setPollingIntervalRef = (func) => {
|
||||
pollingIntervalRef.current = func;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (enterAgain) form.submit();
|
||||
}, [enterAgain, form]);
|
||||
@@ -402,12 +422,44 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
form.setFieldsValue(formValues);
|
||||
} else {
|
||||
form.resetFields();
|
||||
// Clean up polling on modal close
|
||||
if (pollingIntervalRef.current) {
|
||||
clearInterval(pollingIntervalRef.current);
|
||||
pollingIntervalRef.current = null;
|
||||
}
|
||||
setScanLoading(false);
|
||||
setIsAiScan(false);
|
||||
}
|
||||
}, [billEnterModal.open, form, formValues]);
|
||||
|
||||
// Cleanup on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (pollingIntervalRef.current) {
|
||||
clearInterval(pollingIntervalRef.current);
|
||||
pollingIntervalRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t("bills.labels.new")}
|
||||
title={
|
||||
<Space size="large">
|
||||
{t("bills.labels.new")}
|
||||
{Bill_OCR_AI.treatment === "on" && (
|
||||
<BillEnterAiScan
|
||||
fileInputRef={fileInputRef}
|
||||
form={form}
|
||||
pollingIntervalRef={pollingIntervalRef}
|
||||
setPollingIntervalRef={setPollingIntervalRef}
|
||||
scanLoading={scanLoading}
|
||||
setScanLoading={setScanLoading}
|
||||
setIsAiScan={setIsAiScan}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
}
|
||||
width={"98%"}
|
||||
open={billEnterModal.open}
|
||||
okText={t("general.actions.save")}
|
||||
@@ -460,7 +512,11 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
||||
>
|
||||
<div ref={formTopRef}>
|
||||
<RbacWrapper action="bills:enter">
|
||||
<BillFormContainer form={form} disableInvNumber={billEnterModal.context.disableInvNumber} />
|
||||
<BillFormContainer
|
||||
form={form}
|
||||
isAiScan={isAiScan}
|
||||
disableInvNumber={billEnterModal.context.disableInvNumber}
|
||||
/>
|
||||
</RbacWrapper>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
Reference in New Issue
Block a user