5850 lines
204 KiB
JavaScript
5850 lines
204 KiB
JavaScript
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 (0–99%) 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: </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;
|