import React, { useState, useEffect, useRef, useContext, useCallback, useMemo, } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { ArrowRightOutlined, PlusCircleOutlined, SearchOutlined, } from '@ant-design/icons'; import { Form, Tooltip, Table, Input, AutoComplete, Switch, Checkbox } from 'antd'; import { IoAddCircleSharp } from 'react-icons/io5'; import { InputField } from '../../Components/Forms/InputField.jsx'; import Buttons from '../../Components/Forms/Buttons.jsx'; import { Modal } from 'antd'; import { Messages } from '../../Components/Notifications/Messages.jsx'; import { DeleteFilled } from '@ant-design/icons'; import { changeBreadCrumb } from '../../Features/AppPage/CenterPage.js'; import FormHeader from '../PageComponents/FormHeader.jsx'; import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx'; import { getSession, validateSafeInput } from '../../Services/Others.js'; import { DatePicProd } from '../../Components/Forms/DatePickerProduct.jsx'; import { RadioGrpButton } from '../../Components/Forms/RadioGroup.jsx'; import moment from 'moment'; import { DropDowns } from '../../Components/Forms/DropDown.jsx'; import { BsUpcScan } from 'react-icons/bs'; import { debounce } from 'lodash'; import { getProductData, getSupplierData, getPurchaseTypeData, getPurchaseTaxTypeData, postPurchaseData, putStockData, } from '../../Features/StockMaster/StockMaster.js'; import '../../Styles/Stock/StockMaster.scss'; import "../../Styles/OverAllStyle/OverAllStyle.scss" import { getAdmin, getUomData, getProdCatData, uomDataSelector, postSupplier, getProductTypeData, bulkpostdata, postFieldSetup, getFieldSetupData, } from '../../Features/ProductPage/ProductPage.js'; import SupplierProductMappingForm from '../SupplierProductMapping/SuplierProductMappingForm.jsx'; import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js'; import FloatLabel from '../../Components/Forms/FloatLabel/index.jsx'; import { FaLink, FaEye } from 'react-icons/fa'; import { TbUpload } from 'react-icons/tb'; import { getSupplaierIdBasedProducts, getSupplaierIdwithTypeBasedProducts, postSupplaierProducts, } from '../../Features/SupplierProductMapping/SupplierProductMapping.js'; import { ApplicationPreferences, getCommonAppPreference, } from '../../Features/BrachLogin/BranchLogin.js'; import { getConfigType, getPaymentOptionFeatureApi, PendingOrdersPE, } from '../../Features/BookingScreen/BookingData/BookingData.js'; import InvoiceImageExtractorModal from './InvoiceImageExtractor.jsx'; import { v4 as uuidv4 } from 'uuid'; import AddAllProductsButton from './AddAllProductGrid.jsx'; import SettingsIconWithModal from './SettingsIconWithModal.jsx'; import VirtualizedTable from './VirtualizedTable.jsx'; import { useDebounce } from './UseDebounce.jsx'; const subDirectory = import.meta.env.BASE_URL; const EditableContext = React.createContext(null); const EditableRow = ({ index, ...props }) => { const [form] = Form.useForm(); return (
); }; const EditableCell = ({ title, editable, children, dataIndex, record, handleSave, ...restProps }) => { const [editing, setEditing] = useState(false); const inputRef = useRef(null); const form = useContext(EditableContext); useEffect(() => { if (editing) { inputRef?.current?.focus(); } }, [editing]); const toggleEdit = () => { setEditing(!editing); form.setFieldsValue({ [dataIndex]: record[dataIndex], }); }; const save = async () => { try { const values = await form.validateFields(); toggleEdit(); handleSave({ ...record, ...values, }); } catch (errInfo) { console.log('Save failed:', errInfo); } }; let childNode = children; if (editable) { childNode = editing ? ( ) : (
); } return {childNode}; }; const StockForm = ({ formType }) => { console.log('counttesttttttttttttttttttt'); const formRef = useRef(null); const productAddInfoRef = useRef(null); const formProductRef = useRef(null); const formSupplierRef = useRef(null); const dispatch = useDispatch(); const navigate = useNavigate(); const location = useLocation(); const [form] = Form.useForm(); const [editingKey, setEditingKey] = useState(''); const [index, setindex] = useState(); const state = location?.state; const editstate = state?.editstate; const CompId = getSession('CompId'); const BranchId = getSession('BranchId'); const AppId = getSession('AppId'); const UserId = getSession('UserId'); const UomData = useSelector(uomDataSelector); const appPreferences = useSelector(ApplicationPreferences); const [applicationRestrictedFields, setApplicationRestrictedFields] = useState({ DatesAndExpiry: false, BatchAndModelDetails: false, AmountPerPieceDetail: false, }); const [editingQty, setEditingQty] = useState({}); const [selectedAdditionalColumn, setSelectedAdditionalColumn] = useState([]); const [tableFieldPreferences, setTableFieldPreferences] = useState([]); const [SupplierData, setSupplierData] = useState([]); const [SupplierOpen, setSupplierOpen] = useState('own'); const [purchaseOrderList, setPurchaseOrderList] = useState([]); const [selectedSupplierName, setSelectedSupplierName] = useState(); const [messageType, setMessageType] = useState(null); const [messageData, setMessageData] = useState(null); const [searchText, setSearchText] = useState(null); const [productSearchText, setProductSearchText] = useState(''); const [selectedInvoice, setSelectedInvoice] = useState(null); const [orderType, setOrderType] = useState(true); const [PurchaseTypeData, setPurchaseTypeData] = useState(null); const [SelectedPurchaseType, setSelectedPurchaseType] = useState(null); const [SelectedPurcTaxType, setSelectedPurcTaxType] = useState(null); const [PurchaseData, setPurchaseData] = useState([]); const [additionalInfoModal, setAdditionalInfoModal] = useState(false); const [selectedRowIndex, setSelectedRowIndex] = useState(null); const [selectedRowRecord, setSelectedRowRecord] = useState({}); const [purchaseOrderId, setPurchaseOrderId] = useState(); const [selectedProductName, setSelectedProductName] = useState(null); const [scanner, setScanner] = useState(false); const [Delete, setDelete] = useState(false); const [selectedSupplierData, setSelectedSupplierData] = useState(null); const [inwardDate, setInwardDate] = useState(new Date().toJSON()); const [SuppInvoiceDate, setSuppInvoiceDate] = useState(); const [invoiceType, setInvoiceType] = useState('I'); const [PurchaseDate, setPurchaseDate] = useState(); const [paymentAmount, setPaymentAmount] = useState(null); const [OpenSupplierModel, setOpenSupplierModel] = useState(false); const [zipCodeData, setZipCodeData] = useState(false); const [imeiSerialOpen, setimeiSerialOpen] = useState(false); const [dataSource, setDataSource] = useState([]); const [dataSourceBackup, setDataSourceBackup] = useState([]); const [purchaseStatus, setPurchaseStatus] = useState('P'); const [isModalOpen, setIsModalOpen] = useState(false); const [productData, setProductData] = useState([]); const [message, setMessage] = useState({ type: null, data: null }); const [initialLoad, setInitialLoad] = useState(true); const [deliveryPerformanceData, SetDeleveryPerformanceData] = useState([]); const [DiscountData, setDiscountData] = useState([]); const [QualityData, setQualityData] = useState([]); const [Delivery, setDeliveryValue] = useState(); const [DicountValue, setDicountValue] = useState(); const [QualityValue, setQualityValue] = useState(); const [ViewDtl, setViewDtl] = useState(false); const [paymentOptions, setPaymentOptions] = useState([]); const [selectedPaymentMode, setSelectedPaymentMode] = useState(null); const [payAmountDisable, setPayAmountDisable] = useState( paymentOptions ?.find((option) => option?.ModeId === selectedPaymentMode) ?.ModeName?.toLowerCase() === 'credit' ); const [extractorModalVisible, setExtractorModalVisible] = useState(false); const [extractorData, setExtractorData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [loadingText, setLoadingText] = useState(''); // const [filteredPurchaseData, setFilteredPurchaseData] = useState([]); const [searchValue, setSearchValue] = useState(''); const isSearching = Boolean(searchValue?.trim()); const [showAllSuppliers, setShowAllSuppliers] = useState(false); const SelInvoiceAmount = useMemo(() => { const total = PurchaseData?.reduce( (acc, item) => acc + Number(item?.Amount || 0), 0 ); return !isNaN(total) && total !== 0 ? total : null; }, [PurchaseData]); const TotalTaxAmount = useMemo(() => { return PurchaseData?.reduce( (acc, item) => acc + Number(item?.TaxAmt || 0), 0 ); }, [PurchaseData]); const filteredPurchaseData = useMemo(() => { if (!searchValue?.trim()) return PurchaseData; return PurchaseData.filter((item) => item?.ProdName?.toLowerCase().includes(searchValue.toLowerCase()) ); }, [PurchaseData, searchValue]); const items = [ { name: 'Home', link: `${subDirectory}app-page/home`, }, { name: 'Product Receipt', link: `${subDirectory}setting/purchase-entry`, }, { name: editstate ? 'Edit' : 'New', link: null, }, ]; const categoryId = appPreferences?.find( (p) => p?.PreferredCatName?.toLowerCase() === 'purchase entry' )?.PreferredCatId; useEffect(() => { dispatch(changeBreadCrumb({ items: items })); dispatch( getProductData({ CompId: CompId, AppId: AppId, BranchId: BranchId }) ).unwrap(); dispatch(getProductTypeData()); dispatch(getAdmin({ AppId: AppId, CompId: CompId })); dispatch(getProdCatData({ AppId: AppId })); dispatch(getUomData()); applicationApplicableFields(); getPurchaseType(); getPurchaseTaxType(); deliveryPerformance(); discountLevel(); qualityofSupp(); getSuplaierApi({ Type: null }); if (formType == 'add') { formRef.current?.setFieldsValue({ SuppInvoiceDate: new Date().toJSON() }); setSuppInvoiceDate(new Date().toJSON()); formRef.current?.setFieldsValue({ InvoiceDate: new Date().toJSON() }); // setInvoiceDate(new Date().toJSON()); formRef.current?.setFieldsValue({ DueDate: new Date().toJSON() }); setPurchaseDate(new Date().toJSON()); formRef.current?.setFieldsValue({ InvoiceDate: new Date().toJSON() }); formRef.current?.setFieldsValue({ OrderType: 'N' }); } if (formType == 'edit') { formRef.current?.setFieldsValue({ ProdId: editstate?.ProdId, ProdVariantName: editstate?.ProdVariantName, SuppId: editstate?.SuppId, InwardDate: editstate?.InwardDate + 'T00:00:00', }); if (applicationRestrictedFields.DatesAndExpiry) { formRef.current?.setFieldsValue({ ManufDate: editstate?.ManufDate, ExpDate: editstate?.ExpDate, }); } handleSupplierBasedProduct(editstate?.SuppId); // setSelectedProductData(editstate?.ProdId); setSelectedSupplierData(editstate?.SuppId); } }, []); useEffect(() => { if (SupplierOpen !== 'own') { getPurchaseOrders(); fetchPaymentOptions(); } }, [SupplierOpen]); useEffect(() => { getFieldSetup(); }, [categoryId]); useEffect(() => { if (initialLoad && SupplierData?.length > 0) { SetSelfSupplier(); setInitialLoad(false); } }, [SupplierData]); useEffect(() => { if (extractorData && selectedSupplierData) { if ( extractorData?.invoiceNo !== null && extractorData?.invoiceNo !== '' ) { formRef?.current?.setFieldsValue({ SuppInvoiceNo: extractorData?.invoiceNo, }); } formRef?.current?.setFieldsValue({ PaymentAmount: extractorData?.TotalAmtData, }); setPaymentAmount(extractorData?.TotalAmtData); onSuppInvoiceDateChange( extractorData?.date, extractorData?.date?.format('DD-MM-YYYY') || '' ); } }, [selectedSupplierData]); useEffect(() => { return () => { debouncedScannerSearch.cancel(); }; }, []); const SetSelfSupplier = async () => { let SupplierId = SupplierData?.filter( (item) => item.SuppName?.toLowerCase() === 'self' )?.[0]?.['SuppId']; let SupplierName = SupplierData?.filter( (item) => item.SuppName?.toLowerCase() === 'self' )?.[0]?.['SuppName']; formRef.current?.setFieldsValue({ CustSuppId: SupplierId }); setSelectedSupplierData(SupplierId); handleSupplierBasedProduct(SupplierId); SupplierName === 'Self' ? setSelectedSupplierName(false) : setSelectedSupplierName(true); }; const getSuplaierApi = async ({ dataReturn = false, Type = null }) => { const response = await dispatch( getPurchaseSupplierAndWareHouseData({ CompId, AppId, BranchId, Type }) ).unwrap(); if (response?.statusCode === 1) { setSupplierData(response?.data); if (dataReturn) { return response?.data; } } else { setSupplierData([]); if (dataReturn) { return []; } } }; const getPurchaseOrders = async () => { const { data: res } = await dispatch( PendingOrdersPE({ CompId, AppId, BranchId }) ).unwrap(); if (res?.statusCode === 1) { setPurchaseOrderList( res?.data?.PurchaseOrder?.map((item) => ({ ...item, localId: uuidv4(), })) ); } else { setPurchaseOrderList([]); setMessageType('error'); setMessageData('No pending purchase orders found.'); } }; const fetchPaymentOptions = async () => { try { const response = await dispatch( getPaymentOptionFeatureApi({ CompId, BranchId, AppId }) ).unwrap(); if (response?.data?.statusCode === 1) { const paymentDetails = response?.data?.data?.[0]?.PaymentDetails?.find( (item) => item.FlowName === 'Sales' )?.OptionDetails?.[0]?.ModeDetails?.filter( (filter) => filter.ModeName?.toLowerCase() === 'cash' || filter.ModeName?.toLowerCase() === 'upi' || filter.ModeName?.toLowerCase() === 'credit' ); setPaymentOptions(paymentDetails); const modeId = paymentDetails?.find( (item) => item.ModeName === 'Cash' )?.ModeId; setSelectedPaymentMode(modeId); formRef.current?.setFieldsValue({ PaymentMode: modeId }); } } catch (error) { setMessage({ type: 'error', data: error?.message || 'Failed to fetch payment options.', }); } }; const findMatchingSuppliers = async (name, mobile, supplierData) => { let list = []; if (mobile) { const m = mobile; list = supplierData.filter((x) => (x.SuppMobile || '').toString().includes(m) ); } // 2️⃣ If no mobile match or mobile empty → fallback to name if (name) { const n = name?.trim().toLowerCase(); // 🔥 trimmed + lowercase list = supplierData.filter( (x) => (x.SuppName || '').trim().toLowerCase() === n // 🔥 safe compare ); } let finalList = list?.length > 0 ? [list[0]] : []; const mappedSupplierProducts = await handleSupplierDropDownChange( finalList?.[0]?.SuppId, null, supplierData ); return { mappedSupplierProducts, SuppId: finalList?.[0]?.SuppId }; }; const getFieldSetup = async () => { try { const response = await dispatch( getFieldSetupData({ AppId, CompId, BranchId, categoryId, Type: 'PE' }) ).unwrap(); if (response?.data?.statusCode === 1) { setSelectedAdditionalColumn( response?.data?.data?.[0]?.ConfigDtl?.filter( (c) => c.ConfigId && c.Access === 'Y' )?.map((c) => c.ConfigName) || [] ); setTableFieldPreferences( response?.data?.data?.[0]?.ConfigDtl?.map((c) => ({ value: c.ConfigId, label: c.ConfigName, access: c.Access, })) || [] ); } } catch (error) { console.error('Error fetching field setup:', error); } }; const AddSupplierimg = async (subSupplierData) => { const addSupplierData = { CompId: CompId, AppId: AppId, BranchId: BranchId, SuppName: subSupplierData?.SuppName, SuppGSTIN: subSupplierData?.SuppGSTIN, SuppPOC: subSupplierData?.SuppPOC, SuppMobile: subSupplierData?.SuppMobile, SuppEmail: subSupplierData?.SuppEmail, Address1: subSupplierData?.Address1, Address2: subSupplierData?.Address1, Zip: subSupplierData?.Zip, City: subSupplierData?.City, State: subSupplierData?.State, Dist: subSupplierData?.Dist, CreatedBy: UserId, }; let response = {}; response = await dispatch(postSupplier(addSupplierData)).unwrap(); if (response?.data?.statusCode == 1) { setMessageType('success'); setMessageData(response?.data?.response); let response1 = await dispatch( getSupplierData({ CompId: CompId, AppId: AppId, BranchId: BranchId, ActiveStatus: 'A', }) ).unwrap(); const suppliers = await getSuplaierApi({ dataReturn: true }); if (response1?.data?.statusCode == 1) { setZipCodeData(null); const mappedSupplierProducts = await findMatchingSuppliers( subSupplierData?.SuppName, subSupplierData?.SuppMobile, suppliers ); return mappedSupplierProducts; } } else { setMessageType('error'); setMessageData(response?.data?.response); return { mappedSupplierProducts: null, SuppId: null }; } }; const handleExtractorApply = async (data) => { setIsLoading(true); setLoadingText('Processing extracted data...'); setExtractorData(data); let supplierProducts = []; let suppId = null; if (data?.supplierSuggestions?.length > 0) { setLoadingText('Loading supplier products...'); supplierProducts = await handleSupplierDropDownChange( data?.supplierSuggestions?.[0]?.SuppId ); suppId = data?.supplierSuggestions?.[0]?.SuppId; } if (data?.supplierSuggestions?.length === 0) { setLoadingText('Creating new supplier...'); const Address = await getPincodeValues(data?.pincode); let suppdata = { SuppName: data?.name, SuppMobile: data?.mobile, SuppGSTIN: data?.gst, Zip: data?.pincode, City: Address?.City || '.', State: Address?.State || '.', Dist: Address?.Dist || '.', Address1: data?.address || '.', }; const { mappedSupplierProducts, SuppId } = await AddSupplierimg(suppdata); suppId = SuppId; supplierProducts = mappedSupplierProducts; } // check if the products from extractor exist in the supplier's products setLoadingText('Matching products with supplier...'); let matchedProducts = data?.products?.map((imgItem) => { const match = supplierProducts?.find( (supp) => supp?.ProdName?.toLowerCase() === imgItem?.description?.toLowerCase() ); return { selectedProduct: match || null, parsedData: imgItem, matchFound: !!match, selectedProdId: match?.ProdId || null, }; }); const unmatchedProducts = matchedProducts.filter( (item) => !item.matchFound ); if (unmatchedProducts?.length > 0) { setLoadingText('Mapping unmatched products...'); const response = await dispatch( getSupplaierIdBasedProducts({ CompId, AppId, BranchId, SuppId: suppId }) ).unwrap(); if (response?.data?.statusCode === 1) { const allSupplierProducts = response?.data?.data || []; const matchingProdIds = []; const NewImageProducts = []; console.log(unmatchedProducts, 'unmatchedProductsunmatchedProducts'); // check if the unmatched products exists in our products list unmatchedProducts.forEach((item) => { const match = allSupplierProducts?.[0]?.ProductDetails.find( (supp) => supp?.ProdName?.toLowerCase() === item?.parsedData?.description?.toLowerCase() ); if (match) { matchingProdIds.push(match.ProdId); } else { NewImageProducts.push(item?.parsedData); } }); // Bulk upload new image products if (NewImageProducts.length > 0) { const newProductsData = NewImageProducts.map((product) => ({ AppId: AppId || 0, CompId: CompId || '', BranchId: BranchId || '', CreatedBy: UserId || 0, ProdName: product.description?.trim() || '', ProdVariantName: '', Size: 1 || '', UOM: product.unit || '', MRP: parseFloat(product.rate) || 0, WhSalePrice: 0, SellPrice: parseFloat(product.rate) || 0, ProdCat: 'General', ProdSubCat: '', Brand: '', AutoGenerateQr: '', QRCode: '', StockAvailable: 'No', HSNCode: '', PartNumber: '', Rack: 0, ManufDate: '', ExpDate: '', AvailableFrom: '', AvailableTo: '', ProdLogo: '', OnePcsAvailable: 'No', AutoGenerateSingleQr: 'No', TaxId: 'NIL - 0%', OnePcQR: '', TokenAvailable: 'No', OpeningQty: 0, QtyBasedPrice: '', InwardDate: '', SuppId: suppId || '', Reference: '', ReceivedQty: 0, AcceptedQty: 0, RejectedQty: 0, RejectionReason: '', IssuedQty: 0, BalanceQty: 0, InwardPrice: 0, OfferPrice: 0, SpecialPrice: 0, Cess: 0, })); const bulkResponse = await dispatch( bulkpostdata({ ProdDetails: newProductsData }) ).unwrap(); if (bulkResponse?.data?.statusCode === 1) { // After successful bulk upload, check the condition again const updatedResponse = await dispatch( getSupplaierIdBasedProducts({ CompId, AppId, BranchId, SuppId: suppId, }) ).unwrap(); if (updatedResponse?.data?.statusCode === 1) { const updatedAllSupplierProducts = updatedResponse?.data?.data || []; const updatedMatchingProdIds = []; unmatchedProducts.forEach((item) => { const match = updatedAllSupplierProducts?.[0]?.ProductDetails.find( (supp) => supp?.ProdName?.toLowerCase() === item?.parsedData?.description?.toLowerCase() ); if (match) { updatedMatchingProdIds.push(match.ProdId); } }); if (updatedMatchingProdIds.length > 0) { matchingProdIds.push(...updatedMatchingProdIds); } } } } // if there is matching products, map them to the supplier if (matchingProdIds.length > 0) { setLoadingText('Mapping products to supplier...'); const payload = { CompId, BranchId, AppId, SuppId: suppId, ProductDetails: matchingProdIds.map((item) => ({ ProdId: item })), }; const response = await dispatch( postSupplaierProducts(payload) )?.unwrap(); if (response?.data?.statusCode === 1) { const suppliers = await getSuplaierApi({ dataReturn: true }); const mappedSupplierProducts = await handleSupplierDropDownChange( suppId, null, suppliers ); // update matchedProducts with newly mapped products matchedProducts = data?.products?.map((imgItem) => { const match = mappedSupplierProducts?.find( (supp) => supp?.ProdName?.toLowerCase() === imgItem?.description?.toLowerCase() ); return { selectedProduct: match || null, parsedData: imgItem, matchFound: !!match, selectedProdId: match?.ProdId || null, }; }); console.log(matchedProducts, 'matchedProductsmatchedProducts'); if (matchedProducts?.length > 0) { setLoadingText('Adding products to purchase list...'); const newProducts = []; for (const item of matchedProducts) { if (item.matchFound) { const newProduct = await ProductDropDownChange( item?.selectedProduct.ProdVariantName, item.selectedProdId, { label: item.selectedProduct.ProdName }, mappedSupplierProducts, true, item, newProducts ); if (newProduct) { if ( !PurchaseData.some((p) => p.ProdId === newProduct.ProdId) ) { newProducts.push(newProduct); } else { if (suppId !== selectedSupplierData) { newProducts.push(newProduct); } else { setMessageType('error'); setMessageData( `Product ${newProduct.ProdName} already added in the list.` ); } } } } } // if (newProducts.length > 0) { const updatedPurchaseData = [...PurchaseData, ...newProducts]; const purchasedData = selectedSupplierData === suppId ? updatedPurchaseData : newProducts; setPurchaseData(purchasedData); if (purchasedData.length > 0) { for (const item of purchasedData) { // const index = purchasedData.indexOf(item); const localId = item?.localId; form.setFieldsValue({ ...form.getFieldsValue(), [`BalanceQty${localId}`]: item.BalanceQty, [`ReceivedQty${localId}`]: item.ReceivedQty, [`AcceptedQty${localId}`]: item.AcceptedQty, [`RejectedQty${localId}`]: item?.RejectedQty, [`InwardPrice${localId}`]: item?.InwardPrice, [`Amount${localId}`]: item?.Amount, }); } } // } setMessageType('success'); setMessageData('Extracted data applied successfully!'); } else { setMessageType('error'); setMessageData( 'No matching products found in your product list.' ); console.log('Matching 1'); } } else { setMessageType('error'); setMessageData( 'Error Occurred while mapping products with supplier.' ); } } else { setMessageType('error'); setMessageData('No matching products found in your product list.'); console.log('Matching 2'); } } else { setIsLoading(false); setLoadingText(''); setMessageType('error'); setMessageData('Error Occurred while mapping products with supplier.'); return; } } else { if (matchedProducts?.length > 0) { setLoadingText('Adding products to purchase list...'); const newProducts = []; for (const item of matchedProducts) { if (item.matchFound) { const newProduct = await ProductDropDownChange( item?.selectedProduct?.ProdVariantName, item.selectedProdId, { label: item.selectedProduct.ProdName }, supplierProducts, true, item, newProducts ); if (newProduct) { if (!PurchaseData.some((p) => p.ProdId === newProduct.ProdId)) { newProducts.push(newProduct); } else { if (suppId !== selectedSupplierData) { newProducts.push(newProduct); } else { setMessageType('error'); setMessageData( `Product ${newProduct.ProdName} already added in the list.` ); } } } } } // if (newProducts.length > 0) { const updatedPurchaseData = [...PurchaseData, ...newProducts]; const purchasedData = selectedSupplierData === suppId ? updatedPurchaseData : newProducts; setPurchaseData(purchasedData); if (purchasedData.length > 0) { for (const item of purchasedData) { // const index = purchasedData.indexOf(item); const localId = item?.localId; form.setFieldsValue({ ...form.getFieldsValue(), [`BalanceQty${localId}`]: item.BalanceQty, [`ReceivedQty${localId}`]: item.ReceivedQty, [`AcceptedQty${localId}`]: item.AcceptedQty, [`RejectedQty${localId}`]: item?.RejectedQty, [`InwardPrice${localId}`]: item?.InwardPrice, [`Amount${localId}`]: item?.Amount, }); } } // } setMessageType('success'); setMessageData('Extracted data applied successfully!'); } else { setMessageType('error'); setMessageData('No matching products found in your product list.'); console.log('Matching 3'); } } setExtractorModalVisible(false); setIsLoading(false); setLoadingText(''); }; const applicationApplicableFields = async () => { const response = await dispatch(getCommonAppPreference(AppId)).unwrap(); if (response?.data?.statusCode === 1) { const details = response?.data?.data?.[0]?.PreferenceDetails?.find( (find) => find.PreferredCatName === 'Purchase Entry' ); if (Object.keys(details || {})?.length > 0) { if (details?.PreferenceCatDetails?.length > 0) { setApplicationRestrictedFields({ DatesAndExpiry: details?.PreferenceCatDetails?.some( (some) => some.PreferredSubCatName === 'Dates & Expiry' && some.PreferredStatus === 'Y' ), BatchAndModelDetails: details?.PreferenceCatDetails?.some( (some) => some.PreferredSubCatName === 'Batch & Model Details' && some.PreferredStatus === 'Y' ), AmountPerPieceDetail: details?.PreferenceCatDetails?.some( (some) => some.PreferredSubCatName === 'Amount Per Piece' && some.PreferredStatus === 'Y' ), }); return; } } setApplicationRestrictedFields({ DatesAndExpiry: null, BatchAndModelDetails: null, AmountPerPieceDetail: null, }); } }; const filteredOptions = useMemo(() => { return ( purchaseOrderList?.map((data) => { const purchaseInvoiceParts = data?.PurOrderId?.split('-'); return { value: data?.PurOrderId, label: purchaseInvoiceParts[purchaseInvoiceParts?.length - 1], }; }) || [] ); }, [purchaseOrderList, selectedSupplierData]); const getPurchaseType = async () => { let res = await dispatch(getPurchaseTypeData()).unwrap(); if (res?.data?.statusCode === 1) { setPurchaseTypeData(res?.data?.data); let tempcash = res?.data?.data?.find( (item) => item?.ConfigName?.toLowerCase() === 'cash' ); setSelectedPurchaseType(tempcash?.ConfigId); formRef.current?.setFieldsValue({ PaymentType: tempcash?.ConfigId }); } else { setPurchaseTypeData(null); } }; const getPurchaseTaxType = async () => { let res = await dispatch(getPurchaseTaxTypeData()).unwrap(); if (res?.data?.statusCode === 1) { // setPurcTaxTypeData(res?.data?.data); let tempniltax = res?.data?.data?.find( (item) => item?.ConfigName?.toLowerCase() === 'inclusive' ); setSelectedPurcTaxType(tempniltax?.ConfigId); formRef.current?.setFieldsValue({ TaxType: tempniltax?.ConfigId }); } // else { // setPurcTaxTypeData(null); // } }; const pinCodeChange = async (e) => { if (e.target.value?.length < 6) { setZipCodeData(false); return false; } await getPincodeValues(e?.target?.value); }; const getPincodeValues = async (pinCode) => { let response = ''; await fetch(`https://api.postalpincode.in/pincode/${pinCode}`) .then((res) => res.text()) .then((text) => (response = JSON.parse(text))); if (response[0]['Status'] === 'Success') { setZipCodeData(true); formSupplierRef.current?.setFieldsValue({ City: response[0]['PostOffice'][0]['Block'], Dist: response[0]['PostOffice'][0]['District'], State: response[0]['PostOffice'][0]['State'], }); return { City: response[0]['PostOffice'][0]['Block'], Dist: response[0]['PostOffice'][0]['District'], State: response[0]['PostOffice'][0]['State'], }; } else { setZipCodeData(false); } }; const handleMRP = () => { formProductRef.current?.setFieldsValue({ SellPrice: null }); }; const handleSuppInvoiceNoChange = (e) => { const value = e.target.value; formRef.current?.setFieldsValue({ SuppInvoiceNo: value }); setExtractorData((prev) => (prev ? { ...prev, invoiceNo: value } : null)); }; const handleInvoiceTypeChange = (value) => { setInvoiceType(value); }; const handleInwardDateChange = (date) => { setInwardDate(date); }; // formRef?.current?.setFieldsValue({ SuppInvoiceNo: extractorData?.invoiceNo }); const handleSupplierDropDownChange = async ( SuppId, option, suppliers = null ) => { let suppName = (suppliers || SupplierData)?.filter( (item) => item.SuppId == SuppId )?.[0]?.SuppName; formRef?.current?.setFieldsValue({ CustSuppId: SuppId }); setSelectedSupplierData(SuppId); const mappedSupplierProducts = await handleSupplierBasedProduct(SuppId); formRef?.current?.resetFields(['VarProdId', 'ProdId']); suppName === 'Self' ? setSelectedSupplierName(false) : setSelectedSupplierName(true); // setselectedProductVariantData(null); // setSelectedProductData(null); setSelectedProductName(null); formRef?.current?.setFieldsValue({ ProdId: null }); setSearchText(null); return mappedSupplierProducts; }; const handlePurchaseTypeChange = (PurId) => { formRef.current?.setFieldsValue({ PaymentType: PurId }); setSelectedPurchaseType(PurId); }; const onSuppInvoiceDateChange = async (date, dateString) => { if (dateString) { const Date3 = moment(dateString, ['DD-MM-YYYY']).format( 'YYYY-MM-DDTHH:mm:ss' ); formRef.current?.setFieldsValue({ SuppInvoiceDate: Date3 }); setSuppInvoiceDate(Date3); } else if (dateString === '') { setSuppInvoiceDate(); } }; const onPurchaseDateChange = async (date, dateString) => { if (dateString) { const Date3 = moment(dateString, ['DD-MM-YYYY']).format( 'YYYY-MM-DDTHH:mm:ss' ); formRef.current?.setFieldsValue({ DueDate: Date3 }); setPurchaseDate(Date3); } else if (dateString === '') { setPurchaseDate(); } }; const ProductDropDownChange = async ( VariantName, ProdId, option, productsList, extractedProduct = false, extractedItem, existingProducts ) => { setProductSearchText(''); setSelectedProductName(option?.label ? option?.label : ''); formRef?.current?.resetFields(['VarProdId']); // setselectedProductVariantData(null); if (true) { formRef.current?.setFieldsValue({ ProdId: ProdId }); // await setSelectedProductData(ProdId); if ( (existingProducts || PurchaseData)?.some( (e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName ) ) { const existingProduct = (existingProducts || PurchaseData)?.find( (e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName ); setMessageType('error'); setMessageData( `Product "${existingProduct?.ProdName} - ${existingProduct?.ProdVariantName}" already exists` ); return null; } else { let ProductData1 = (productsList || productData)?.find( (e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName ); let DefaultVariant = ProductData1?.ProdVariantPriceDetails?.find( (item) => item?.DefaultVariant === 'Y' && item?.ReceivedQty === 0 )?.DefaultVariant; let ProduData2 = { DefaultVariant: DefaultVariant, ProdId: ProductData1?.ProdId, MRP: ProductData1?.MRP, ProdName: ProductData1?.ProdName, UomName: ProductData1?.UomName, SellPrice: ProductData1?.SellPrice, StockAvailable: ProductData1?.StockAvailable, OnePcsAvailable: ProductData1?.OnePcsAvailable, OnePcsPrice: ProductData1?.OnePcsPrice, NoOfPcs: ProductData1?.NoOfPcs, TaxId: ProductData1?.TaxId, TaxPercentage: ProductData1?.TaxPercentage, ProdVariantName: ProductData1?.ProdVariantName, }; const qty = extractedProduct ? parseFloat(extractedItem?.parsedData?.qty) || 0 : 0; const acceptedQty = extractedProduct ? parseFloat(extractedItem?.parsedData?.qty) || 0 : 0; const rate = extractedProduct ? parseFloat(extractedItem?.parsedData?.rate) || 0 : 0; let tempPurData = { ...ProduData2, PurchaseTax: parseFloat(extractedItem?.parsedData?.tax) || 0, BalanceQty: qty, InwardPrice: rate, PurcDisc: 0, Amount: isNaN(rate) || isNaN(acceptedQty) ? 0 : rate * acceptedQty, WhSalePrice: 0, ReceivedQty: qty, AcceptedQty: acceptedQty, RejectedQty: qty - acceptedQty, OfferPrice: 0, SpecialPrice: 0, FreeItem: 0, TaxAmt: 0, TaxType: SelectedPurcTaxType ? SelectedPurcTaxType : 0, PurcDiscType: 'P', refImage: extractedItem?.parsedData?.image, PurchaseHSNCode: extractedItem?.parsedData?.hsn || '', localId: uuidv4(), }; return tempPurData; } } }; const handleProductSelect = async (value, option) => { const [prodId, variantName] = value?.split('_'); const product = productData.find( (p) => p.ProdId === prodId && p.ProdVariantName === variantName ); if (!product) return; // Check for duplicates const exists = PurchaseData.some( (p) => p.ProdId === prodId && p.ProdVariantName === variantName ); if (exists) { const existingProduct = PurchaseData.find( (p) => p.ProdId === prodId && p.ProdVariantName === variantName ); setMessageType('error'); setMessageData( `Product "${existingProduct?.ProdName} - ${existingProduct?.ProdVariantName}" already exists` ); return; } // Build product row const defaultVariant = product.ProdVariantPriceDetails?.find( (item) => item?.DefaultVariant === 'Y' && item?.ReceivedQty === 0 )?.DefaultVariant; const newRow = { ProdId: product.ProdId, ProdName: product.ProdName, ProdVariantName: product.ProdVariantName, UomName: product.UomName, MRP: product.MRP, SellPrice: product.SellPrice, OnePcsPrice: product.OnePcsPrice, NoOfPcs: product.NoOfPcs, StockAvailable: product.StockAvailable, OnePcsAvailable: product.OnePcsAvailable, TaxId: product.TaxId, TaxPercentage: product.TaxPercentage, DefaultVariant: defaultVariant, PurchaseTax: 0, BalanceQty: 0, InwardPrice: 0, ReceivedQty: 0, AcceptedQty: 0, RejectedQty: 0, Amount: 0, WhSalePrice: 0, OfferPrice: 0, SpecialPrice: 0, FreeItem: 0, TaxAmt: 0, PurcDisc: 0, PurcDiscType: 'P', PurchaseHSNCode: product.PurchaseHSNCode || '', refImage: product?.image || '', localId: uuidv4(), }; // ✅ Single state update: update PurchaseData + form fields together setPurchaseData((prev) => [newRow, ...prev]); form?.setFieldsValue({ [`SellPrice${newRow.localId}`]: newRow.SellPrice, [`PurchaseTax${newRow.localId}`]: newRow.PurchaseTax, ProdId: prodId, }); // Reset search text setProductSearchText(''); setSelectedProductName(option?.label || ''); }; const debouncedScannerSearch = useCallback( debounce(async (value) => { const qr = value?.trim(); const matchedProduct = productData.find( (p) => p.QRCode?.toLowerCase() === qr?.toLowerCase() ); if (matchedProduct) { let productName = {}; productName.label = `${matchedProduct?.ProdName} (${matchedProduct.Size} ${matchedProduct.UomName})${matchedProduct?.BrandName ? ` - ${matchedProduct?.BrandName}` : ''}`; const newProduct = await ProductDropDownChange( matchedProduct?.ProdVariantName, matchedProduct.ProdId, productName ); if (newProduct) { setPurchaseData([newProduct, ...PurchaseData]); } if (matchedProduct?.ProdVariantPriceDetails?.length < 2) { setSelectedProductName(''); // setSelectedProductData(null); } } else { setMessageType('error'); setMessageData('The Scanned Product not Available in Product List'); } }, 300), [productData] ); // Clean up debounce on unmount const handleProductSearch = (value) => { if (scanner) { debouncedScannerSearch(value); } setProductSearchText(value); setSelectedProductName(value); }; const handleScanSearch = () => { if (scanner === false) { setMessageType('success'); setMessageData('Search by QrCode/BarCode Enabled'); } else { setMessageType('success'); setMessageData('Search by QrCode/BarCode Disabled'); } setScanner((prev) => !prev); setSelectedProductName(null); // setselectedProductVariantData(null); // setVariants(null); formRef?.current?.setFieldsValue({ ProdId: null, VarProdId: null, }); }; const addSupplier = () => { setOpenSupplierModel(true); }; const handleSupplier = () => { setOpenSupplierModel(false); }; const submitSupplier = async () => { const subSupplierData = await formSupplierRef?.current?.validateFields(); const addSupplierData = { CompId: CompId, AppId: AppId, BranchId: BranchId, SuppName: subSupplierData?.SuppName, SuppGSTIN: subSupplierData?.SuppGSTIN, SuppPOC: subSupplierData?.SuppPOC, SuppMobile: subSupplierData?.SuppMobile, SuppEmail: subSupplierData?.SuppEmail, Address1: subSupplierData?.Address1, Address2: subSupplierData?.Address1, Zip: subSupplierData?.Zip, City: subSupplierData?.City, State: subSupplierData?.State, Dist: subSupplierData?.Dist, SuppPOCMobile: subSupplierData?.SuppPOCMobile, SuppPOCEmail: subSupplierData?.SuppPOCEmail, DeliveryPerformance: subSupplierData?.DeliveryPerformance, DiscountLevel: subSupplierData?.DiscountLevel, QualityofSupp: subSupplierData?.QualityofSupp, CreatedBy: UserId, }; let response = {}; response = await dispatch(postSupplier(addSupplierData)).unwrap(); if (response?.data?.statusCode == 1) { setMessageType('success'); setMessageData(response?.data?.response); let response1 = await dispatch( getSupplierData({ CompId: CompId, AppId: AppId, BranchId: BranchId, ActiveStatus: 'A', }) ).unwrap(); if (response1?.data?.statusCode == 1) { setOpenSupplierModel(false); } formSupplierRef?.current?.resetFields(); setZipCodeData(null); } else { setMessageType('error'); setMessageData(response?.data?.response); formSupplierRef?.current?.resetFields(); } }; useEffect(() => { if (!editingKey) return; const record = PurchaseData.find((item) => item.localId === editingKey); if (!record) return; const localId = record.localId; const values = Delete ? { [`BalanceQty${localId}`]: undefined, [`ReceivedQty${localId}`]: undefined, [`AcceptedQty${localId}`]: undefined, [`RejectedQty${localId}`]: undefined, [`Amount${localId}`]: undefined, [`Freeqty${localId}`]: undefined, [`InwardPrice${localId}`]: undefined, [`MRP${localId}`]: undefined, [`PurcDisc${localId}`]: undefined, [`SellPrice${localId}`]: undefined, [`WhSalePrice${localId}`]: undefined, [`offerSalePrice${localId}`]: undefined, [`splSalePrice${localId}`]: undefined, [`NumberofPieceinside${localId}`]: undefined, [`AmountPerPiece${localId}`]: undefined, [`PurcDiscType${localId}`]: undefined, [`ManufDate${localId}`]: undefined, [`ExpDate${localId}`]: undefined, [`OnePcsPrice${localId}`]: undefined, [`NoOfPcs${localId}`]: undefined, } : { [`BalanceQty${localId}`]: record.BalanceQty, [`ReceivedQty${localId}`]: record.ReceivedQty, [`AcceptedQty${localId}`]: record.AcceptedQty, [`RejectedQty${localId}`]: record.RejectedQty, [`Freeqty${localId}`]: record.FreeItem, [`MRP${localId}`]: record.MRP, [`ManufDate${localId}`]: record.ManufDate, [`ExpDate${localId}`]: record.ExpDate, [`SellPrice${localId}`]: record.SellPrice, [`WhSalePrice${localId}`]: record.WhSalePrice, [`PurcDiscType${localId}`]: record.PurcDiscType, [`Amount${localId}`]: record.Amount, [`InwardPrice${localId}`]: record.InwardPrice, [`PurcDisc${localId}`]: record.PurcDisc, [`offerSalePrice${localId}`]: record.OfferPrice, [`splSalePrice${localId}`]: record.SpecialPrice, [`OnePcsPrice${localId}`]: record.OnePcsPrice, [`NoOfPcs${localId}`]: record.NoOfPcs, }; if (!Delete && applicationRestrictedFields.BatchAndModelDetails) { values[`BatchRef${localId}`] = record.BatchRef; } form.setFieldsValue(values); setDelete(false); }, [editingKey]); const save = async (localId) => { try { const row = await form.validateFields(); const modifiedObject = {}; for (const key in row) { // remove localId suffix from field names if (key.endsWith(localId)) { const newKey = key?.replace(localId, ''); modifiedObject[newKey] = row[key]; } } setPurchaseData((prev) => prev.map((item) => item.localId === localId ? { ...item, ...modifiedObject } : item ) ); setEditingKey(''); } catch (err) { console.error('Save failed:', err); } }; const handleKeyPress = async (e, record) => { if (e.key === 'Enter') { try { await form.validateFields(); save(record.localId); } catch (error) { console.error('Save failed:', error); } } }; const formatDateForDisplay = (dateString) => { if (!dateString) return ''; return moment(dateString).format('DD-MMM-YY'); }; const sellPriceValidator = useCallback((_, value) => { if (value <= 0) return Promise.reject('Invalid price'); return Promise.resolve(); }, []); const handleDecimalInput = (e) => { let value = e.target.value?.replace(/[^0-9.]/g, ''); if (value.startsWith('.')) value = '0' + value; const parts = value.split('.'); e.target.value = parts?.length > 2 ? `${parts[0]}.${parts.slice(1).join('')}` : value; }; const updateRowValues = (localId, updates) => { setPurchaseData((prev) => prev.map((item) => item.localId === localId ? { ...item, ...updates } : item ) ); const formUpdates = {}; Object.keys(updates).forEach((key) => { formUpdates[`${key}${localId}`] = updates[key]; }); form.setFieldsValue(formUpdates); }; const updateRowValue = (localId, key, value) => { setPurchaseData((prev) => prev.map((item) => item.localId === localId ? { ...item, [key]: value } : item ) ); form.setFieldsValue({ [`${key}${localId}`]: value, }); }; const columns = useMemo(() => { const baseColumns = [ { title: 'SL.NO', align: 'center', key: 'sno', width: 50, render: (text, object, index) => ( {index + 1} ), }, { title: 'Name', dataIndex: 'ProdName', key: 'ProdName', align: 'left', width: 150, render: (text, record, index) => ( {record?.ProdName} ), }, { title: 'Variant', dataIndex: 'ProdVariantName', key: 'ProdVariantName', align: 'center', width: 100, render: (text, record, index) => ( {record?.ProdVariantName} ), }, { title: 'Uom', dataIndex: 'UomName', key: 'UOMName', align: 'center', width: 100, }, { title: 'Qty', dataIndex: 'BalanceQty', key: 'BalanceQty', align: 'center', editable: true, width: 100, render: (text, record, index) => { return ( handleQtyTyping(e, record)} onBlur={() => commitQtyChange(record)} onPressEnter={() => commitQtyChange(record)} inputMode="decimal" onInput={(e) => { let v = e.target.value.replace(/[^0-9.]/g, ''); if (v.startsWith('.')) v = '0' + v; const parts = v.split('.'); e.target.value = parts.length > 2 ? `${parts[0]}.${parts.slice(1).join('')}` : v; }} /> ); }, }, { title: 'Pur Rate / unit', dataIndex: 'InwardPrice', key: 'InwardPrice', width: 120, editable: true, align: 'center', render: (_, record) => { const editable = true; return editable ? ( handlePurrateTyping(e, record)} /> ) : (
edit(record)} // ✅ THIS is required style={{ cursor: 'pointer' }} > {record.InwardPrice || 0}
); }, }, { title: ( Tax (%) ), dataIndex: 'PurchaseTax', key: 'PurchaseTax', editable: true, align: 'center', width: 100, render: (_, record) => ( handleTaxTyping(e, record)} onBlur={() => debouncedTaxCalc(record.PurchaseTax, record)} /> ), }, { title: 'Amount', dataIndex: 'Amount', key: 'Amount', editable: true, align: 'right', width: 100, }, ...(selectedAdditionalColumn.includes('Mrp') ? [ { title: 'MRP', dataIndex: 'MRP', key: 'MRP', editable: true, width: 100, align: 'center', render: (_, record) => { return ( edit(record)} placeholder="MRP" value={record?.MRP ?? ''} maxLength={10} inputMode="decimal" onChange={(e) => handleMRPChange(e, record)} onBlur={(e) => handleMRPBlur(e, record)} onPressEnter={(e) => handleKeyPress(e, record)} /> ); }, }, ] : []), { title: ( Selling Price ), dataIndex: 'SellPrice', key: 'SellPrice', width: 100, editable: true, align: 'center', render: (_, record) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} value={record?.SellPrice ?? ''} maxLength={10} inputMode="decimal" onChange={(e) => handleSellPriceChange(e, record)} onBlur={(e) => handleSellPriceBlur(e, record)} onPressEnter={(e) => handleKeyPress(e, record)} onInput={handleDecimalInput} /> ); }, }, ...(selectedAdditionalColumn.includes('Amount Per Piece') ? [ { title: 'Amount per piece', dataIndex: 'OnePcsPrice', key: 'OnePcsPrice', width: 125, editable: true, render: (_, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} disabled={record?.OnePcsAvailable === 'N'} placeholder="OnePcsPrice" value={record?.OnePcsPrice ?? ''} maxLength={10} inputMode="decimal" onChange={(e) => handleOnePcsChange(e, record)} onBlur={(e) => handleOnePcsBlur(e, record)} onPressEnter={() => handleKeyPress(e, record)} onInput={(e) => { let v = e.target.value.replace(/[^0-9.]/g, ''); if (v.startsWith('.')) v = '0' + v; const parts = v.split('.'); e.target.value = parts.length > 2 ? `${parts[0]}.${parts.slice(1).join('')}` : v; }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Amount Per Piece') ? [ { title: 'Number of piece', dataIndex: 'NoOfPcs', key: 'NoOfPcs', width: 125, editable: true, render: (_, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} disabled={record?.OnePcsAvailable === 'N'} placeholder="NoOfPcs" value={record.NoOfPcs ?? ''} maxLength={5} inputMode="numeric" onChange={(e) => handleNoOfPcsChange(e, record)} onBlur={(e) => handleNoOfPcsBlur(e, record)} onPressEnter={() => handleKeyPress(e, record)} onInput={(e) => { // remove invalid characters & leading zeros let val = e.target.value.replace(/[^0-9]/g, ''); val = val.replace(/^0+(?=\d)/, ''); // removes leading zeros but keeps single 0 e.target.value = val; }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Wholesale Price') ? [ { title: 'Wholesale price', dataIndex: 'WhSalePrice', key: 'WhSalePrice', width: 125, editable: true, render: (_, record) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} placeholder="WhSalePrice" value={record.WhSalePrice ?? ''} inputMode="decimal" maxLength={10} onChange={(e) => handleWhSalePriceChange(e, record)} onBlur={(e) => handleWhSalePriceBlur(e, record)} onPressEnter={() => handleKeyPress(record)} onInput={(e) => { let val = e.target.value.replace(/[^0-9.]/g, ''); // remove invalid chars if (val.startsWith('.')) val = '0' + val; // leading dot fix const parts = val.split('.'); if (parts.length > 2) val = `${parts[0]}.${parts.slice(1).join('')}`; // max one dot val = val.replace(/^0+(?=\d)/, ''); // remove leading zeros e.target.value = val; }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Manufacture Date') ? [ { title: 'Manuf.Date', dataIndex: 'ManufDate', key: 'ManufDate', editable: true, width: 100, render: (text, record, index) => { return ( { // Format date to your preferred format const formattedDate = dateString ? moment(dateString, ['DD-MM-YYYY']).format( 'YYYY-MM-DDTHH:mm:ss' ) : undefined; // Update the row data immutably const newData = PurchaseData.map((item) => item.localId === record.localId ? { ...item, ManufDate: formattedDate } : item ); setPurchaseData(newData); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Expiry Date') ? [ { title: 'Exp.Date', dataIndex: 'ExpDate', key: 'ExpDate', editable: true, width: 100, render: (text, record, index) => { return ( handleExpDateChange(dateString, record) } /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Hsn') ? [ { title: 'Hsn', dataIndex: 'Hsn', key: 'Hsn', editable: true, width: 100, align: 'center', render: (text, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} onPressEnter={() => handleKeyPress(record)} onChange={(e) => { const value = e.target.value; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, PurchaseHSNCode: value } : item ) ); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Model No') ? [ { title: 'Model', dataIndex: 'Model', key: 'Model', editable: true, width: 100, align: 'center', render: (text, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} onPressEnter={() => handleKeyPress(record)} onChange={(e) => { const value = e.target.value; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, ModelNumber: value } : item ) ); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Batch No') ? [ { title: 'Batch', dataIndex: 'Batch', key: 'Batch', width: 100, align: 'center', editable: true, render: (text, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} onPressEnter={() => handleKeyPress(record, index)} onChange={(e) => { const value = e.target.value; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, BatchRef: value } : item ) ); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Rejected Qty') ? [ { title: 'Rejected Qty', dataIndex: 'RejectedQty', key: 'RejectedQty', editable: true, width: 100, align: 'center', render: (text, record, index) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} onPressEnter={() => handleKeyPress(record, index)} onChange={(e) => { let inputValue = e.target.value.replace(/[^0-9.]/g, ''); // allow only numbers if (inputValue.startsWith('0') && inputValue.length > 1) { inputValue = inputValue.replace(/^0+/, ''); // remove leading zeros } const rejectedQty = parseFloat(inputValue) || 0; const receivedQty = parseFloat(record.ReceivedQty) || 0; // validation if (rejectedQty >= receivedQty) { setMessageType('error'); setMessageData( 'Rejected Qty cannot be greater than or equal to Received Qty' ); return; } const acceptedQty = receivedQty - rejectedQty; const price = parseFloat(record.InwardPrice) || 0; const amount = acceptedQty * price; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, RejectedQty: rejectedQty, AcceptedQty: acceptedQty, Amount: amount, } : item ) ); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('Free Qty') ? [ { title: 'Free Qty', dataIndex: 'Freeqty', key: 'Freeqty', editable: true, width: 100, align: 'center', render: (text, record) => { return ( edit(record)} onFocus={(e) => e.stopPropagation()} onPressEnter={() => handleKeyPress(record)} onChange={(e) => { let value = e.target.value.replace(/[^0-9]/g, ''); // only digits if (value.startsWith('0') && value.length > 1) { value = value.replace(/^0+/, ''); // remove leading zeros } updateRowValue(record.localId, 'Freeqty', value); }} /> ); }, }, ] : []), ...(selectedAdditionalColumn.includes('IMEI') ? [ { title: 'IMEI', dataIndex: 'AdditionalInfo', key: 'AdditionalInfo', width: 120, align: 'center', render: (text, record, index) => { const receivedQty = parseFloat(record?.ReceivedQty) || 0; const isClickable = receivedQty > 0; return ( { if (!isClickable) { setMessageType('error'); setMessageData('Please Enter Qty'); return; } setSelectedRowIndex(index); handleModelDataOpen(record); }} className="shape-preview" /> ); }, }, ] : []), { title: 'Action', dataIndex: 'Action', key: 'Action', align: 'center', width: 80, render: (_, record, index) => ( { e.stopPropagation(); }} > statusFormatters(record)} /> ), }, ]; return baseColumns; }, [editingKey, editingQty, selectedAdditionalColumn]); const statusFormatters = (record) => { const localId = record?.localId; setPurchaseData((prev) => prev.filter((item) => item.localId !== localId)); const formValues = form.getFieldsValue(); const keysToRemove = Object.keys(formValues).filter((key) => key.endsWith(localId) ); if (keysToRemove.length) { const newValues = { ...formValues }; keysToRemove.forEach((key) => { newValues[key] = undefined; }); form.setFieldsValue(newValues); } // 3️⃣ Clear other single fields formRef?.current?.setFieldsValue({ ProdId: null, }); setDelete(true); // only if absolutely necessary }; const handleQtyTyping = (e, record) => { let value = e.target.value; // allow only numbers + decimal if (!/^\d*\.?\d*$/.test(value)) return; // 🔥 remove leading zero (but keep "0." valid) if (value.length > 1 && value.startsWith('0') && !value.startsWith('0.')) { value = value.replace(/^0+/, ''); } setEditingQty((prev) => ({ ...prev, [record.localId]: value, })); }; const commitQtyChange = (record) => { const { localId } = record; const qty = Number(editingQty[localId]) || 0; setPurchaseData((prev) => prev.map((item) => item.localId === localId ? { ...item, BalanceQty: qty, ReceivedQty: qty, AcceptedQty: qty, RejectedQty: 0, PurcDisc: 0, Amount: isNaN(item.InwardPrice) || isNaN(qty) ? 0 : item.InwardPrice * qty, ProductIdentifierDtls: [], } : item ) ); form.setFieldsValue({ [`BalanceQty${localId}`]: qty, [`ReceivedQty${localId}`]: qty, [`AcceptedQty${localId}`]: qty, [`RejectedQty${localId}`]: 0, [`PurcDisc${localId}`]: 0, }); }; useEffect(() => { const id = setTimeout(() => { const total = PurchaseData.reduce( (acc, d) => acc + Number(d.Amount || 0), 0 ); setPaymentAmount(total); formRef?.current?.setFieldsValue({ PaymentAmount: total }); }, 150); return () => clearTimeout(id); }, [PurchaseData]); const handleMRPChange = (e, record) => { const value = e.target.value ?? ''; if (!/^\d*\.?\d*$/.test(value)) return; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, MRP: value, SellPrice: value, } : item ) ); }; const handleMRPBlur = (e, record) => { const value = e.target.value ?? ''; const normalized = value === '' ? '' : String(Number(value)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, MRP: normalized, SellPrice: normalized, } : item ) ); }; const handlePurrateChange = useCallback((e, record) => { let value = e?.target?.value ?? ''; // allow decimals only if (!/^\d*\.?\d*$/.test(value)) return; // 🔥 remove leading zero when user starts typing if (value.length > 1 && value.startsWith('0') && !value.startsWith('0.')) { value = value.replace(/^0+/, ''); } setPurchaseData((prev) => prev.map((item) => { if (item.localId !== record.localId) return item; const qty = Number(item.AcceptedQty) || 0; const rateNum = Number(value || 0); const amount = rateNum * qty; let discountAmt = 0; if (item.PurcDiscType === 'P') { discountAmt = (amount * Number(item.PurcDisc || 0)) / 100; } else { discountAmt = Number(item.PurcDisc || 0); } const taxPercent = Number(item.TaxPercentage || 0); const taxAmt = taxPercent > 0 ? ((amount - discountAmt) * taxPercent) / (100 + taxPercent) : 0; return { ...item, InwardPrice: value, // 👈 clean value Amount: amount, TaxAmt: +taxAmt.toFixed(2), }; }) ); }, []); const handlePurrateTyping = (e, record) => { let value = e?.target?.value ?? ''; if (!/^\d*\.?\d*$/.test(value)) return; if (value.length > 1 && value.startsWith('0') && !value.startsWith('0.')) { value = value.replace(/^0+/, ''); } setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, InwardPrice: value } : item ) ); debouncedCalc(value, record); }; const calculateRate = useCallback((value, record) => { setPurchaseData((prev) => prev.map((item) => { if (item.localId !== record.localId) return item; const qty = Number(item.AcceptedQty) || 0; const rateNum = Number(value || 0); const amount = rateNum * qty; let discountAmt = 0; if (item.PurcDiscType === 'P') { discountAmt = (amount * Number(item.PurcDisc || 0)) / 100; } else { discountAmt = Number(item.PurcDisc || 0); } const taxPercent = Number(item.TaxPercentage || 0); const taxAmt = taxPercent > 0 ? ((amount - discountAmt) * taxPercent) / (100 + taxPercent) : 0; return { ...item, Amount: amount, TaxAmt: +taxAmt.toFixed(2), }; }) ); }, []); const debouncedCalc = useDebounce(calculateRate, 300); const handleSellPriceChange = (e, record) => { const value = e?.target?.value ?? ''; // allow smooth typing if (!/^\d*\.?\d*$/.test(value)) return; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, SellPrice: value } : item ) ); }; const handleSellPriceBlur = (e, record) => { const value = e?.target?.value ?? ''; const normalized = value === '' ? '' : String(Number(value)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, SellPrice: normalized } : item ) ); }; const handleOnePcsChange = (e, record) => { const value = e?.target?.value ?? ''; if (!/^\d*\.?\d*$/.test(value)) return; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, OnePcsPrice: value } : item ) ); }; const handleOnePcsBlur = (e, record) => { const value = e?.target?.value ?? ''; const normalized = value === '' ? '' : String(Number(value)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, OnePcsPrice: normalized } : item ) ); }; const handleNoOfPcsChange = (e, record) => { const value = e?.target?.value ?? ''; // only whole numbers if (!/^\d*$/.test(value)) return; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, NoOfPcs: value } : item ) ); }; const handleNoOfPcsBlur = (e, record) => { const value = e?.target?.value ?? ''; const normalized = value === '' ? '' : String(parseInt(value, 10)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, NoOfPcs: normalized } : item ) ); }; const handleWhSalePriceChange = (e, record) => { const value = e?.target?.value ?? ''; if (!/^\d*\.?\d*$/.test(value)) return; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, WhSalePrice: value } : item ) ); }; const handleWhSalePriceBlur = (e, record) => { const value = e?.target?.value ?? ''; const normalized = value === '' ? '' : String(Number(value)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, WhSalePrice: normalized } : item ) ); }; const handleManufDateChange = (dateString, record) => { const formattedDate = !dateString || dateString === '' ? undefined : moment(dateString, ['DD-MM-YYYY']).format('YYYY-MM-DDTHH:mm:ss'); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, ManufDate: formattedDate } : item ) ); }; const handleExpDateChange = (dateString, record) => { const formattedDate = !dateString || dateString === '' ? undefined : moment(dateString, ['DD-MM-YYYY']).format('YYYY-MM-DDTHH:mm:ss'); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, ExpDate: formattedDate } : item ) ); }; const handleHSNChange = (value, record) => { // optional: digits only (HSN is numeric) const cleanValue = value.replace(/\D/g, ''); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, PurchaseHSNCode: cleanValue } : item ) ); }; const handleTaxTyping = (e, record) => { let value = e?.target?.value ?? ''; // allow decimal typing only if (!/^\d*\.?\d*$/.test(value)) return; // fix ".5" → "0.5" if (value.startsWith('.')) value = '0' + value; setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, PurchaseTax: value } // keep STRING : item ) ); debouncedTaxCalc(value, record); }; const calculateTax = useCallback((value, record) => { setPurchaseData((prev) => prev.map((item) => { if (item.localId !== record.localId) return item; const amount = Number(item.Amount) || 0; const taxPercent = Number(value || 0); const taxAmt = taxPercent > 0 ? (amount * taxPercent) / (100 + taxPercent) : 0; return { ...item, TaxPercentage: taxPercent, TaxAmt: +taxAmt.toFixed(2), }; }) ); }, []); const debouncedTaxCalc = useDebounce(calculateTax, 300); // const handleTaxChange = (e, record) => { // const { localId } = record; // const value = e?.target?.value ?? ''; // // ✅ allow natural typing // if (!/^\d*\.?\d*$/.test(value)) return; // setPurchaseData((prev) => // prev.map((item) => // item.localId === localId // ? { // ...item, // PurchaseTax: value, // 👈 KEEP STRING // } // : item // ) // ); // // 👇 keep form in sync (string only) // form.setFieldsValue({ // [`PurchaseTax${localId}`]: value, // }); // }; const handleTaxBlur = (e, record) => { const value = e?.target?.value ?? ''; const normalized = value === '' ? '' : String(Number(value)); setPurchaseData((prev) => prev.map((item) => item.localId === record.localId ? { ...item, PurchaseTax: normalized } : item ) ); form.setFieldsValue({ [`PurchaseTax${record.localId}`]: normalized, }); }; const purchaseStatusChange = (value) => { setPurchaseStatus(value); }; const SupplierOpenfun = (value) => { setSupplierOpen(value); }; const getUniqueImageArray = (data = []) => { const seen = new Set(); return data.reduce((acc, item) => { const url = item?.refImage; if (url && !seen.has(url)) { seen.add(url); acc.push({ ImageUrl: url }); } return acc; }, []); }; const onFinish = async ({ PaymentType, PaymentAmount = 0, ...values }) => { try { // =============================== // 1️⃣ TAX VALIDATION // =============================== const invalidTaxItems = PurchaseData?.filter((item) => { const tax = item?.PurchaseTax; if (tax === undefined || tax === '' || tax === null) return false; const num = Number(tax); return isNaN(num) || num < 0 || num > 99; }); if (invalidTaxItems?.length > 0) { setMessageType('error'); setMessageData( 'Please enter valid tax percentage (0–99%) for all items' ); return; } if ( PurchaseData?.some( (item) => item.SellPrice && item.MRP && Number(item.SellPrice) > Number(item.MRP) ) ) { setMessageType('error'); setMessageData('Selling Price cannot be greater than MRP'); return; } if (!PurchaseData || PurchaseData?.length === 0) { setMessageType('error'); setMessageData('No Product Selected'); return; } const validRows = []; const invalidRowNumbers = []; PurchaseData.forEach((item, index) => { const qty = Number(item.BalanceQty) || 0; const amount = Number(item.Amount) || 0; if (qty > 0 && amount > 0) { validRows.push(item); } else { invalidRowNumbers.push(index + 1); } }); if (validRows?.length === 0) { setMessageType('error'); setMessageData('Please enter Qty and Amount for at least one product'); return; } // =============================== // 5️⃣ CONFIRMATION FOR INVALID ROWS // =============================== if (invalidRowNumbers.length > 0) { Modal.confirm({ title: '⚠️ Incomplete Product Rows', width: 520, centered: true, content: (

Some products are missing Qty or Amount.

Affected row(s): {invalidRowNumbers.join(', ')}

Are you sure you want to continue without these products?

), okText: 'Continue Anyway', cancelText: 'Go Back', okButtonProps: { danger: true }, onOk: () => proceedSubmit(validRows, values, PaymentType, PaymentAmount), }); return; } // If all rows valid await proceedSubmit(validRows, values, PaymentType, PaymentAmount); } catch (error) { console.error(error); setMessageType('error'); setMessageData('Something went wrong'); } }; const proceedSubmit = async ( filteredPurchaseData, values, PaymentType, PaymentAmount ) => { const images = getUniqueImageArray(filteredPurchaseData); const postData = { ...values, InvoiceAmount: filteredPurchaseData.reduce( (acc, item) => acc + Number(item.Amount || 0), 0 ), CompId, BranchId, AppId, CreatedBy: UserId, PurOrderStatus: purchaseStatus, TaxAmount: TotalTaxAmount?.toFixed(2), BillAmount: (SelInvoiceAmount - TotalTaxAmount)?.toFixed(2), TotalAmount: SelInvoiceAmount, PurOrderInvoiceNo: purchaseOrderId, PaymentStatus: 'S', LocationType: SupplierData?.find( (item) => item?.SuppId === selectedSupplierData )?.Type, ImageDetails: images || [], }; const fieldsToRemove = [ 'InwardDtlId', 'InwardId', 'UomName', 'ProdName', 'UOMName', ]; const processedData = filteredPurchaseData.map((item) => { const cleanItem = { ...item }; fieldsToRemove.forEach((field) => delete cleanItem[field]); return { ...cleanItem, TaxType: SelectedPurcTaxType || 0, BalanceQty: cleanItem.AcceptedQty, OnePcsPrice: cleanItem.OnePcsPrice, NoOfPcs: cleanItem.NoOfPcs, }; }); const isPaidSelected = PurchaseTypeData?.some( (item) => item.ConfigId === SelectedPurchaseType && item.ConfigName === 'Cash' ); if ( (SupplierOpen !== 'own' || selectedSupplierName) && selectedSupplierData && isPaidSelected ) { postData.PaymentAmount = PaymentAmount; postData.PaymentType = selectedPaymentMode; } else { postData.PaymentType = PaymentType; } postData.ProdDetails = processedData; if (formType === 'edit') { postData.ProdId = editstate?.ProdId; postData.InwardId = editstate?.InwardId; postData.InwardDtlId = editstate?.InwardDtlId; postData.UpdatedBy = UserId; } let response; try { response = formType === 'add' ? await dispatch(postPurchaseData(postData)).unwrap() : await dispatch(putStockData(postData)).unwrap(); } catch (err) { response = { data: { statusCode: 0, response: 'Please Give Required Fields', }, }; } if (response?.data?.statusCode === 1) { navigate(`${subDirectory}setting/purchase-entry/`, { state: { Notiffy: { messageType: 'success', messageData: response?.data?.response, }, }, }); } else { setMessageType('error'); setMessageData(response?.data?.response); } }; const onComplete = useCallback(() => { setMessageData(null); setMessageType(null); }, []); const defaultColumns = [ { title: 'IMEI 1', dataIndex: 'imei1', width: '30%', editable: true, }, { title: 'IMEI 2', dataIndex: 'imei2', editable: true, }, { title: 'Serial No', dataIndex: 'serialno', editable: true, }, { title: 'Mac Id', dataIndex: 'Macid', editable: true, }, ]; const handleSave = (row) => { const newData = [...dataSource]; const index = newData.findIndex((item) => row.key === item.key); const item = newData[index]; newData.splice(index, 1, { ...item, ...row, }); setDataSource(newData); }; const components = { body: { row: EditableRow, cell: EditableCell, }, }; const IMEIcolumns = defaultColumns.map((col) => { if (!col.editable) { return col; } return { ...col, onCell: (record) => ({ record, editable: col.editable, dataIndex: col.dataIndex, title: col.title, handleSave, }), }; }); const handleInvoiceSearch = (value) => { setSelectedSupplierData(null); formRef?.current?.setFieldsValue({ CustSuppId: null }); setSelectedSupplierName(true); setSearchText(value); setPurchaseOrderId(null); setSelectedInvoice(null); setPurchaseData([]); setProductData([]); form?.resetFields(); }; const handleInvoiceSelect = async (value) => { if (value === selectedInvoice) return; const invoiceParts = value?.split('-'); const shortInvoice = invoiceParts[invoiceParts.length - 1]; formRef?.current?.setFieldsValue({ SuppInvoiceNo: value }); formRef?.current?.setFieldsValue({ PurchaseOrderNo: value }); const purchaseOrders = purchaseOrderList?.filter( (order) => order?.PurOrderId === value ); const supplierExists = SupplierData?.filter( (item) => item?.SuppId === purchaseOrders?.[0]?.SuppId ); console.log(supplierExists, 'supplierExists'); let supplierMappedProducts = []; if (supplierExists?.length > 0) { setSelectedSupplierData(purchaseOrders?.[0]?.SuppId); supplierMappedProducts = (await handleSupplierBasedProduct(purchaseOrders?.[0]?.SuppId)) || []; formRef?.current?.setFieldsValue({ CustSuppId: purchaseOrders?.[0]?.SuppId, }); } else { setMessageType('error'); setMessageData("Supplier for this Order isn't Active"); return; } if (supplierExists?.[0]?.SuppName === 'Self') { setSelectedSupplierName(false); setSupplierOpen('own'); } else { setSelectedSupplierName(true); } setSelectedInvoice(value); setSearchText(shortInvoice); if (!purchaseOrders?.[0]?.OrderDetails?.length) { setPurchaseData([]); return; } let unMappedProducts = []; const orderedData = purchaseOrders[0].OrderDetails.map((order, index) => { const orderedProduct = supplierMappedProducts?.find( (prod) => prod?.ProdId === order?.ProdId ); if (orderedProduct === undefined) { unMappedProducts.push(`${order?.ProdName}`); } const DefaultVariant = orderedProduct?.ProdVariantPriceDetails?.find( (item) => item?.ReceivedQty === 0 && item?.ProdVariantName === order?.ProdVariantName && item?.ProdId === order?.ProdId )?.DefaultVariant; const ProduData2 = { DefaultVariant, ProdId: orderedProduct?.ProdId, MRP: orderedProduct?.MRP, ProdName: orderedProduct?.ProdName, UomName: orderedProduct?.UomName, SellPrice: orderedProduct?.SellPrice, StockAvailable: orderedProduct?.StockAvailable, OnePcsAvailable: orderedProduct?.OnePcsAvailable, NumberofPieceinside: orderedProduct?.NoOfPcs, AmountPerPiece: orderedProduct?.OnePcsPrice, TaxId: orderedProduct?.TaxId, TaxPercentage: orderedProduct?.TaxPercentage, PurOrderInvoiceNo: order?.PurOrderId, }; const uniqueId = uuidv4(); const tempPurData = { ...ProduData2, BalanceQty: JSON.stringify(order?.OrderQty), InwardPrice: 0, PurcDisc: 0, Amount: 0, WhSalePrice: 0, ReceivedQty: order?.OrderQty, AcceptedQty: JSON.stringify(order?.OrderQty), RejectedQty: 0, OfferPrice: 0, SpecialPrice: 0, ProdVariantName: order?.ProdVariantName, FreeItem: 0, TaxAmt: 0, TaxType: SelectedPurcTaxType || 0, PurcDiscType: 'P', localId: uniqueId, }; form.setFieldsValue({ [`BalanceQty${uniqueId}`]: JSON.stringify(order?.OrderQty), [`ReceivedQty${uniqueId}`]: order?.OrderQty, [`AcceptedQty${uniqueId}`]: JSON.stringify(order?.OrderQty), }); return tempPurData; }); const filterOrders = orderedData?.filter( (order) => order?.ProdId !== null && order?.ProdId !== undefined ); if (filterOrders?.length > 0) { setPurchaseOrderId(filterOrders[0]?.PurOrderInvoiceNo); } setPurchaseData(filterOrders); if (unMappedProducts?.length > 0) { setMessageType('error'); setMessageData( `Please map the products that are not mapped with the selected supplier.` ); } }; const handleOrderTypeChange = (checked) => { const isNewOrder = checked; const supplierData = isNewOrder ? SupplierData?.find((supplier) => supplier?.SuppName === 'Self')?.SuppId : null; setOrderType(isNewOrder); setSelectedInvoice(null); setSearchText(null); setSelectedSupplierName(!isNewOrder); setSupplierOpen(isNewOrder ? 'own' : null); setSelectedSupplierData(supplierData); setPurchaseData([]); // setSelectedProductData(null); setSelectedProductName(null); // setselectedProductVariantData(null); setInvoiceType('I'); setPurchaseStatus('P'); setProductData([]); handleSupplierBasedProduct(supplierData); formRef?.current?.setFieldsValue({ InvoiceType: 'I', PurchaseOrderNo: null, SuppInvoiceNo: null, CustSuppId: supplierData, ProdId: null, OrderType: isNewOrder ? 'N' : 'O', VarProdId: null, }); form?.resetFields(); }; useEffect(() => { if (additionalInfoModal) { productAddInfoRef?.current?.setFieldsValue({ ReceivedQty: selectedRowRecord?.ReceivedQty, RejectedQty: selectedRowRecord?.RejectedQty, AcceptedQty: selectedRowRecord?.AcceptedQty, FreeItem: selectedRowRecord?.FreeItem, OfferPrice: selectedRowRecord?.OfferPrice, WhSalePrice: selectedRowRecord?.WhSalePrice, SpecialPrice: selectedRowRecord?.SpecialPrice, MRP: selectedRowRecord?.MRP, SellPrice: selectedRowRecord?.SellPrice, AmountPerPiece: selectedRowRecord?.AmountPerPiece, NumberofPieceinside: selectedRowRecord?.NumberofPieceinside, }); if (applicationRestrictedFields.BatchAndModelDetails) { productAddInfoRef?.current?.setFieldsValue({ BatchRef: selectedRowRecord?.BatchRef, ModelNumber: selectedRowRecord?.ModelNumber, }); } if (applicationRestrictedFields.DatesAndExpiry) { productAddInfoRef?.current?.setFieldsValue({ ManufDate: selectedRowRecord?.ManufDate, ExpDate: selectedRowRecord?.ExpDate, }); } } }, [additionalInfoModal]); // command const validateSellPrice = (record) => (_, value) => { if (!value) { return Promise.reject('Selling Price is required'); } if (!/^[1-9]\d*(\.\d+)?$/.test(value)) { return Promise.reject('Please enter a valid selling price'); } const mrp = record?.MRP; // const mrp = productAddInfoRef?.current?.getFieldValue('MRP'); if (parseFloat(value) > parseFloat(mrp)) { return Promise.reject( 'Please enter selling price less than or equal to MRP' ); } return Promise.resolve(); }; const handleModelDataOpen = (selectedRowRecord) => { const acceptedQty = parseInt(selectedRowRecord?.AcceptedQty) || 0; const productIdentifiers = selectedRowRecord?.ProductIdentifierDtls || []; let finalCombined = productIdentifiers.map((device, idx) => ({ key: idx, column1: `Row ${idx + 1} Col 1`, imei1: device?.IMEI1 || null, imei2: device?.IMEI2 || null, Macid: device?.MacId || null, serialno: device?.SerialNumber || null, })); if (finalCombined.length > 0) { if (finalCombined.length < acceptedQty) { const rowsToAdd = acceptedQty - finalCombined.length; for (let i = 0; i < rowsToAdd; i++) { finalCombined.push({ key: finalCombined.length + i, column1: `Row ${finalCombined.length + i + 1} Col 1`, imei1: null, imei2: null, Macid: null, serialno: null, }); } } setDataSource(finalCombined); setimeiSerialOpen(true); } else { if (acceptedQty > 0) { if (dataSourceBackup.length === 0 || dataSource.length === 0) { const newEmptyData = Array(acceptedQty) .fill(null) .map((_, index) => ({ key: index, column1: `Row ${index + 1} Col 1`, })); setDataSource(newEmptyData); } else { setDataSource(dataSourceBackup); } setimeiSerialOpen(true); } else { setMessageType('error'); setMessageData('Enter Qty'); } } }; const handleModelDataSumbitOrClose = () => { setimeiSerialOpen(false); const productIdentifierDtls = dataSource ?.filter( (item) => item.serialno || item.imei1 || item.imei2 || item.Macid ) ?.map((item) => ({ SerialNumber: item.serialno || '', IMEI1: item.imei1 || '', IMEI2: item.imei2 || '', MacId: item.Macid || '', })); const newData = PurchaseData.map((item, index) => index === selectedRowIndex ? { ...item, ProductIdentifierDtls: productIdentifierDtls } : item ); setPurchaseData(newData); }; const handleFieldSetupSubmit = async ({ selectedFields, tempSelectedColumns, closeModal, resetTemp, }) => { const postData = { AppId, CompId, BranchId, Type: 'PE', FormType: 'Purchase Entry', TypeId: categoryId, ConfigDtl: selectedFields.map((field) => ({ ConfigId: field, Access: 'Y', })), CreatedBy: UserId, }; const response = await dispatch(postFieldSetup(postData))?.unwrap(); if (response?.data?.statusCode === 1) { setSelectedAdditionalColumn([...tempSelectedColumns]); closeModal(); resetTemp(); setMessageType('success'); setMessageData(response?.data?.response); await getFieldSetup(); } else { setMessageType('error'); setMessageData('Failed to set up fields'); } }; const handleModalSubmited = () => { setIsModalOpen(false); }; const handleSupplierBasedProduct = async (SuppId) => { const Type = SupplierData?.find((find) => find.SuppId === SuppId)?.Type; const LocationType = Type === 'Supplier' ? 'S' : Type === 'Branch' ? 'B' : Type === 'WareHouse' ? 'W' : ''; const productResponse = await dispatch( getSupplaierIdwithTypeBasedProducts({ CompId, AppId, BranchId, SuppId, LocationType, }) ).unwrap(); setPurchaseData([]); if (productResponse?.data?.statusCode === 1) { setProductData(productResponse?.data?.data); return productResponse?.data?.data; } else { setProductData([]); return []; } }; const validatePhoneNumber = (rule, value, callback) => { if (value && value?.length !== 10) { callback(); } else { callback(); } }; const validateEmail = (rule, value, callback) => { const regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/; if (!value || regex.test(value)) { callback(); } else { callback('Please enter a valid Mail Id'); } }; const deliveryPerformance = async () => { let response = await dispatch( getConfigType({ TypeName: 'Delivery Performance' }) ).unwrap(); SetDeleveryPerformanceData(response?.data?.data); }; const discountLevel = async () => { let response = await dispatch( getConfigType({ TypeName: 'Discount Level' }) ).unwrap(); setDiscountData(response?.data?.data); }; const qualityofSupp = async () => { let response = await dispatch( getConfigType({ TypeName: 'Quality Of Supplier' }) ).unwrap(); setQualityData(response?.data?.data); }; const handleDeliveryPerformanceChange = (value) => { formSupplierRef?.current?.setFieldsValue({ DeliveryPerformance: value }); setDeliveryValue(value); }; const handleDiscountLevelChange = (value) => { formSupplierRef?.current?.setFieldsValue({ DiscountLevel: value }); setDicountValue(value); }; const handleQualityofSuppChange = (value) => { formSupplierRef?.current?.setFieldsValue({ QualityofSupp: value }); setQualityValue(value); }; const ViewMoreFields = () => setViewDtl((prev) => !prev); const handlePaymentModeChange = (modeId) => { setPayAmountDisable( paymentOptions ?.find((option) => option?.ModeId === modeId) ?.ModeName?.toLowerCase() === 'credit' ); setSelectedPaymentMode(modeId); formRef.current?.setFieldsValue({ PaymentMode: modeId }); }; return (
{isLoading && (
{loadingText &&
{loadingText}
}
)}
setExtractorModalVisible(true)} > {' '}

Scan Receipt (Auto-Fill)

navigate(`${subDirectory}setting/purchase-entry`) } >

