Android_Retail/src/Pages/StockMaster/StockForm.jsx

5850 lines
204 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
InfoCircleOutlined,
SearchOutlined,
} from '@ant-design/icons';
import {
Form,
Tooltip,
Table,
Input,
Collapse,
AutoComplete,
Switch,
} from 'antd';
import { IoAddCircleSharp, IoSettingsOutline } from 'react-icons/io5';
import { ScannerInputField } from '../../Components/Forms/ScannerInputField.jsx';
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 { DatePic } from '../../Components/Forms/DatePicker.jsx';
import { RadioGrpButton } from '../../Components/Forms/RadioGroup.jsx';
import Imageupload from '../../Components/Forms/Upload.jsx';
import moment from 'moment';
import barcodeimg from '../../Images/barcodeimg.png';
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
import { BsUpcScan } from 'react-icons/bs';
import { debounce } from 'lodash';
import {
SupplierDataSelector,
productDataSelector,
getProductData,
getSupplierData,
getVariantData,
getPurchaseTypeData,
getPurchaseTaxTypeData,
postPurchaseData,
getProdvaraiantdata,
} from '../../Features/StockMaster/StockMaster.js';
import '../../Styles/Stock/StockMaster.scss';
import {
getAdmin,
prodTaxDataSelector,
taxSelector,
getUomData,
getProdCatData,
getProdSubCatData,
getBrandData,
uomDataSelector,
prodCatDataSelector,
prodSubCatDataSelector,
brandDataSelector,
postProductData,
getConfigTypeData,
postTax,
postSupplier,
getQrcodeData,
getsingleQrcodeData,
productTypeDataSelector,
getProductTypeData,
bulkpostdata,
postFieldSetup,
getFieldSetupData,
} from '../../Features/ProductPage/ProductPage.js';
import { postConfiguration } from '../../Features/ConfigMasterPage/ConfigMasterPage.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 { color } from 'highcharts';
import { v4 as uuidv4 } from 'uuid';
const subDirectory = import.meta.env.BASE_URL;
const EditableContext = React.createContext(null);
const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
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 ? (
<Form.Item
style={{
margin: 0,
}}
name={dataIndex}
// rules={[
// (dataIndex == "imei1" || dataIndex == "imei2") && {
// pattern: /^[0-9]{15}$/,
// message: 'IMEI must be a 15-digit number'
// }
// ]}
>
<Input
ref={inputRef}
onPressEnter={save}
onBlur={save}
onMouseLeave={save}
value={
Array.isArray(record[dataIndex]) ? undefined : record[dataIndex]
}
/>
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{
paddingRight: 24,
cursor: 'pointer',
}}
onClick={toggleEdit}
>
<Input
ref={inputRef}
onPressEnter={save}
onBlur={save}
value={
Array.isArray(record[dataIndex]) ? undefined : record[dataIndex]
}
/>
</div>
);
}
return <td {...restProps}>{childNode}</td>;
};
const StockForm = ({ formType }) => {
const { Panel } = Collapse;
const formRef = useRef(null);
const productAddInfoRef = useRef(null);
const formProductRef = useRef(null);
const formCategoryRef = useRef(null);
const formSubCategoryRef = useRef(null);
const formBrandRef = useRef(null);
const formTaxRef = 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 [SupplierAppId, setSupplierAppId] = useState(getSession('AppId'));
const [SupplierBranchId, setSupplierBranchId] = useState(
getSession('BranchId')
);
const [SupplierCompId, setSupplierCompId] = useState(getSession('CompId'));
const UserId = getSession('UserId');
const ProdCatData = useSelector(prodCatDataSelector);
const ProdSubCatData = useSelector(prodSubCatDataSelector);
const ProdTaxData = useSelector(prodTaxDataSelector);
const TaxData = useSelector(taxSelector);
const BrandData = useSelector(brandDataSelector);
const UomData = useSelector(uomDataSelector);
const ProductTypeData = useSelector(productTypeDataSelector);
const appPreferences = useSelector(ApplicationPreferences);
const [applicationRestrictedFields, setApplicationRestrictedFields] =
useState({
DatesAndExpiry: false,
BatchAndModelDetails: false,
AmountPerPieceDetail: false,
});
const [selectedAdditionalColumn, setSelectedAdditionalColumn] = useState([]);
console.log(selectedAdditionalColumn, 'selectedAdditionalColumn');
const [showColumnModal, setShowColumnModal] = useState(false);
const [tempSelectedColumns, setTempSelectedColumns] = useState([]);
const [tableFieldPreferences, setTableFieldPreferences] = useState([]);
const [selectedFields, setSelectedFields] = useState([]);
const [SupplierData, setSupplierData] = useState([]);
const [StockOpen, setStockOpen] = useState('N');
const [SupplierOpen, setSupplierOpen] = useState('own');
const [purchaseOrderList, setPurchaseOrderList] = useState([]);
const [selectedSupplierName, setSelectedSupplierName] = useState();
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [productName, setProductName] = useState(null);
const [searchText, setSearchText] = useState(null);
const [productSearchText, setProductSearchText] = useState('');
const [selectedInvoice, setSelectedInvoice] = useState(null);
const [orderType, setOrderType] = useState(true);
const [invoiceNo, setInvoiceNo] = useState(null);
const [PurchaseTypeData, setPurchaseTypeData] = useState(null);
const [SelectedPurchaseType, setSelectedPurchaseType] = useState(null);
const [PurcTaxTypeData, setPurcTaxTypeData] = useState(null);
const [SelectedPurcTaxType, setSelectedPurcTaxType] = useState(null);
const [SelectedUom, setSelectedUom] = useState(null);
const [SelectedBrand, setSelectedBrand] = useState(null);
const [SelectedProdCat, setSelectedProdCat] = useState(null);
const [SelectedProdSubCat, setSelectedProdSubCat] = useState(null);
const [SelectedTaxId, setSelectedTaxId] = useState(null);
const [SelectedCategory, setSelectedCategory] = useState(null);
const [SelectedSubCategory, setSelectedSubCategory] = useState(null);
const [SelectedTaxNameId, setSelectedTaxNameId] = useState(null);
const [OpenAdd, setOpenAdd] = useState(false);
const [imageCategoryUrl, setCategoryImageUrl] = useState('');
const [imageSubCategoryUrl, setSubCategoryImageUrl] = useState('');
const [imageBrandUrl, setBrandImageUrl] = useState('');
const [PurchaseData, setPurchaseData] = useState([]);
console.log(PurchaseData, 'PurchaseData');
const [additionalInfoModal, setAdditionalInfoModal] = useState(false);
const [selectedRowIndex, setSelectedRowIndex] = useState(null);
const [selectedRowRecord, setSelectedRowRecord] = useState({});
const [purchaseOrderId, setPurchaseOrderId] = useState();
const [VariantData1, setVariantData1] = useState([]);
const [selectedProductData, setSelectedProductData] = useState(null);
const [selectedProductVariantData, setselectedProductVariantData] =
useState(null);
const [selectedProductName, setSelectedProductName] = useState(null);
const [scanner, setScanner] = useState(false);
const [Variants, setVariants] = useState();
const [Delete, setDelete] = useState(false);
const [selectedSupplierData, setSelectedSupplierData] = useState(null);
const [inwardDate, setInwardDate] = useState(new Date().toJSON());
const [selectedVariantName, setSelectedVariantName] = useState(null);
const [SelInvoiceAmount, setSelInvoiceAmount] = useState(null);
const [TotalTaxAmount, setTotalTaxAmount] = useState(null);
const [SuppInvoiceDate, setSuppInvoiceDate] = useState();
const [invoiceType, setInvoiceType] = useState('I');
const [InvoiceDate, setInvoiceDate] = useState();
const [PurchaseDate, setPurchaseDate] = useState();
const [paymentAmount, setPaymentAmount] = useState(null);
const [AddProductDetail, setAddProductDetail] = useState();
const [OpenCategoryModel, setOpenCategoryModel] = useState(false);
const [OpenSubCategoryModel, setOpenSubCategoryModel] = useState(false);
const [OpenBrandModel, setOpenBrandModel] = useState(false);
const [OpenTaxModel, setOpenTaxModel] = useState(false);
const [OpenSupplierModel, setOpenSupplierModel] = useState(false);
const [zipCodeData, setZipCodeData] = useState(false);
const [expandCollapseActive, setExpandCollapseActive] = useState('1');
const [TokenOpen, setTokenOpen] = useState('N');
const [QrcodeAuto, setQrcodeAuto] = useState('N');
const [QrcodeAutoSingle, setQrcodeAutoSingle] = useState('N');
const [AmountPerPieceAvailable, setAmountPerPieceAvailable] = useState('N');
const [QrcodeFinalVal, setQrcodeFinalVal] = useState();
const [QrcodeSingleFinalVal, setQrcodeSingleFinalVal] = useState();
const [QrcodeExistsVal, setQrcodeExistsVal] = useState();
const [QrcodeSingleExistsVal, setQrcodeSingleExistsVal] = useState();
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([]);
console.log(productData, 'productData');
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());
useEffect(() => {
if (searchValue?.trim()) {
const search = searchValue.toLowerCase();
const filtered = PurchaseData.filter((item) =>
item?.ProdName?.toLowerCase().includes(search)
);
setFilteredPurchaseData(filtered);
} else {
setFilteredPurchaseData([]);
}
}, [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();
getPurchaseOrders();
getPurchaseType();
getPurchaseTaxType();
deliveryPerformance();
discountLevel();
qualityofSupp();
getSuplaierApi({});
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.',
});
}
};
fetchPaymentOptions();
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);
setSelectedVariantName(editstate?.ProdVariantName);
}
}, []);
useEffect(() => {
let UomId = UomData?.filter(
(item) => item.ConfigName?.toLowerCase() === 'pcs'
)?.[0]?.['ConfigId'];
formProductRef.current?.setFieldsValue({ UOM: UomId });
setSelectedUom(UomId);
}, [UomData, AddProductDetail]);
useEffect(() => {
let x = productData?.filter((e) => e.ProdId == selectedProductData);
setVariantData1(x?.[0]?.ProdVariantPriceDetails);
}, [selectedProductData]);
const getSuplaierApi = async ({ dataReturn = false }) => {
const response = await dispatch(
getPurchaseSupplierAndWareHouseData({ CompId, AppId, BranchId })
).unwrap();
if (response?.statusCode === 1) {
setSupplierData(response?.data);
if (dataReturn) {
return response?.data;
}
} else {
setSupplierData([]);
if (dataReturn) {
return [];
}
}
};
useEffect(() => {
if (formType == 'add') {
let ProductCatId = ProdCatData?.filter(
(item) => item.ConfigName?.toLowerCase() === 'general'
)?.[0]?.['ConfigId'];
dispatch(getProdSubCatData({ ConfigId: ProductCatId }));
formProductRef.current?.setFieldsValue({ ProdCat: ProductCatId });
setSelectedProdCat(ProductCatId);
}
}, [ProdCatData, AddProductDetail]);
useEffect(() => {
if (formType == 'add') {
let ProductSubCatId = ProdSubCatData?.filter(
(item) => item.ConfigName?.toLowerCase() === 'general'
)?.[0]?.['ConfigId'];
formProductRef.current?.setFieldsValue({ ProdSubCat: ProductSubCatId });
setSelectedProdSubCat(ProductSubCatId);
}
}, [ProdSubCatData, AddProductDetail]);
useEffect(() => {
if (formType == 'add') {
let TaxId = TaxData?.filter(
(item) => item.TaxIdName?.toLowerCase() === 'nil'
)?.[0]?.['TaxId'];
formRef.current?.setFieldsValue({ TaxId: TaxId });
setSelectedTaxId(TaxId);
}
}, [TaxData, AddProductDetail]);
useEffect(() => {
if (initialLoad && SupplierData?.length > 0) {
SetSelfSupplier();
setInitialLoad(false);
}
}, [SupplierData]);
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);
};
useEffect(() => {
const total = PurchaseData?.reduce((acc, item) => {
return acc + Number(item?.Amount || 0);
}, 0);
const invoiceAmount = !isNaN(total) && total !== 0 ? total : null;
setSelInvoiceAmount(invoiceAmount);
formRef.current?.setFieldsValue({
InvoiceAmount: invoiceAmount,
});
const totalTax = PurchaseData?.reduce((acc, item) => {
return acc + Number(item?.TaxAmt || 0);
}, 0);
setTotalTaxAmount(totalTax);
}, [PurchaseData]);
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 findMatchingSuppliers = async (name, mobile, supplierData) => {
let list = [];
console.log(name, mobile, 'listlistlist', supplierData);
// 1⃣ Mobile number takes full priority
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 };
};
useEffect(() => {
getFieldSetup();
}, [categoryId]);
const getFieldSetup = async () => {
try {
const response = await dispatch(
getFieldSetupData({ AppId, CompId, BranchId, categoryId, Type: 'PE' })
).unwrap();
if (response?.data?.statusCode === 1) {
console.log(response?.data?.data?.[0]?.ConfigDtl, 'Field Setup Data');
setSelectedFields(
response?.data?.data?.[0]?.ConfigDtl?.filter(
(c) => c.ConfigId && c.Access === 'Y'
)?.map((c) => c.ConfigId) || []
);
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: getSession('CompId'),
AppId: getSession('AppId'),
BranchId: getSession('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);
console.log('mohan Extractor data received:', 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;
}
console.log(supplierProducts, 'supplierProductssupplierProducts');
// 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);
}
});
console.log(NewImageProducts, 'NewImageProductsNewImageProducts');
// 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',
TaxId: '',
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 handleSellPrice = (rule, value, callback) => {
if (
parseInt(formProductRef?.current?.getFieldsValue()?.MRP) >=
parseInt(value)
) {
callback();
} else {
callback('Please enter retail less than MRP');
}
};
const handleInwardDateChange = (date) => {
console.log(date, 'date');
setInwardDate(date);
};
useEffect(() => {
if (extractorData && selectedSupplierData) {
console.log(
formRef?.current?.getFieldsValue(),
'formRefformRefformRefformRef'
);
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]);
// formRef?.current?.setFieldsValue({ SuppInvoiceNo: extractorData?.invoiceNo });
const handleSupplierDropDownChange = async (
SuppId,
option,
suppliers = null
) => {
let SuppDtl = (suppliers || SupplierData).filter(
(item) => item.SuppId == SuppId
)?.[0];
setSupplierAppId(SuppDtl?.SuppAppId);
setSupplierCompId(SuppDtl?.SuppCompId);
setSupplierBranchId(SuppDtl?.SuppBranchId);
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 onInvoiceDateChange = async (date, dateString) => {
if (dateString) {
const Date3 = moment(dateString, ['DD-MM-YYYY']).format(
'YYYY-MM-DDTHH:mm:ss'
);
formRef.current?.setFieldsValue({ InvoiceDate: Date3 });
setInvoiceDate(Date3);
} else if (dateString === '') {
setInvoiceDate();
}
};
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);
setSelectedProductData(ProdId);
// let x = (productsList || productData)?.find(
// (e) => e.ProdId == ProdId
// )?.ProdName;
let OnePcsAvailable =
(productsList || productData)?.find(
(e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName
)?.OnePcsAvailable == 'Y';
// let variantValues1 = await dispatch(
// getProdvaraiantdata({
// CompId: SupplierCompId,
// AppId: SupplierAppId,
// BranchId: SupplierBranchId,
// prodName: x,
// })
// ).unwrap();
// let variants = variantValues1?.data?.data;
// let cc = variants?.filter((variant) =>
// variant?.ProductDetail?.some((e) => e.ProdId == ProdId)
// )?.[0]?.ProductDetail;
// setVariants(
// cc?.[0]?.ProdVariantDetails?.map((detail) => ({
// ...detail,
// ProdIdProdName: `${detail.ProdVariantName} ${detail.ProdId}`,
// OnePcsAvailable,
// }))
// );
if (
true
// cc?.[0]?.ProdVariantDetails?.length < 2 ||
// (extractedProduct ? cc?.[0]?.ProdVariantDetails?.length > 0 : false)
) {
// let getSuppId = (productsList || productData)?.filter((item) => item.ProdId == ProdId);
formRef.current?.setFieldsValue({ ProdId: ProdId });
await setSelectedProductData(ProdId);
// await setSelectedSupplierData(getSuppId?.[0]?.["SuppId"]) ,CustSuppId:getSuppId?.[0]?.["SuppId"]
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,
// NumberofPieceinside: ProductData1?.NoOfPcs,
// AmountPerPiece: ProductData1?.OnePcsPrice,
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,
// ProdVariantName: 'Variant 1',
FreeItem: 0,
TaxAmt: 0,
TaxType: SelectedPurcTaxType ? SelectedPurcTaxType : 0,
PurcDiscType: 'P',
refImage: extractedItem?.parsedData?.image,
PurchaseHSNCode: extractedItem?.parsedData?.hsn || '',
localId: uuidv4(),
};
return tempPurData;
}
}
};
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
useEffect(() => {
return () => {
debouncedScannerSearch.cancel();
};
}, []);
const handleProductSearch = (value) => {
if (scanner) {
debouncedScannerSearch(value);
}
setProductSearchText(value);
setSelectedProductName(value);
setselectedProductVariantData([]);
setVariants([]);
};
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 handleTaxDropDownChange = async (TaxId) => {
formProductRef.current?.setFieldsValue({ TaxId: TaxId });
await setSelectedTaxId(TaxId);
};
const handleKeyPressSingle = (e) => {
// Prevent form submission on Enter key press
if (e.key === 'Enter') {
e.preventDefault();
}
};
const handleInput = async (val) => {
if (val?.target?.value?.length >= 5) {
let QRCodeData = await dispatch(
getQrcodeData({ QRCode: val?.target?.value })
).unwrap();
if (QRCodeData?.data?.statusCode == 0) {
setQrcodeFinalVal(val?.target?.value);
// setMessageType("success");
// setMessageData("Qrcode Added :" + `${val?.target?.value}`);
} else {
let existsQrcodeData = QRCodeData?.data?.data?.filter(
(item) =>
item?.AppId === AppId &&
item?.CompId === CompId &&
item?.BranchId === BranchId
);
if (existsQrcodeData?.length > 0) {
setQrcodeFinalVal(null);
formRef.current?.setFieldsValue({ QRCode: null });
setQrcodeExistsVal(existsQrcodeData?.[0]?.QRCode);
setMessageType('error');
setMessageData('Qrcode Already Exists');
} else {
// setQrcodeExistsData(QRCodeData.data?.data)
// setQrcodeExistsDataOpen(true)
setQrcodeFinalVal(val?.target?.value);
// setMessageType("success");
// setMessageData("Qrcode Added :" + `${val?.target?.value}`);
setQrcodeAuto('N');
}
}
}
};
const handleInputSingle = async (val) => {
setQrcodeSingleFinalVal(val?.target?.value);
if (val?.target?.value?.length >= 5) {
let QRCodeData = await dispatch(
getsingleQrcodeData({ QRCode: val?.target?.value })
).unwrap();
if (QRCodeData.data?.statusCode == 0) {
setQrcodeSingleFinalVal(val?.target?.value);
// setMessageType("success");
// setMessageData("Qrcode Added :" + `${val?.target?.value}`);
} else {
let existsQrcodeData = QRCodeData?.data?.data?.filter(
(item) =>
item?.AppId === AppId &&
item?.CompId === CompId &&
item?.BranchId === BranchId
);
if (existsQrcodeData?.length > 0) {
setQrcodeSingleFinalVal(null);
formRef.current?.setFieldsValue({ QRCodeSingle: null });
setQrcodeSingleExistsVal(val?.target?.value);
setMessageType('error');
setMessageData('Qrcode Already Exists');
} else {
// setQrcodeExistsData(QRCodeData.data?.data)
// setQrcodeExistsDataOpen(true)
setQrcodeSingleFinalVal(val?.target?.value);
// setMessageType("success");
// setMessageData("Qrcode Added :" + `${val?.target?.value}`);
setQrcodeAutoSingle('N');
}
}
}
};
const addSupplier = () => {
setOpenSupplierModel(true);
};
const handleSupplier = () => {
setOpenSupplierModel(false);
};
const handleCategory = () => {
setOpenCategoryModel(false);
setCategoryImageUrl('');
formCategoryRef?.current?.resetFields();
};
const handleSubCategory = () => {
setOpenSubCategoryModel(false);
setSubCategoryImageUrl('');
setSelectedCategory(null);
formSubCategoryRef?.current?.resetFields();
};
const handleBrand = () => {
setOpenBrandModel(false);
setBrandImageUrl('');
setSelectedSubCategory(null);
formBrandRef?.current?.resetFields();
};
const handleTax = () => {
setOpenTaxModel(false);
};
const submitCategory = async () => {
const categoryData = await formCategoryRef?.current?.validateFields();
const categoryTypeId = await dispatch(
getConfigTypeData({ TypeName: 'Product Category' })
).unwrap();
const addCategoryData = {
TypeId: categoryTypeId?.data?.data?.[0]?.TypeId,
ConfigName: categoryData?.ConfigName,
AlphaNumFId: AppId,
SmallIcon: imageCategoryUrl,
CreatedBy: UserId,
};
let response = {};
response = await dispatch(postConfiguration(addCategoryData)).unwrap();
if (response?.data?.statusCode == 1) {
setCategoryImageUrl('');
setMessageType('success');
setMessageData(response?.data?.response);
setOpenCategoryModel(false);
dispatch(getProdCatData({ AppId: AppId }));
formCategoryRef?.current?.resetFields();
} else {
setCategoryImageUrl('');
setMessageType('error');
setMessageData(response?.data?.response);
formCategoryRef?.current?.resetFields();
}
};
const submitSubCategory = async () => {
const subCategoryData = await formSubCategoryRef?.current?.validateFields();
const subCategoryTypeId = await dispatch(
getConfigTypeData({ TypeName: 'Product Sub-Category' })
).unwrap();
const addSubCategoryData = {
TypeId: subCategoryTypeId?.data?.data?.[0]?.TypeId,
ConfigName: subCategoryData?.SubConfigName,
AlphaNumFId: AppId,
NumFId: SelectedCategory,
SmallIcon: imageSubCategoryUrl,
CreatedBy: UserId,
};
let response = {};
response = await dispatch(postConfiguration(addSubCategoryData)).unwrap();
if (response?.data?.statusCode == 1) {
setSubCategoryImageUrl('');
setMessageType('success');
setMessageData(response?.data?.response);
setOpenSubCategoryModel(false);
setSelectedCategory(null);
dispatch(getProdSubCatData({ ConfigId: SelectedCategory }));
formSubCategoryRef?.current?.resetFields();
} else {
setSubCategoryImageUrl('');
setSelectedCategory(null);
setMessageType('error');
setMessageData(response?.data?.response);
formSubCategoryRef?.current?.resetFields();
}
};
const submitBrand = async () => {
const subBrandData = await formBrandRef?.current?.validateFields();
const subBrandTypeId = await dispatch(
getConfigTypeData({ TypeName: 'Product Brand' })
).unwrap();
const addBrandData = {
TypeId: subBrandTypeId?.data?.data?.[0]?.TypeId,
ConfigName: subBrandData?.SubConfigName,
AlphaNumFId: AppId,
NumFId: SelectedSubCategory,
SmallIcon: imageBrandUrl,
CreatedBy: UserId,
};
let response = {};
response = await dispatch(postConfiguration(addBrandData)).unwrap();
if (response?.data?.statusCode == 1) {
setBrandImageUrl('');
setMessageType('success');
setMessageData(response?.data?.response);
setOpenBrandModel(false);
setSelectedSubCategory(null);
dispatch(getBrandData({ ConfigId: SelectedSubCategory }));
formBrandRef?.current?.resetFields();
} else {
setBrandImageUrl('');
setSelectedSubCategory(null);
setMessageType('error');
setMessageData(response?.data?.response);
formBrandRef?.current?.resetFields();
}
};
const submitTax = async () => {
const subTaxData = await formTaxRef?.current?.validateFields();
const effectiveDate = new Date(subTaxData.EffectiveFrom);
const formattedDate = effectiveDate.toLocaleDateString('en-CA');
const addTaxData = {
CompId: getSession('CompId'),
AppId: getSession('AppId'),
TaxName: subTaxData?.TaxName,
TaxPercentage: subTaxData?.TaxPercentage,
EffectiveFrom: formattedDate,
Reference: subTaxData?.Reference,
CreatedBy: UserId,
};
let response = {};
response = await dispatch(postTax(addTaxData)).unwrap();
if (response?.data?.statusCode == 1) {
setMessageType('success');
setMessageData(response?.data?.response);
setOpenTaxModel(false);
dispatch(getAdmin({ CompId: CompId, AppId: AppId }));
formTaxRef?.current?.resetFields();
} else {
setMessageType('error');
setMessageData(response?.data?.response);
formTaxRef?.current?.resetFields();
}
};
const submitSupplier = async () => {
const subSupplierData = await formSupplierRef?.current?.validateFields();
const addSupplierData = {
CompId: getSession('CompId'),
AppId: getSession('AppId'),
BranchId: getSession('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();
}
};
const getOptionLabel = (option, selected) => {
return selected
? option.TaxPercentage + ' %'
: option.TaxIdName + ' - ' + option.TaxPercentage + ' % ';
};
const isEditing = (record, index) => record?.localId === editingKey;
const edit = (record, index) => {
const localId = record?.localId;
form.setFieldsValue({ ...record });
setEditingKey(localId);
setindex(localId);
if (Delete) {
form.setFieldsValue({
[`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,
});
setDelete(false);
} else {
form.setFieldsValue({
[`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 (applicationRestrictedFields.BatchAndModelDetails) {
form.setFieldsValue({
[`BatchRef${localId}`]: record?.BatchRef,
});
}
}
};
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 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 = [
{
title: 'SL.NO',
align: 'center',
key: 'sno',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{index + 1}</a>
),
},
{
title: 'Name',
dataIndex: 'ProdName',
key: 'ProdName',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.ProdName}</a>
),
},
{
title: 'Variant',
dataIndex: 'ProdVariantName',
key: 'ProdVariantName',
align: 'left',
render: (text, record, index) => (
<a style={{ color: 'black' }}>{record?.ProdVariantName}</a>
),
},
{
title: 'Uom',
dataIndex: 'UomName',
key: 'UOMName',
},
{
title: 'Qty',
dataIndex: 'BalanceQty',
key: 'BalanceQty',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'BalanceQty' + record?.localId}
rules={[
{
required: true,
pattern: /^(0+\d*[1-9]\d*|[1-9]\d*|0\.\d+)(\.\d+)?$/,
message: 'Please enter quantity',
},
{
validator: (_, value) => {
if (value?.length > 10) {
return Promise.reject(
'Quantity cannot exceeds more than 10 chars'
);
}
return Promise.resolve();
},
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record)}
onBlur={(e) => handleQtyChange(e, record)}
onChange={(e) => handleQtyChange(e, record)}
inputMode="decimal"
onInput={(e) => {
let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); // Remove invalid characters
const parts = cleanedValue.split('.');
if (cleanedValue.startsWith('.')) {
cleanedValue = '0' + cleanedValue;
}
e.target.value =
parts.length > 2
? `${parts[0]}.${parts.slice(1).join('')}`
: cleanedValue;
}}
/>
</Form.Item>
) : (
text
);
},
},
{
title: (
<Tooltip title="Purchase rate per unit" placement="top">
Purchase Rate/unit
</Tooltip>
),
dataIndex: 'InwardPrice',
key: 'InwardPrice',
width: 120,
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'InwardPrice' + record?.localId}
rules={[
{
required: true,
pattern: /^(0+\d*[1-9]\d*|[1-9]\d*|0\.\d+)(\.\d+)?$/,
message: 'Please enter Purchase Rate',
},
{
validator: (_, value) => {
if (value?.length > 10) {
return Promise.reject(
'Purchase Rate cannot exceeds more than 10 chars'
);
}
return Promise.resolve();
},
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => handlePurrateChange(e, record)}
onBlur={(e) => handlePurrateChange(e, record)}
inputMode="decimal"
onInput={(e) => {
let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); // Remove invalid characters
const parts = cleanedValue.split('.');
if (cleanedValue.startsWith('.')) {
cleanedValue = '0' + cleanedValue;
}
e.target.value =
parts.length > 2
? `${parts[0]}.${parts.slice(1).join('')}`
: cleanedValue;
}}
/>
</Form.Item>
) : (
text || 0
);
},
},
{
title: (
<Tooltip title="GST (CGST + SGST or IGST)" placement="top">
{' '}
Tax (%){' '}
</Tooltip>
),
dataIndex: 'PurchaseTax',
key: 'PurchaseTax',
// width: 120,
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={`PurchaseTax${record?.localId}`}
validateTrigger={['onChange', 'onBlur']}
rules={[
{
validator: (_, value) => {
if (value === undefined || value === '' || value === null) {
return Promise.resolve();
}
const stringValue = String(value).trim();
if (stringValue === '') {
return Promise.resolve();
}
const num = parseFloat(stringValue);
if (isNaN(num)) {
return Promise.reject('Invalid tax value');
}
if (num < 0) {
return Promise.reject('Tax cannot be negative');
}
if (num > 99) {
return Promise.reject('Tax cannot exceed 99%');
}
if (stringValue.length > 10) {
return Promise.reject('Tax cannot exceed 10 characters');
}
// Check for valid decimal format
if (!/^\d+(\.\d{1,2})?$/.test(stringValue)) {
return Promise.reject(
'Enter valid tax format (max 2 decimal places)'
);
}
return Promise.resolve();
},
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => handleTaxChange(e, record)}
onBlur={(e) => handleTaxChange(e, record)}
inputMode="decimal"
onInput={(e) => {
let value = e.target.value.replace(/[^0-9.]/g, '');
if (value.startsWith('.')) value = '0' + value;
const parts = value.split('.');
if (parts.length > 2) {
value = `${parts[0]}.${parts.slice(1).join('')}`;
}
e.target.value = value;
}}
/>
</Form.Item>
) : (
text || 0
);
},
},
{
title: 'Amount',
dataIndex: 'Amount',
key: 'Amount',
editable: true,
},
...(selectedAdditionalColumn.includes('Mrp')
? [
{
title: 'MRP',
dataIndex: 'MRP',
key: 'MRP',
editable: true,
// width: 150,
render: (text, record) => {
const localId = record.localId;
return isEditing(record) ? (
<Form.Item name={`MRP${localId}`}>
<Input
placeholder="MRP"
onChange={(e) => {
const value = e.target.value;
if (!/^\d*\.?\d*$/.test(value)) {
setMessageType('error');
setMessageData('Only numeric values are allowed');
return;
}
updateRowValues(record.localId, {
MRP: value,
SellPrice: value,
});
}}
onPressEnter={(e) => handleKeyPress(e, record)}
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
{
title: (
<Tooltip title="Selling price per unit" placement="top">
Selling Price
</Tooltip>
),
dataIndex: 'SellPrice',
key: 'SellPrice',
width: 70,
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={`SellPrice${record?.localId}`}
rules={[
{
validator: validateSellPrice(record),
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => handleSellPriceChange(e, record)}
onBlur={(e) => handleSellPriceChange(e, record)}
inputMode="decimal"
onInput={(e) => {
let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); // Remove invalid characters
const parts = cleanedValue.split('.');
if (cleanedValue.startsWith('.')) {
cleanedValue = '0' + cleanedValue;
}
e.target.value =
parts.length > 2
? `${parts[0]}.${parts.slice(1).join('')}`
: cleanedValue;
}}
/>
</Form.Item>
) : (
text || 0
);
},
},
...(selectedAdditionalColumn.includes('Amount Per Piece')
? [
{
title: 'Amount per piece',
dataIndex: 'OnePcsPrice',
key: 'OnePcsPrice',
width: 70,
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'OnePcsPrice' + record?.localId}
rules={[
{
required: false,
message: 'Please enter OnePcsPrice',
},
]}
>
<Input
disabled={record?.OnePcsAvailable == 'N'}
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => {
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, OnePcsPrice: e.target.value }
: item
);
setPurchaseData(newData);
}}
placeholder="OnePcsPrice"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Amount Per Piece')
? [
{
title: 'Number of piece',
dataIndex: 'NoOfPcs',
key: 'NoOfPcs',
width: 70,
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'NoOfPcs' + record?.localId}
rules={[
{
required: false,
message: 'Please enter NoOfPcs',
},
]}
>
<Input
disabled={record?.OnePcsAvailable == 'N'}
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => {
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, NoOfPcs: e.target.value }
: item
);
setPurchaseData(newData);
}}
placeholder="NoOfPcs"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Wholesale Price')
? [
{
title: 'Wholesale price',
dataIndex: 'WhSalePrice',
key: 'WhSalePrice',
width: 70,
editable: true,
render: (text, record) => {
return isEditing(record) ? (
<Form.Item
name={`WhSalePrice${record.localId}`}
rules={[
{
pattern: /^\d*\.?\d*$/,
message: 'Only numbers are allowed',
},
]}
>
<Input
placeholder="WhSalePrice"
inputMode="decimal" // 📱 numeric keyboard
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => {
const value = e.target.value;
// 🚫 block non-numeric
if (!/^\d*\.?\d*$/.test(value)) return;
updateRowValue(record.localId, 'WhSalePrice', value);
}}
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Manufacture Date')
? [
{
title: 'Manuf.Date',
dataIndex: 'ManufDate',
key: 'ManufDate',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'ManufDate' + record?.localId}
rules={[
{
required: false,
message: 'Please select manufacture date',
},
]}
>
<DatePicProd
canSelectPast={true}
onChange={(date, dateString) => {
const formattedDate =
dateString === ''
? undefined
: moment(dateString, ['DD-MM-YYYY']).format(
'YYYY-MM-DDTHH:mm:ss'
);
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, ManufDate: formattedDate }
: item
);
setPurchaseData(newData);
form.setFieldsValue({
[`ManufDate${record?.localId}`]: formattedDate,
});
}}
valueData={record?.ManufDate}
cancelFuture={true}
/>
</Form.Item>
) : (
formatDateForDisplay(text)
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Expiry Date')
? [
{
title: 'Exp.Date',
dataIndex: 'ExpDate',
key: 'ExpDate',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'ExpDate' + record?.localId}
rules={[
{
required: false,
message: 'Please select expiry date',
},
]}
>
<DatePicProd
canSelectPast={false}
onChange={(date, dateString) => {
const formattedDate =
dateString === ''
? undefined
: moment(dateString, ['DD-MM-YYYY']).format(
'YYYY-MM-DDTHH:mm:ss'
);
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, ExpDate: formattedDate }
: item
);
setPurchaseData(newData);
form.setFieldsValue({
[`ExpDate${record?.localId}`]: formattedDate,
});
}}
valueData={record?.ExpDate}
cancelFuture={false}
/>
</Form.Item>
) : (
formatDateForDisplay(text)
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Hsn')
? [
{
title: 'Hsn',
dataIndex: 'Hsn',
key: 'Hsn',
editable: true,
// width: 130,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'Hsn' + record?.localId}
rules={[
{
required: false,
message: 'Please enter HSN code',
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => {
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, PurchaseHSNCode: e.target.value }
: item
);
setPurchaseData(newData);
}}
placeholder="HSN code"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Model No')
? [
{
title: 'Model',
dataIndex: 'Model',
key: 'Model',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'Model' + record?.localId}
rules={[
{
required: false,
message: 'Please enter Model No',
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record, index)}
onChange={(e) => {
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, ModelNumber: e.target.value }
: item
);
setPurchaseData(newData);
}}
placeholder="Model No"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Batch No')
? [
{
title: 'Batch',
dataIndex: 'Batch',
key: 'Batch',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'Batch' + record?.localId}
rules={[
{
required: false,
message: 'Please enter Batch No',
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record, index)}
onChange={(e) => {
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? { ...item, BatchRef: e.target.value }
: item
);
setPurchaseData(newData);
}}
placeholder="Batch No"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Rejected Qty')
? [
{
title: 'Rejected Qty',
dataIndex: 'RejectedQty',
key: 'RejectedQty',
editable: true,
render: (text, record, index) => {
return isEditing(record, index) ? (
<Form.Item
name={'RejectedQty' + record?.localId}
rules={[
{
required: false,
message: 'Please enter Rejected Qty',
},
]}
>
<Input
onPressEnter={(e) => handleKeyPress(e, record, index)}
onChange={(e) => {
const inputValue = e.target.value;
const rejectedQty = parseFloat(inputValue) || 0;
const receivedQty = parseFloat(record.ReceivedQty) || 0;
if (inputValue !== '' && rejectedQty >= receivedQty) {
setMessageType('error');
setMessageData(
'Rejected Qty cannot be greater than or Equal to Received Qty'
);
form.setFieldsValue({
[`RejectedQty${record?.localId}`]:
record.RejectedQty || 0,
});
return;
}
const acceptedQty = receivedQty - rejectedQty;
const totalAmount =
acceptedQty * (parseFloat(record.InwardPrice) || 0);
const newData = PurchaseData.map((item) =>
item.localId === record?.localId
? {
...item,
RejectedQty: parseFloat(inputValue) || 0,
AcceptedQty: acceptedQty,
Amount: totalAmount,
}
: item
);
setPurchaseData(newData);
}}
placeholder="Rejected Qty"
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('Free Qty')
? [
{
title: 'Free Qty',
dataIndex: 'Freeqty',
key: 'Freeqty',
editable: true,
render: (text, record) => {
return isEditing(record) ? (
<Form.Item
name={`Freeqty${record.localId}`}
rules={[
{
pattern: /^\d*$/,
message: 'Only numbers are allowed',
},
]}
>
<Input
placeholder="Free Qty"
inputMode="numeric"
onPressEnter={(e) => handleKeyPress(e, record)}
onChange={(e) => {
const value = e.target.value;
// 🚫 block non-numeric
if (!/^\d*$/.test(value)) return;
updateRowValue(record.localId, 'Freeqty', value);
}}
/>
</Form.Item>
) : (
text
);
},
},
]
: []),
...(selectedAdditionalColumn.includes('IMEI')
? [
{
title: 'IMEI',
dataIndex: 'AdditionalInfo',
key: 'AdditionalInfo',
width: 120,
align: 'center',
render: (text, record, index) => {
const hasQty =
record?.ReceivedQty && parseFloat(record.ReceivedQty) > 0;
return (
<>
{' '}
<IoAddCircleSharp
style={{
cursor: hasQty ? 'pointer' : 'not-allowed',
color: hasQty ? '#1890ff' : '#d9d9d9',
}}
onClick={() => {
if (hasQty) {
setSelectedRowIndex(index);
handleModelDataOpen(record);
} else {
setMessageType('error');
setMessageData('Please Enter Qty');
}
}}
className="shape-preview"
/>
</>
);
},
},
]
: []),
{
title: 'Action',
dataIndex: 'Action',
key: 'Action',
align: 'center',
render: (_, record, index) => (
<a
onClick={(e) => {
e.stopPropagation();
}}
>
<DeleteFilled
style={{
color: '#FF4D4F',
}}
onClick={() => statusFormatters(record)}
/>
</a>
),
},
];
const statusFormatters = (record) => {
const localId = record?.localId;
// Remove row using localId (not index)
const data = PurchaseData.filter((item) => item?.localId !== localId);
setDelete(true);
// Clear form fields for this row
form.setFieldsValue({
[`BalanceQty${localId}`]: undefined,
[`ReceivedQty${localId}`]: undefined,
[`AcceptedQty${localId}`]: undefined,
[`RejectedQty${localId}`]: undefined,
[`Freeqty${localId}`]: undefined,
[`MRP${localId}`]: undefined,
[`ManufDate${localId}`]: undefined,
[`ExpDate${localId}`]: undefined,
[`SellPrice${localId}`]: undefined,
[`WhSalePrice${localId}`]: undefined,
[`PurcDiscType${localId}`]: undefined,
[`Amount${localId}`]: undefined,
[`InwardPrice${localId}`]: undefined,
[`PurcDisc${localId}`]: undefined,
[`offerSalePrice${localId}`]: undefined,
[`splSalePrice${localId}`]: undefined,
[`OnePcsPrice${localId}`]: undefined,
[`NoOfPcs${localId}`]: undefined,
});
setVariants(undefined);
setPurchaseData(data);
setSelectedProductData(null);
formRef?.current?.setFieldsValue({
ProdId: null,
});
};
const handleQtyChange = (e, record) => {
const { localId } = record;
const sourceData = PurchaseData;
const findIndex = sourceData.findIndex((item) => item?.localId === localId);
if (findIndex === -1) return;
const inputValue = e.target.value;
// ✅ Numeric validation
if (!/^\d*\.?\d*$/.test(inputValue)) {
setMessageType('error');
setMessageData('Only numeric values are allowed');
return;
}
const qty = Number(inputValue) || 0;
const acceptedQty = qty;
const newData = [...PurchaseData];
const item = newData[findIndex];
newData[findIndex] = {
...item,
Amount:
isNaN(Number(item?.InwardPrice)) || isNaN(acceptedQty)
? 0
: Number(item?.InwardPrice) * acceptedQty,
PurcDisc: 0,
BalanceQty: qty,
ReceivedQty: qty,
AcceptedQty: acceptedQty,
RejectedQty: 0,
ProductIdentifierDtls: [],
};
setPurchaseData(newData);
// ✅ Sync form values
form.setFieldsValue({
[`PurcDisc${localId}`]: 0,
[`BalanceQty${localId}`]: qty,
[`ReceivedQty${localId}`]: qty,
[`AcceptedQty${localId}`]: acceptedQty,
[`RejectedQty${localId}`]: 0,
});
};
const handlePurrateChange = (e, record) => {
const { localId, PurcDisc, PurcDiscType } = record;
const PurcRate = e.target.value;
// ✅ Numeric validation
if (!/^\d*\.?\d*$/.test(PurcRate)) {
setMessageType('error');
setMessageData('Only numeric values are allowed');
return;
}
const acceptedQty = Number(record?.AcceptedQty) || 0;
const rate = Number(PurcRate) || 0;
const amount = rate * acceptedQty;
// 🔍 Find correct index using localId
const findIndex = PurchaseData.findIndex(
(item) => item?.localId === localId
);
if (findIndex === -1) return;
const item = PurchaseData[findIndex];
// 🧮 Discount calculation
let discountAmt = 0;
if (PurcDiscType === 'P') {
discountAmt = (amount * Number(PurcDisc || 0)) / 100;
} else {
discountAmt = Number(PurcDisc || 0);
}
// 🧮 Tax calculation
const taxPercent = Number(item?.TaxPercentage || 0);
const taxAmt =
taxPercent > 0
? ((amount - discountAmt) * taxPercent) / (100 + taxPercent)
: 0;
// ✅ Update data immutably
const newData = [...PurchaseData];
newData[findIndex] = {
...item,
PurcDisc: 0,
InwardPrice: Delete ? 0 : rate,
Amount: !isNaN(amount) ? amount : 0,
TaxAmt: taxAmt.toFixed(2),
};
setPurchaseData(newData);
// 🔄 Update payment amount
const totalAmount = newData.reduce(
(acc, data) => acc + Number(data?.Amount || 0),
0
);
setPaymentAmount(totalAmount);
formRef?.current?.setFieldsValue({
PaymentAmount: totalAmount,
});
// 🔄 Sync row form fields
form.setFieldsValue({
[`PurcDisc${localId}`]: 0,
[`InwardPrice${localId}`]: Delete ? 0 : rate,
[`Amount${localId}`]: !isNaN(amount) ? amount : 0,
});
};
const handleSellPriceChange = (e, record) => {
const { localId } = record;
const value = e?.target?.value;
// ✅ Numeric validation
if (!/^\d*\.?\d*$/.test(value)) {
setMessageType('error');
setMessageData('Only numeric values are allowed');
return;
}
// 🔍 Find correct row using localId
const findIndex = PurchaseData.findIndex(
(item) => item?.localId === localId
);
if (findIndex === -1) return;
// ✅ Immutable update
const newData = [...PurchaseData];
newData[findIndex] = {
...newData[findIndex],
SellPrice: value,
};
setPurchaseData(newData);
// 🔄 Sync form field
form.setFieldsValue({
[`SellPrice${localId}`]: value,
});
};
const handleTaxChange = (e, record) => {
const { localId } = record;
const value = e?.target?.value;
// ✅ Numeric validation
if (!/^\d*\.?\d*$/.test(value)) {
setMessageType('error');
setMessageData('Only numeric values are allowed');
return;
}
const taxValue = Number(value) || 0;
// 🔍 Find correct row
const findIndex = PurchaseData.findIndex(
(item) => item?.localId === localId
);
if (findIndex === -1) return;
// ✅ Immutable update
const newData = [...PurchaseData];
newData[findIndex] = {
...newData[findIndex],
PurchaseTax: taxValue,
};
setPurchaseData(newData);
// 🔄 Sync form value
form.setFieldsValue({
[`PurchaseTax${localId}`]: taxValue,
});
};
const purchaseStatusChange = (value) => {
setPurchaseStatus(value);
};
const handleQuickAddCancel = () => {
setAddProductDetail(false);
formProductRef.current?.resetFields();
setOpenAdd(false);
setSelectedProdCat(null);
setSelectedProdSubCat(null);
setSelectedBrand(null);
};
const handleUomDropDownChange = async (ConfigId) => {
formProductRef.current?.setFieldsValue({ UOM: ConfigId });
setSelectedUom(ConfigId);
};
const handleBrandDropDownChange = async (ConfigId) => {
formProductRef.current?.setFieldsValue({ Brand: ConfigId });
setSelectedBrand(ConfigId);
};
const handleProdCatDropDownChange = async (ConfigId) => {
dispatch(getProdSubCatData({ ConfigId: ConfigId }));
formProductRef.current?.setFieldsValue({
ProdCat: ConfigId,
ProdSubCat: null,
});
setSelectedProdCat(ConfigId);
setSelectedProdSubCat(null);
};
const handleProdSubCatDropDownChange = async (ConfigId) => {
dispatch(getBrandData({ ConfigId: ConfigId }));
formProductRef.current?.setFieldsValue({
ProdSubCat: ConfigId,
Brand: null,
});
setSelectedProdSubCat(ConfigId);
setSelectedBrand(null);
};
const openToken = (value) => {
setTokenOpen(value);
};
const openQrcodeAuto = (value) => {
setQrcodeAuto(value);
};
const openQrcodeAutoSingle = (value) => {
setQrcodeAutoSingle(value);
};
const openAmountPerPieceAvailable = (value) => {
setAmountPerPieceAvailable(value);
};
const addCategory = () => {
setOpenCategoryModel(true);
};
const addSubCategory = () => {
setOpenSubCategoryModel(true);
};
const addBrand = () => {
setOpenBrandModel(true);
};
const addTax = () => {
setOpenTaxModel(true);
};
const handleCatDropDownChange = (value) => {
setSelectedCategory(value);
formSubCategoryRef?.current?.setFieldsValue({ CategoryId: value });
};
const handleSubCatDropDownChange = (value) => {
setSelectedSubCategory(value);
formBrandRef?.current?.setFieldsValue({ SubCategoryId: value });
};
const handleTaxNameDropDownChange = async (ConfigId) => {
formTaxRef.current?.setFieldsValue({ TaxName: ConfigId });
setSelectedTaxNameId(ConfigId);
};
const updateCategoryImageUrl = (url) => {
setCategoryImageUrl(url);
};
const updateSubCategoryImageUrl = (url) => {
setSubCategoryImageUrl(url);
};
const updateBrandImageUrl = (url) => {
setBrandImageUrl(url);
};
const openAdditionalDetails = () => {
setOpenAdd(OpenAdd ? false : true);
};
const openStock = (value) => {
setStockOpen(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 (099%) for all items'
);
return;
}
// ===============================
// 2⃣ SELL PRICE > MRP CHECK
// ===============================
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;
}
// ===============================
// 3⃣ NO PRODUCT CHECK
// ===============================
if (!PurchaseData || PurchaseData.length === 0) {
setMessageType('error');
setMessageData('No Product Selected');
return;
}
// ===============================
// 4⃣ FILTER VALID / INVALID ROWS
// ===============================
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: (
<div style={{ fontSize: 14 }}>
<p>
Some products are missing <b>Qty or Amount</b>.
</p>
<p>
Affected row(s): <b>{invalidRowNumbers.join(', ')}</b>
</p>
<p style={{ marginTop: 8 }}>
Are you sure you want to continue without these products?
</p>
</div>
),
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 onProductFinish = async (values) => {
setExpandCollapseActive('1');
let postData = values;
postData['CompId'] = CompId;
postData['BranchId'] = BranchId;
postData['AppId'] = AppId;
postData['SuppId'] = SupplierData?.filter(
(item) => item.SuppName?.toLowerCase() === 'Self'?.toLowerCase()
)?.[0]?.['SuppId'];
postData['ProdType'] = ProductTypeData?.filter(
(item) => item.ConfigName === 'Product'
)?.[0]?.['ConfigId'];
postData['InvoiceDate'] = new Date().toJSON();
postData['StockAvailable'] = StockOpen;
postData['TokenAvailable'] = TokenOpen;
postData['OnePcsAvailable'] = AmountPerPieceAvailable;
postData['AutoGenerateQr'] =
values?.QRCode == undefined || values?.QRCode == null ? QrcodeAuto : 'N';
postData['AutoGenerateSingleQr'] =
values?.OnePcQR == undefined || values?.OnePcQR == null
? QrcodeAutoSingle
: 'N';
postData['CreatedBy'] = UserId;
if (SelectedTaxId) {
postData['Cess'] =
values?.Cess == undefined || values?.Cess == null || values?.Cess == ''
? 0
: values?.Cess;
}
let response = {};
if (formType === 'add') {
try {
response = await dispatch(postProductData(postData)).unwrap();
} catch (err) {
if (err['message'] == 'Request failed with status code 422') {
response = {
data: {
statusCode: 0,
response: 'Please Give Required Fields',
data: [],
},
};
}
}
}
if (response?.data?.statusCode == 1) {
setOpenAdd(false);
setExpandCollapseActive('1');
setMessageType('success');
setMessageData(response?.data?.response);
let postData1 = {};
postData1['CompId'] = CompId;
postData1['BranchId'] = BranchId;
postData1['AppId'] = AppId;
let product = await dispatch(getProductData(postData1))?.unwrap();
if (product.data?.statusCode == 1) {
handleQuickAddCancel();
}
} else {
setMessageType('error');
setMessageData(response?.data?.response);
}
};
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);
setInvoiceNo(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 () => {
const postData = {
AppId: AppId,
CompId: CompId,
BranchId: 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]);
setShowColumnModal(false);
setTempSelectedColumns([]);
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 (
<div className="pageOverAll" style={{ position: 'relative' }}>
{isLoading && (
<div className="loading-overlay">
<div className="loading-spinner" />
{loadingText && <div className="loading-text">{loadingText}</div>}
</div>
)}
<div className="userPage">
<div className="userPageContent" style={{ paddingBottom: '1rem' }}>
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<div className="purchase-entry-fh">
<div
className="formName"
style={{
flexWrap: 'wrap',
gap: '10px',
justifyContent: 'space-between',
}}
>
<FormHeader title={'Product Receipt'} />
{/* <div className="prurachseViewBtn" style={{ backgroundColor: '#25D366', }}>
<button onClick={() => navigate(`${subDirectory}setting/purchase-entry`)}> <FaEye size={18} />
View Entry List</button>
</div> */}
<div
className="header-buttons"
style={{ flexWrap: 'wrap', width: 'unset' }}
>
<div
className="pruchaseCatBTN scan-receipt-btn"
onClick={() => setExtractorModalVisible(true)}
>
<TbUpload size={18} strokeWidth={3} />{' '}
<p> Scan Receipt (Auto-Fill)</p>
</div>
<div
className="pruchaseCatBTN"
onClick={() =>
navigate(`${subDirectory}setting/purchase-entry`)
}
>
<FaEye size={18} /> <p> View Entry List</p>
</div>
</div>
</div>
</div>
<div className="formDiv">
<Form
ref={formRef}
initialValues={editstate}
className="formDivAnt"
onFinish={onFinish}
>
<div className="purchase-entry-form">
<div className="formDivS">
<div className="purchase-entry-dtls">
<div className="pe-inward-date">
<label className="required">Inward Date</label>
<Form.Item
name={'InvoiceDate'}
rules={[
{
required: true,
message: 'Please Select Inward Date',
},
]}
>
<DatePicProd
canSelectPast={true}
onChange={handleInwardDateChange}
valueData={inwardDate}
disabled={formType == 'edit' ? true : false}
cancelFuture={true}
/>
</Form.Item>
</div>
<Form.Item
name="OrderType"
rules={[
{
required: true,
message: 'Please Select Order Type',
},
]}
>
<div className="switch-order-type">
<div className="switch-header required">Order Type</div>
<Switch
checked={orderType}
onChange={handleOrderTypeChange}
checkedChildren="New Order"
unCheckedChildren="Pending Orders"
/>
</div>
</Form.Item>
</div>
<div className="inputFormSTOCKFORM">
<div className="purchaseDetails">
<div className="supplierInfo">
<h2 className="supplier-dtls">Supplier Details</h2>
<div className="supplierInfo1">
{!orderType && (
<Form.Item
name="PurchaseOrderNo"
rules={[
{
required: true,
message: 'Please Select Purchase Order No.',
},
]}
>
<FloatLabel
label={
<label class="required">
Purchase Order No.
</label>
}
isOnChange={searchText ? true : false}
>
<AutoComplete
style={{ width: '180px' }}
options={filteredOptions}
className="supplier-invoice-select"
autoComplete="off"
allowClear
value={searchText}
onSelect={handleInvoiceSelect}
onSearch={handleInvoiceSearch}
filterOption={(inputValue, option) =>
option.label
?.toLowerCase()
.includes(inputValue?.toLowerCase())
}
/>
</FloatLabel>
</Form.Item>
)}
<Form.Item
name="CustSuppId"
rules={[
{
required: true,
message: 'Please Select Supplier',
},
]}
>
<DropDowns
options={
SupplierData
? SupplierData.filter(
(obj, index, self) =>
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={<label class="required">Supplier</label>}
className="field-DropDown"
onChangeFunction={handleSupplierDropDownChange}
valueData={selectedSupplierData}
disabled={
editstate?.SuppId
? true
: !orderType
? true
: false
}
/>
<Tooltip title="Add Supplier" placement="top">
<PlusCircleOutlined
className="product-add-iconMargin"
onClick={addSupplier}
/>
</Tooltip>
</Form.Item>
{!selectedSupplierName && (
<RadioGrpButton
content={[
{ value: 'own', label: 'Own' },
{ value: 'paid', label: 'With paid' },
]}
fieldState={true}
defaultSelect={SupplierOpen}
// Header={"Stock Available"}
onSelectFuntion={(e) => SupplierOpenfun(e)}
/>
)}
</div>
<div className="supplierInfo2">
{(SupplierOpen !== 'own' || selectedSupplierName) &&
selectedSupplierData && (
<>
<Form.Item name={'InvoiceType'}>
<RadioGrpButton
content={[
{ value: 'I', label: 'Invoice' },
{
value: 'DC',
label: 'Delivery Challan',
},
]}
defaultSelect={invoiceType}
onSelectFuntion={handleInvoiceTypeChange}
/>
</Form.Item>
<Form.Item
name="SuppInvoiceNo"
rules={[
{
required: true,
// pattern:/^[1-9]\d*(\.\d+)?$/,
message:
invoiceType === 'I'
? 'Please Enter Invoice Number'
: 'Please Enter Delivery Challan',
},
{
validator: async (_, value) => {
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();
},
},
]}
>
<div className="stock-input">
<InputField
autoComplete="off"
label={
<label class="required">
{invoiceType === 'I'
? 'Supplier Invoice Number'
: 'Delivery Challan No.'}
</label>
}
onChange={handleSuppInvoiceNoChange}
isOnChange={
extractorData?.invoiceNo ? true : false
}
value={extractorData?.invoiceNo}
/>
</div>
</Form.Item>
<Form.Item name="SuppInvoiceDate">
<div className="supplier-invoice-date">
<label className="required">
{invoiceType === 'I'
? 'Supplier Invoice Date'
: 'Delivery Challan Date'}
</label>
<DatePicProd
canSelectPast={true}
onChange={onSuppInvoiceDateChange}
valueData={SuppInvoiceDate}
disabled={
formType == 'edit' ? true : false
}
cancelFuture={true}
/>
</div>
</Form.Item>
</>
)}
</div>
</div>
{(SupplierOpen !== 'own' || selectedSupplierName) &&
selectedSupplierData && (
<div className="invoiceDetails">
<>
<Form.Item
name="PaymentType"
rules={[
{
required: true,
message: 'Please Select Pruchase Type ',
},
]}
>
<DropDowns
options={PurchaseTypeData?.map((option) => ({
value: option.ConfigId,
label:
option.ConfigName === 'Cash'
? 'Paid'
: option.ConfigName,
}))}
label={
<label class="required">Payment Type</label>
}
className="field-DropDown"
onChangeFunction={handlePurchaseTypeChange}
valueData={SelectedPurchaseType}
disabled={editstate?.SuppId ? true : false}
/>
</Form.Item>
{PurchaseTypeData?.some(
(item) =>
item.ConfigId === SelectedPurchaseType &&
item.ConfigName === 'Cash'
) && (
<>
<Form.Item
name="PaymentMode"
rules={[
{
required: true,
message: 'Please Select Payment Mode',
},
]}
>
<DropDowns
options={paymentOptions?.map((mode) => ({
value: mode.ModeId,
label: mode.ModeName,
}))}
label={
<label className="required">
Payment Mode
</label>
}
className="field-DropDown"
onChangeFunction={handlePaymentModeChange}
valueData={selectedPaymentMode}
/>
</Form.Item>
<Form.Item
name="PaymentAmount"
rules={[
{
required: true,
message: 'Please enter Payment Amount',
},
{
validator: (_, value) => {
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();
},
},
]}
>
<InputField
autoComplete="off"
label={
<label className="required">
Payment Amount
</label>
}
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);
}}
/>
</Form.Item>
</>
)}
<Form.Item name="DueDate">
<label className="required">Due Date</label>
<br />
<DatePicProd
canSelectPast={true}
onChange={onPurchaseDateChange}
valueData={PurchaseDate}
disabled={formType == 'edit' ? true : false}
cancelFuture={false}
/>
</Form.Item>
</>
</div>
)}
</div>
<div className="stockDiv">
<Form.Item name="ProdId">
<div className="product-scan">
<FloatLabel
label={'Product Name'}
value={selectedProductName}
>
<AutoComplete
className="field-DropDown"
value={selectedProductName}
filterOption={(input, option) => {
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,
]);
}
}}
onChange={handleProductSearch}
onKeyDown={(e) => {
if (scanner && e.key === 'Enter') {
e.preventDefault();
}
}}
style={{ width: '250px' }}
></AutoComplete>
</FloatLabel>
<Tooltip title={'BarCode/QrCode'} placement={'top'}>
<BsUpcScan
strokeWidth={0.5}
color="#000"
style={{
fontSize: '16px',
color: scanner ? '#52c41a' : '#888',
fontWeight: '600',
}}
className="product-scan-Icon"
onClick={handleScanSearch}
/>
</Tooltip>
</div>
<Tooltip
title={'Supplier Product Mapping'}
placement={'top'}
>
<FaLink
onClick={() => setIsModalOpen(true)}
size={18}
/>
</Tooltip>
<Tooltip title={'Add All Products'} placement={'top'}>
<button
type="button"
className="addallProductTBN"
onClick={async () => {
const allProducts = await Promise.all(
productData.map(async (product) => {
const newProduct =
await ProductDropDownChange(
product?.ProdVariantName, // Use actual variant name
product.ProdId,
{
label: `${product.ProdName} (${product.Size} ${product.UomName})${product?.BrandName ? ` - ${product?.BrandName}` : ''}`,
},
productData
);
return newProduct;
})
);
const validProducts = allProducts.filter(Boolean);
setPurchaseData([
...validProducts,
...PurchaseData,
]);
// Set form field values for all added products
validProducts.forEach((product) => {
const localId = product?.localId;
form?.setFieldsValue({
[`SellPrice${localId}`]: product?.SellPrice,
[`PurchaseTax${localId}`]:
product?.PurchaseTax,
[`BalanceQty${localId}`]: product?.BalanceQty,
[`ReceivedQty${localId}`]:
product?.ReceivedQty,
[`AcceptedQty${localId}`]:
product?.AcceptedQty,
[`RejectedQty${localId}`]:
product?.RejectedQty,
[`InwardPrice${localId}`]:
product?.InwardPrice,
[`Amount${localId}`]: product?.Amount,
});
});
}}
>
Add All
</button>
</Tooltip>
</Form.Item>
{isModalOpen && (
<SupplierProductMappingForm
isModalOpen={isModalOpen}
setIsModalOpen={() => {
(setIsModalOpen(false),
handleSupplierDropDownChange(
selectedSupplierData
));
}}
CompId={CompId}
BranchId={BranchId}
AppId={AppId}
setMessage={setMessage}
onMappingAdded={handleModalSubmited}
/>
)}
<div className="productSearchRecipt">
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '10px',
justifyContent: 'flex-end',
fontFamily: 'Poppins',
fontWeight: '500',
textDecoration: 'underline',
cursor: 'Pointer',
width: '100%',
}}
onClick={() => {
setTempSelectedColumns([
...selectedAdditionalColumn,
]);
setShowColumnModal(true);
}}
>
<Tooltip title="Add Fields" placement="left">
<IoSettingsOutline
style={{ cursor: 'pointer', fontSize: '20px' }}
/>
</Tooltip>
</div>
<div style={{ marginBottom: '10px' }}>
<Input
placeholder="Search products..."
prefix={<SearchOutlined />}
onChange={(e) => {
const value = e.target.value.toLowerCase();
setSearchValue(value);
}}
style={{ width: '300px' }}
/>
</div>
</div>
</div>
<div
className="Product-table stockformTabele"
style={{
maxwidth: '500px',
overflowX: 'auto',
scrollbarWidth: 'thin',
maxHeight: '50vh',
}}
>
{/* <Form form={form} component={false}>
<Table
className="purchase-receipt-table"
bordered
dataSource={filteredPurchaseData.length > 0 ? filteredPurchaseData : PurchaseData}
columns={columns}
rowClassName="editable-row"
onRow={(record, index) => ({
onClick: () => {
edit(record, index);
},
})}
pagination={false}
/> */}
<Form form={form} component={false}>
<Table
className="purchase-receipt-table"
bordered
dataSource={
isSearching ? filteredPurchaseData : PurchaseData
}
columns={columns}
rowClassName="editable-row"
onRow={(record) => ({
onClick: () => {
edit(record);
},
})}
pagination={false}
locale={{
emptyText: isSearching
? 'No matching products found'
: 'No data',
}}
/>
</Form>
</div>
</div>
</div>
</div>
</Form>
</div>
<Form
ref={formRef}
initialValues={editstate}
className="finalSubmitPRBTN"
onFinish={onFinish}
>
{PurchaseData?.length > 0 && (
<div className="purchase-status-data">
<div className="total-purchase-amnt">
<label>Total Amount:&nbsp;</label>
<div>
{PurchaseData.reduce(
(acc, data) => acc + data?.Amount,
0
)?.toFixed(2)}
</div>
</div>
{!orderType && (
<div className="purchase-status">
<RadioGrpButton
content={[
{ value: 'P', label: 'Pending' },
{ value: 'C', label: 'Completed' },
]}
Header={'Purchase Status'}
defaultSelect={purchaseStatus}
onSelectFuntion={purchaseStatusChange}
/>
</div>
)}
</div>
)}
<Buttons
buttonText="SUBMIT"
color="901D77"
icon={<ArrowRightOutlined />}
/>
</Form>
</div>
<DefaultModal
title="Add Supplier"
open={OpenSupplierModel}
footer={true}
buttonText="Submit"
children={
<Form ref={formSupplierRef} className="formDivAnt">
<div className="subRowFlex">
<Form.Item
name="SuppName"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Supplier Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value?.length > 30) {
return Promise.reject(
'Supplier Name cannot exceeds more than 30 chars'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
label={<label class="required">Supplier Name</label>}
autocomplete="off"
/>
</Form.Item>
<Form.Item
name="Address1"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Address1',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">Address</label>}
/>
</Form.Item>
<Form.Item
name="Zip"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Zipcode',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">Zipcode</label>}
maxLength="6"
onChange={pinCodeChange}
/>
</Form.Item>
<p
style={{ color: '#1292ee', justifyContent: 'end' }}
onClick={ViewMoreFields}
>
{' '}
{ViewDtl ? 'Less More' : 'View More'}
</p>
{ViewDtl && (
<>
<Form.Item
name="SuppGSTIN"
rules={[
{
pattern:
/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9A-Za-z]{1}$/,
message: 'Enter a valid GSTIN',
},
]}
>
<InputField
style={{ textTransform: 'uppercase' }}
autoComplete="off"
label="GST No"
autocapitalize="on"
// isOnChange={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="SuppMobile"
rules={[
{
pattern: /^\d{10}$/,
message: 'Please Enter a Valid Mobile Number',
},
{ validator: validatePhoneNumber },
]}
>
<InputField
label={<label>Mobile Number</label>}
maxLength="10"
autocomplete="off"
// isOnChange={formType == 'edit' ? true : false}
inputMode="numeric"
onInput={(e) =>
(e.target.value = e.target.value.replace(
/[^0-9]/g,
''
))
}
/>
</Form.Item>
<Form.Item
name="SuppEmail"
rules={[{ validator: validateEmail }]}
>
<InputField
label={<label>MailId</label>}
autocomplete="off"
// isOnChange={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="SuppPOC"
rules={[
{
pattern: /^(?!\s*$).+/,
message: 'Please Enter Point of Contact Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value?.length > 30) {
return Promise.reject(
'Point of Contact cannot exceeds more than 30 chars'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
label={<label class="">Point of Contact</label>}
autocomplete="off"
// isOnChange={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="SuppPOCMobile"
rules={[
{
pattern: /^\d{10}$/,
message: 'Please Enter a Valid Mobile Number',
},
{
// required: true,
message: 'Please Enter Mobile Number',
},
{ validator: validatePhoneNumber },
]}
>
<InputField
label={<label class="">POC Mobile Number</label>}
autocomplete="off"
maxLength="10"
// isOnChange={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="SuppPOCEmail"
rules={[{ validator: validateEmail }]}
>
<InputField
label={<label class="">POC MailId</label>}
autocomplete="off"
// isOnChange={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="DeliveryPerformance"
rules={[
{
required: false,
message: 'Please Select DeliveryPerformance',
},
]}
>
<DropDowns
options={deliveryPerformanceData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label>Delivery Performance</label>}
className="field-DropDown"
id="DeliveryPerformance"
onChangeFunction={(e) =>
handleDeliveryPerformanceChange(e)
}
// isOnChange={formType == 'edit' ? true : false}
valueData={Delivery}
/>
</Form.Item>
<Form.Item
name="DiscountLevel"
rules={[
{
required: false,
message: 'Please Select DiscountLevel',
},
]}
>
<DropDowns
options={DiscountData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label>Discount Level</label>}
className="field-DropDown"
id="DiscountLevel"
onChangeFunction={(e) => handleDiscountLevelChange(e)}
// isOnChange={formType == 'edit' ? true : false}
valueData={DicountValue}
/>
</Form.Item>
<Form.Item
name="QualityofSupp"
rules={[
{
required: false,
message: 'Please Select QualityofSupp',
},
]}
>
<DropDowns
options={QualityData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label>Quality of Supplier</label>}
className="field-DropDown"
id="QualityofSupp"
onChangeFunction={(e) => handleQualityofSuppChange(e)}
// isOnChange={formType == 'edit' ? true : false}
valueData={QualityValue}
/>
</Form.Item>
</>
)}
{zipCodeData ? (
<>
<Form.Item
name="City"
rules={[
{
required: true,
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
disabled={true}
isOnChange={true}
label="City"
/>
</Form.Item>
<Form.Item
name="Dist"
rules={[
{
required: true,
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
disabled={true}
isOnChange={true}
label="District"
/>
</Form.Item>
<Form.Item
name="State"
rules={[
{
required: true,
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
disabled={true}
isOnChange={true}
label="State"
/>
</Form.Item>
</>
) : (
''
)}
</div>
</Form>
}
handleSubmit={submitSupplier}
handleCancel={handleSupplier}
></DefaultModal>
<div>
<DefaultModal
open={AddProductDetail}
width={800}
footer={false}
title={'Add Product'}
children={
<Form
ref={formProductRef}
className="formDivAnt"
onFinish={onProductFinish}
>
<div className="subRowFlex">
<Form.Item
name="ProdName"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Product Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value && value.length > 50) {
return Promise.reject(
'Product Name should not exceed 50 characters'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">Product Name</label>}
// isOnChange={(editstate?.ProdName || QrcodeExistsData?.[0]?.ProdName) ? true : false}
onChange={(e) => setProductName(e?.target?.value)}
/>
</Form.Item>
<Form.Item
name="Size"
rules={[
{
required: true,
// pattern: /^[1-9]\d*(\.\d+)?$/,
message: 'Please Enter Quantity',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">Quantity</label>}
// isOnChange={(editstate?.Size || QrcodeExistsData?.[0]?.Size) ? true : false}
suffix={
<Tooltip title="Per Unit(eg: 1 kg,1 piece,500 g)">
<InfoCircleOutlined
style={{
color: 'rgba(0,0,0,.45)',
}}
/>
</Tooltip>
}
/>
</Form.Item>
<Form.Item
name="UOM"
rules={[
{
required: true,
message: 'Please Select Uom',
},
]}
>
<DropDowns
options={UomData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label class="required">Uom</label>}
className="field-DropDown"
// isOnchanges={(editstate?.UOM || SelectedUom)?true:false}
onChangeFunction={handleUomDropDownChange}
valueData={SelectedUom}
disabled={formType == 'edit' ? true : false}
/>
</Form.Item>
<Form.Item
name="MRP"
rules={[
{
required: true,
pattern: /^[1-9]\d*(\.\d+)?$/,
message: 'Please Enter MRP',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">MRP</label>}
// isOnChange={(editstate?.MRP || QrcodeExistsData?.[0]?.MRP) ? true : false}
onChange={handleMRP}
/>
</Form.Item>
<Form.Item
name="SellPrice"
rules={[
{
required: true,
pattern: /^[1-9]\d*(\.\d+)?$/,
message: 'Please enter retail',
},
{ validator: handleSellPrice },
]}
>
<InputField
autoComplete="off"
label={<label class="required">Sales Price</label>}
// isOnChange={(editstate?.SellPrice || QrcodeExistsData?.[0]?.SellPrice)? true : false}
/>
</Form.Item>
<Form.Item
name="ProdCat"
// rules={[
// {
// // required: true,
// message:"Please Select Category"
// },
// ]}
>
<DropDowns
options={ProdCatData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label class="required">Category</label>}
className="field-DropDown"
// isOnchanges={(editstate?.ProdCat || SelectedProdCat)?true:false}
onChangeFunction={handleProdCatDropDownChange}
valueData={SelectedProdCat}
disabled={
editstate?.ProdTypeName == 'Others' || formType == 'add'
? false
: true
}
/>
<Tooltip title="Add Category" placement="top">
<PlusCircleOutlined
className="product-add-iconMargin"
onClick={addCategory}
/>
</Tooltip>
</Form.Item>
<Form.Item name="ProdSubCat">
<DropDowns
options={ProdSubCatData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label>SubCategory</label>}
className="field-DropDown"
// isOnchanges={(editstate?.ProdSubCat || SelectedProdSubCat)?true:false}
onChangeFunction={handleProdSubCatDropDownChange}
valueData={SelectedProdSubCat}
disabled={
editstate?.ProdTypeName == 'Others' || formType == 'add'
? false
: true
}
/>
<Tooltip title="Add Sub-Category" placement="top">
<PlusCircleOutlined
className="product-add-iconMargin"
onClick={addSubCategory}
/>
</Tooltip>
</Form.Item>
<Form.Item name="Brand">
<DropDowns
options={BrandData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label="Brand"
className="field-DropDown"
// isOnchanges={(editstate?.Brand || SelectedBrand)?true:false}
onChangeFunction={handleBrandDropDownChange}
valueData={SelectedBrand}
// disabled={editstate?.Brand ? true : false}
/>
<Tooltip title="Add Brand" placement="top">
<PlusCircleOutlined
className="product-add-iconMargin"
onClick={addBrand}
/>
</Tooltip>
</Form.Item>
<div className="productcollapse1">
<Collapse defaultActiveKey={expandCollapseActive}>
<Panel header="Qrcode and Token" key="1">
<div className="Qrcodediv">
<div>
<RadioGrpButton
content={[
{ value: 'Y', label: 'Yes' },
{ value: 'N', label: 'No' },
]}
fieldState={true}
defaultSelect={StockOpen}
Header={'Stock Available'}
onSelectFuntion={(e) => openStock(e)}
/>
</div>
<div>
<RadioGrpButton
content={[
{ value: 'Y', label: 'Yes' },
{ value: 'N', label: 'No' },
]}
fieldState={true}
defaultSelect={TokenOpen}
Header={'Token Available'}
onSelectFuntion={(e) => openToken(e)}
/>
</div>
<div>
<RadioGrpButton
content={[
{ value: 'Y', label: 'Yes' },
{ value: 'N', label: 'No' },
]}
fieldState={true}
defaultSelect={QrcodeAuto}
Header={'Auto Generate Qrcode'}
onSelectFuntion={(e) => openQrcodeAuto(e)}
disabled={editstate?.QRCode ? true : false}
/>
</div>
<div>
<RadioGrpButton
content={[
{ value: 'Y', label: 'Yes' },
{ value: 'N', label: 'No' },
]}
fieldState={true}
defaultSelect={AmountPerPieceAvailable}
Header={'Amount Per Piece'}
onSelectFuntion={(e) =>
openAmountPerPieceAvailable(e)
}
// disabled={editstate?.QRCode ? true : false}
/>
</div>
{(QrcodeAuto == 'N' || editstate?.QRCode) && (
<div className="scannerdiv">
<img
src={barcodeimg}
style={{ height: '50px' }}
></img>
<Form.Item
name="QRCode"
rules={[
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<ScannerInputField
autoComplete="off"
label="Scanner / AddQrcode"
onKeyPress={handleKeyPress}
valueData={QrcodeFinalVal}
isOnChange={QrcodeFinalVal ? true : false}
onChange={handleInput}
disabled={editstate?.QRCode ? true : false}
/>
{QrcodeExistsVal && QrcodeExistsVal}
</Form.Item>
</div>
)}
{AmountPerPieceAvailable == 'Y' && (
<>
<Form.Item
name="OnePcsPrice"
rules={[
{
pattern: /^[1-9]\d*(\.\d+)?$/,
message:
'Please Enter Valid Amount for Piece',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label="Amount Per Piece"
isOnChange={
editstate?.OnePcsPrice ? true : false
}
/>
</Form.Item>
<div>
<RadioGrpButton
content={[
{ value: 'Y', label: 'Yes' },
{ value: 'N', label: 'No' },
]}
fieldState={true}
defaultSelect={QrcodeAutoSingle}
Header={'Auto Generate One Piece Qrcode'}
onSelectFuntion={(e) =>
openQrcodeAutoSingle(e)
}
disabled={editstate?.OnePcQR ? true : false}
/>
</div>
{(QrcodeAutoSingle == 'N' ||
editstate?.OnePcQR) && (
<div className="scannerdiv">
<img
src={barcodeimg}
style={{ height: '50px' }}
></img>
<Form.Item
name="OnePcQR"
rules={[
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<ScannerInputField
autoComplete="off"
label="Scanner / AddOnePcQrcode"
onKeyPress={handleKeyPressSingle}
valueData={QrcodeSingleFinalVal}
isOnChange={
QrcodeSingleFinalVal ? true : false
}
onChange={handleInputSingle}
// disabled={editstate?.OnePcQR ? true : false}
/>
{QrcodeSingleExistsVal &&
QrcodeSingleExistsVal}
</Form.Item>
</div>
)}
</>
)}
{StockOpen == 'Y' &&
AmountPerPieceAvailable == 'Y' && (
<Form.Item
name="NoOfPcs"
rules={[
{
pattern: /^[1-9]\d*(\.\d+)?$/,
message:
'Please Enter Valid Number Of Piece',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label="Number of Piece inside"
// isOnChange={editstate?.NoOfPcs ? true : false}
/>
</Form.Item>
)}
</div>
</Panel>
</Collapse>
</div>
{OpenAdd && (
<>
<Form.Item name="TaxId">
<DropDowns
options={TaxData?.map((option) => ({
value: option.TaxId,
label: getOptionLabel(
option,
SelectedTaxId === option.TaxId
),
// label: option.TaxIdName + ' - ' + option.TaxPercentage + ' % ',
}))}
label="Tax"
className="field-DropDown"
isOnchanges={SelectedTaxId ? true : false}
onChangeFunction={handleTaxDropDownChange}
valueData={SelectedTaxId}
/>
<Tooltip title="Add Tax" placement="top">
<PlusCircleOutlined
className="product-add-iconMargin"
onClick={addTax}
/>
</Tooltip>
</Form.Item>
<Form.Item
name="Cess"
rules={[
{
pattern: /^\d*\.?\d+$/,
message: 'Please Enter Cess',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField autoComplete="off" label="Cess" />
</Form.Item>
<Form.Item
name="HSNCode"
rules={[
{
pattern: /^(?!\s*$).+/,
message: 'Please Enter HSN',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField autoComplete="off" label="HSN" />
</Form.Item>
<Form.Item
name="WhSalePrice"
rules={[
{
pattern: /^[0-9]\d*(\.\d+)?$/,
message: 'Please Enter WholeSale',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label>WholeSale</label>}
/>
</Form.Item>
<Form.Item
name="splSalePrice"
rules={[
{
pattern: /^[0-9]\d*(\.\d+)?$/,
message: 'Please Enter Special Price',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label>splSale</label>}
/>
</Form.Item>
<Form.Item
name="offerSalePrice"
rules={[
{
pattern: /^[0-9]\d*(\.\d+)?$/,
message: 'Please Enter Offer Sale',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label>offerSale</label>}
/>
</Form.Item>
</>
)}
</div>
<div className="prodAddDetails" onClick={openAdditionalDetails}>
Additional Details
</div>
<div
className="submitButtonDiv"
style={{ display: 'flex', justifyContent: 'flex-end' }}
>
<Buttons
buttonText="SUBMIT"
color="901D77"
icon={<ArrowRightOutlined />}
htmlType={true}
/>
</div>
</Form>
}
handleCancel={handleQuickAddCancel}
/>
<DefaultModal
title="Add Category"
open={OpenCategoryModel}
footer={true}
buttonText="Submit"
children={
<Form ref={formCategoryRef} className="formDivAnt">
<div className="subRowFlex">
<div className="subColumnFlex">
<div>
<Form.Item
name="ConfigName"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Config Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value && value.length > 50) {
return Promise.reject(
'Config Name should not exceed 50 characters'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
label={<label class="required">Config Name</label>}
autocomplete="off"
/>
</Form.Item>
</div>
</div>
<div className="subColumnFlex">
<div className="upload_btn">
<p>Upload Icon</p>
<br></br>
<Imageupload
singleImage={true}
updateImageUrl={updateCategoryImageUrl}
ImageLink={imageCategoryUrl ? imageCategoryUrl : ''}
/>
</div>
</div>
</div>
</Form>
}
handleSubmit={submitCategory}
handleCancel={handleCategory}
></DefaultModal>
<DefaultModal
title="Add Sub-Category"
open={OpenSubCategoryModel}
footer={true}
buttonText="Submit"
handleSubmit={submitSubCategory}
handleCancel={handleSubCategory}
children={
<Form ref={formSubCategoryRef} className="formDivAnt">
<div className="subRowFlex">
<div className="subColumnFlex">
<div className="subProdCatData">
<Form.Item
name="CategoryId"
rules={[
{
required: true,
message: 'Please Select Category',
},
]}
>
<DropDowns
options={ProdCatData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label class="required">Category</label>}
className="field-DropDown"
onChangeFunction={handleCatDropDownChange}
valueData={SelectedCategory}
/>
</Form.Item>
<div className="upload_btn">
<p>Upload Icon</p>
<br></br>
<Imageupload
singleImage={true}
updateImageUrl={updateSubCategoryImageUrl}
ImageLink={
imageSubCategoryUrl ? imageSubCategoryUrl : ''
}
/>
</div>
</div>
</div>
<div className="subColumnFlex">
<div>
<Form.Item
name="SubConfigName"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Config Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value && value.length > 50) {
return Promise.reject(
'Config Name should not exceed 50 characters'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
label={<label class="required">Config Name</label>}
autocomplete="off"
/>
</Form.Item>
</div>
</div>
</div>
</Form>
}
></DefaultModal>
<DefaultModal
title="Add Brand"
open={OpenBrandModel}
footer={true}
buttonText="Submit"
handleSubmit={submitBrand}
handleCancel={handleBrand}
children={
<Form ref={formBrandRef} className="formDivAnt">
<div className="subRowFlex">
<div className="subColumnFlex">
<div className="subProdCatData">
<Form.Item
name="SubCategoryId"
rules={[
{
required: true,
message: 'Please Select Sub-Category',
},
]}
>
<DropDowns
options={ProdSubCatData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label={<label class="required">Sub-Category</label>}
className="field-DropDown"
onChangeFunction={handleSubCatDropDownChange}
valueData={SelectedSubCategory}
/>
</Form.Item>
<div className="upload_btn">
<p>Upload Icon</p>
<br></br>
<Imageupload
singleImage={true}
updateImageUrl={updateBrandImageUrl}
ImageLink={imageBrandUrl ? imageBrandUrl : ''}
/>
</div>
</div>
</div>
<div className="subColumnFlex">
<div>
<Form.Item
name="SubConfigName"
rules={[
{
required: true,
pattern: /^(?!\s*$).+/,
message: 'Please Enter Config Name',
},
{
validator: async (_, value) => {
await validateSafeInput(value);
if (value && value.length > 50) {
return Promise.reject(
'Config Name should not exceed 50 characters'
);
}
return Promise.resolve();
},
},
]}
>
<InputField
label={<label class="required">Config Name</label>}
autocomplete="off"
/>
</Form.Item>
</div>
</div>
</div>
</Form>
}
></DefaultModal>
<DefaultModal
title="Add Tax"
open={OpenTaxModel}
footer={true}
buttonText="Submit"
children={
<Form ref={formTaxRef} className="formDivAnt">
<div className="subRowFlex">
<Form.Item name="TaxName">
<DropDowns
options={ProdTaxData?.map((option) => ({
value: option.ConfigId,
label: option.ConfigName,
}))}
label="Tax Name"
className="field-DropDown"
onChangeFunction={handleTaxNameDropDownChange}
valueData={SelectedTaxNameId}
/>
</Form.Item>
<Form.Item
name="TaxPercentage"
rules={[
{
required: true,
pattern: /^(?:100(?:\.0+)?|\d{1,2}(?:\.\d+)?)$/,
message: 'Please Enter Valid Percentage',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField autoComplete="off" label="Tax Percentage" />
</Form.Item>
<Form.Item
name="Reference"
rules={[
{
pattern: /^(?!\s*$).+/,
message: 'Please Enter Reference',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField label="Reference No" autoComplete="off" />
</Form.Item>
<div>
<label className="required">Effective From :</label>
</div>
<Form.Item
name="EffectiveFrom"
rules={[
{
required: true,
message: 'Please Enter Effective From',
},
]}
>
<DatePic
field="EffectiveFrom"
type="number"
min={1}
max={100}
fieldState={true}
/>
</Form.Item>
</div>
</Form>
}
handleSubmit={submitTax}
handleCancel={handleTax}
></DefaultModal>
<DefaultModal
title="IMEI /Serial Number / Mac Id"
open={imeiSerialOpen}
footer={true}
width={600}
buttonText="Submit"
children={
<div className="imeiSNTable">
<Table
components={components}
rowClassName={() => 'editable-row'}
bordered
dataSource={dataSource}
columns={IMEIcolumns}
pagination={{ showSizeChanger: false }}
/>
</div>
}
handleSubmit={handleModelDataSumbitOrClose}
handleCancel={handleModelDataSumbitOrClose}
></DefaultModal>
<DefaultModal
title="Select Additional Fields"
open={showColumnModal}
footer={true}
buttonText="Apply"
destroyOnClose={true}
handleSubmit={handleFieldSetupSubmit}
handleCancel={() => {
setShowColumnModal(false);
setSelectedFields([
...selectedAdditionalColumn
.map(
(col) =>
tableFieldPreferences?.find((pref) => pref.label === col)
?.value
)
.filter(Boolean),
]);
setTempSelectedColumns([...selectedAdditionalColumn]);
}}
>
<div style={{ padding: '20px' }}>
{tableFieldPreferences?.map((option) => (
<div key={option.value} className="Customized_QuickAdd">
<label>
<input
type="checkbox"
checked={selectedFields?.includes(option.value)}
onChange={(e) => {
const isChecked = e.target.checked;
setSelectedFields((prev) =>
isChecked
? [...prev, option.value]
: prev.filter((item) => item !== option.value)
);
setTempSelectedColumns((prev) =>
isChecked
? [...prev, option.label]
: prev.filter((item) => item !== option.label)
);
}}
style={{ marginRight: '8px' }}
/>
{option.label}
</label>
</div>
))}
</div>
</DefaultModal>
<InvoiceImageExtractorModal
visible={extractorModalVisible}
onClose={() => setExtractorModalVisible(false)}
onApply={handleExtractorApply}
productData={productData}
supplierData={SupplierData}
uomData={UomData}
setVisible={setExtractorModalVisible}
/>
</div>
</div>
<style jsx>{`
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`}</style>
</div>
);
};
export default StockForm;