View Entry List

{/*

Supplier Details

*/}
{!orderType && ( Purchase Order No. } isOnChange={searchText ? true : false} > option.label ?.toLowerCase() .includes(inputValue?.toLowerCase()) } /> )}
index === self.findIndex( (t) => t.SuppId === obj.SuppId ) // remove dup SuppId ).map((option) => ({ key: `${option.SuppId}-${option.Type}`, // 👈 unique key value: option.SuppId, label: option.Type === 'Branch' ? `${option.SuppName} (${option.Type}) [${option.SuppId}]` : `${option.SuppName} (${option.Type})`, })) : [] } label={ } className="field-DropDown" onChangeFunction={handleSupplierDropDownChange} valueData={selectedSupplierData} disabled={ editstate?.SuppId ? true : !orderType ? true : false } /> {orderType && { const checked = e.target.checked; setShowAllSuppliers(checked); setInitialLoad(true); getSuplaierApi({ Type: checked ? 'Y' : null }); }} > All }
{!selectedSupplierName && ( SupplierOpenfun(e)} /> )}
Order Type
{(SupplierOpen !== 'own' || selectedSupplierName) && selectedSupplierData && ( <> { await validateSafeInput(value); if (value?.length > 30) { if (invoiceType === 'I') { return Promise.reject( 'Invoice Number cannot exceeds more than 30 chars' ); } return Promise.reject( 'Delivery Challan cannot exceeds more than 30 chars' ); } return Promise.resolve(); }, }, ]} >
{invoiceType === 'I' ? 'Supplier Invoice Number' : 'Delivery Challan No.'} } onChange={handleSuppInvoiceNoChange} isOnChange={ extractorData?.invoiceNo ? true : false } value={extractorData?.invoiceNo} />
)}
{(SupplierOpen !== 'own' || selectedSupplierName) && selectedSupplierData && (
<> ({ value: option.ConfigId, label: option.ConfigName === 'Cash' ? 'Paid' : option.ConfigName, }))} label={ } className="field-DropDown" onChangeFunction={handlePurchaseTypeChange} valueData={SelectedPurchaseType} disabled={editstate?.SuppId ? true : false} /> {PurchaseTypeData?.some( (item) => item.ConfigId === SelectedPurchaseType && item.ConfigName === 'Cash' ) && ( <> ({ value: mode.ModeId, label: mode.ModeName, }))} label={ } className="field-DropDown" onChangeFunction={handlePaymentModeChange} valueData={selectedPaymentMode} /> { if ( value === undefined || value === null || value === '' ) { return Promise.resolve(); } if (Number(value) === 0) { return Promise.reject( 'Payment Amount cannot be 0' ); } if ( isNaN(value) || Number(value) < 0 ) { return Promise.reject( 'Payment Amount cannot be less than 0' ); } return Promise.resolve(); }, }, ]} > Payment Amount } inputMode="decimal" disable={!payAmountDisable} isOnChange={paymentAmount ? true : false} min={0} type="number" value={paymentAmount} onChange={(e) => { formRef?.current?.setFieldsValue({ PaymentAmount: e?.target?.value, }); setPaymentAmount(e?.target?.value); }} /> )}
)}
{ const [prodId, variantName] = option?.value?.split('_'); const product = productData.find( (p) => p.ProdId === prodId && (p.ProdVariantName || 'Variant1') === variantName ); const nameMatch = option.label ?.toLowerCase() .includes(productSearchText?.toLowerCase()); const qrMatch = product?.QRCode?.toLowerCase() == productSearchText?.toLowerCase(); return nameMatch || qrMatch; }} options={ !scanner ? productData?.map((option) => ({ value: `${option.ProdId}_${option.ProdVariantName}`, label: `${option.ProdName} (${option.Size} ${option.UomName})${option?.BrandName ? ` - ${option?.BrandName}` : ''} - ${option.ProdVariantName}`, })) : [] } // onSelect={async (value, option) => { // const [prodId, variantName] = value?.split('_'); // const product = productData.find( // (p) => // p.ProdId === prodId && // p.ProdVariantName === variantName // ); // const newProduct = await ProductDropDownChange( // product?.ProdVariantName, // prodId, // option // ); // if (newProduct) { // form?.setFieldsValue({ // [`SellPrice${newProduct?.localId}`]: // newProduct?.SellPrice, // [`PurchaseTax${newProduct?.localId}`]: // newProduct?.PurchaseTax, // }); // setPurchaseData([ // newProduct, // ...PurchaseData, // ]); // } // }} onSelect={(value, option) => { handleProductSelect(value, option); }} onSearch={handleProductSearch} onKeyDown={(e) => { if (scanner && e.key === 'Enter') { e.preventDefault(); } }} style={{ width: '250px' }} >
setIsModalOpen(true)} size={18} />
{isModalOpen && ( { (setIsModalOpen(false), handleSupplierDropDownChange( selectedSupplierData )); }} CompId={CompId} BranchId={BranchId} AppId={AppId} setMessage={setMessage} onMappingAdded={handleModalSubmited} /> )}
} onChange={(e) => { const value = e.target.value.toLowerCase(); setSearchValue(value); }} style={{ width: '300px' }} />
{/*
*/}
{PurchaseData?.length > 0 && (
{PurchaseData.reduce( (acc, data) => acc + data?.Amount, 0 )?.toFixed(2)}
{!orderType && (
)}
)} } /> {OpenSupplierModel && (
{ await validateSafeInput(value); if (value?.length > 30) { return Promise.reject( 'Supplier Name cannot exceeds more than 30 chars' ); } return Promise.resolve(); }, }, ]} > Supplier Name} autocomplete="off" /> { await validateSafeInput(value); // To block HTML tags & SQL keywords return Promise.resolve(); }, }, ]} > Address} /> { await validateSafeInput(value); // To block HTML tags & SQL keywords return Promise.resolve(); }, }, ]} > Zipcode} maxLength="6" onChange={pinCodeChange} />

{' '} {ViewDtl ? 'Less More' : 'View More'}

{ViewDtl && ( <> Mobile Number} maxLength="10" autocomplete="off" // isOnChange={formType == 'edit' ? true : false} inputMode="numeric" onInput={(e) => (e.target.value = e.target.value?.replace( /[^0-9]/g, '' )) } /> MailId} autocomplete="off" // isOnChange={formType == 'edit' ? true : false} /> { await validateSafeInput(value); if (value?.length > 30) { return Promise.reject( 'Point of Contact cannot exceeds more than 30 chars' ); } return Promise.resolve(); }, }, ]} > Point of Contact} autocomplete="off" // isOnChange={formType == 'edit' ? true : false} /> POC Mobile Number} autocomplete="off" maxLength="10" // isOnChange={formType == 'edit' ? true : false} /> POC MailId} autocomplete="off" // isOnChange={formType == 'edit' ? true : false} /> ({ value: option.ConfigId, label: option.ConfigName, }))} label={} className="field-DropDown" id="DeliveryPerformance" onChangeFunction={(e) => handleDeliveryPerformanceChange(e) } // isOnChange={formType == 'edit' ? true : false} valueData={Delivery} /> ({ value: option.ConfigId, label: option.ConfigName, }))} label={} className="field-DropDown" id="DiscountLevel" onChangeFunction={(e) => handleDiscountLevelChange(e)} // isOnChange={formType == 'edit' ? true : false} valueData={DicountValue} /> ({ value: option.ConfigId, label: option.ConfigName, }))} label={} className="field-DropDown" id="QualityofSupp" onChangeFunction={(e) => handleQualityofSuppChange(e)} // isOnChange={formType == 'edit' ? true : false} valueData={QualityValue} /> )} {zipCodeData ? ( <> { await validateSafeInput(value); // To block HTML tags & SQL keywords return Promise.resolve(); }, }, ]} > { await validateSafeInput(value); // To block HTML tags & SQL keywords return Promise.resolve(); }, }, ]} > { await validateSafeInput(value); // To block HTML tags & SQL keywords return Promise.resolve(); }, }, ]} > ) : ( '' )}
)}
{imeiSerialOpen && (
'editable-row'} bordered dataSource={dataSource} columns={IMEIcolumns} pagination={{ showSizeChanger: false }} /> )} setExtractorModalVisible(false)} onApply={handleExtractorApply} productData={productData} supplierData={SupplierData} uomData={UomData} setVisible={setExtractorModalVisible} /> ); }; export default StockForm;