2026-01-27 18:27:29 +05:30
|
|
|
|
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,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
SearchOutlined,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} from '@ant-design/icons';
|
|
|
|
|
|
import {
|
|
|
|
|
|
Form,
|
|
|
|
|
|
Tooltip,
|
|
|
|
|
|
Table,
|
|
|
|
|
|
Input,
|
|
|
|
|
|
Collapse,
|
|
|
|
|
|
AutoComplete,
|
|
|
|
|
|
Switch,
|
|
|
|
|
|
} from 'antd';
|
2026-01-30 19:09:15 +05:30
|
|
|
|
import { IoAddCircleSharp, IoSettingsOutline } from 'react-icons/io5';
|
2026-01-27 18:27:29 +05:30
|
|
|
|
import { ScannerInputField } from '../../Components/Forms/ScannerInputField.jsx';
|
|
|
|
|
|
import { InputField } from '../../Components/Forms/InputField.jsx';
|
|
|
|
|
|
import Buttons from '../../Components/Forms/Buttons.jsx';
|
2026-01-30 19:09:15 +05:30
|
|
|
|
import { Modal } from 'antd';
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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,
|
2026-01-28 15:50:57 +05:30
|
|
|
|
bulkpostdata,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
postFieldSetup,
|
|
|
|
|
|
getFieldSetupData,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} 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';
|
2026-02-03 13:55:24 +05:30
|
|
|
|
import { FaLink, FaEye } from 'react-icons/fa';
|
|
|
|
|
|
import { TbUpload } from 'react-icons/tb';
|
2026-01-27 18:27:29 +05:30
|
|
|
|
import {
|
|
|
|
|
|
getSupplaierIdBasedProducts,
|
|
|
|
|
|
getSupplaierIdwithTypeBasedProducts,
|
|
|
|
|
|
postSupplaierProducts,
|
|
|
|
|
|
} from '../../Features/SupplierProductMapping/SupplierProductMapping.js';
|
2026-02-03 13:55:24 +05:30
|
|
|
|
import {
|
|
|
|
|
|
ApplicationPreferences,
|
|
|
|
|
|
getCommonAppPreference,
|
|
|
|
|
|
} from '../../Features/BrachLogin/BranchLogin.js';
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// rules={[
|
|
|
|
|
|
// (dataIndex == "imei1" || dataIndex == "imei2") && {
|
|
|
|
|
|
// pattern: /^[0-9]{15}$/,
|
|
|
|
|
|
// message: 'IMEI must be a 15-digit number'
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ]}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
>
|
|
|
|
|
|
<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,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
cursor: 'pointer',
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}}
|
|
|
|
|
|
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);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const appPreferences = useSelector(ApplicationPreferences);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const [applicationRestrictedFields, setApplicationRestrictedFields] =
|
|
|
|
|
|
useState({
|
|
|
|
|
|
DatesAndExpiry: false,
|
|
|
|
|
|
BatchAndModelDetails: false,
|
|
|
|
|
|
AmountPerPieceDetail: false,
|
|
|
|
|
|
});
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const [selectedAdditionalColumn, setSelectedAdditionalColumn] = useState([]);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
console.log(selectedAdditionalColumn, 'selectedAdditionalColumn');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const [showColumnModal, setShowColumnModal] = useState(false);
|
|
|
|
|
|
const [tempSelectedColumns, setTempSelectedColumns] = useState([]);
|
|
|
|
|
|
const [tableFieldPreferences, setTableFieldPreferences] = useState([]);
|
|
|
|
|
|
const [selectedFields, setSelectedFields] = useState([]);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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([]);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
console.log(PurchaseData, 'PurchaseData');
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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('');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const [filteredPurchaseData, setFilteredPurchaseData] = useState([]);
|
|
|
|
|
|
const [searchValue, setSearchValue] = useState('');
|
|
|
|
|
|
const isSearching = Boolean(searchValue?.trim());
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (searchValue?.trim()) {
|
|
|
|
|
|
const search = searchValue.toLowerCase();
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const filtered = PurchaseData.filter((item) =>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
item?.ProdName?.toLowerCase().includes(search)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
setFilteredPurchaseData(filtered);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setFilteredPurchaseData([]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [PurchaseData, searchValue]);
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const items = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: 'Home',
|
|
|
|
|
|
link: `${subDirectory}app-page/home`,
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
name: 'Product Receipt',
|
|
|
|
|
|
link: `${subDirectory}setting/purchase-entry`,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: editstate ? 'Edit' : 'New',
|
|
|
|
|
|
link: null,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const categoryId = appPreferences?.find(
|
2026-02-03 13:55:24 +05:30
|
|
|
|
(p) => p?.PreferredCatName?.toLowerCase() === 'purchase entry'
|
2026-01-30 19:09:15 +05:30
|
|
|
|
)?.PreferredCatId;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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(() => {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const total = PurchaseData?.reduce((acc, item) => {
|
|
|
|
|
|
return acc + Number(item?.Amount || 0);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}, 0);
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const invoiceAmount = !isNaN(total) && total !== 0 ? total : null;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
setSelInvoiceAmount(invoiceAmount);
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
formRef.current?.setFieldsValue({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
InvoiceAmount: invoiceAmount,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
const totalTax = PurchaseData?.reduce((acc, item) => {
|
|
|
|
|
|
return acc + Number(item?.TaxAmt || 0);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}, 0);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
setTotalTaxAmount(totalTax);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}, [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 };
|
|
|
|
|
|
};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
getFieldSetup();
|
2026-02-03 13:55:24 +05:30
|
|
|
|
}, [categoryId]);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const getFieldSetup = async () => {
|
|
|
|
|
|
try {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const response = await dispatch(
|
|
|
|
|
|
getFieldSetupData({ AppId, CompId, BranchId, categoryId, Type: 'PE' })
|
|
|
|
|
|
).unwrap();
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (response?.data?.statusCode === 1) {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
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,
|
|
|
|
|
|
})) || []
|
|
|
|
|
|
);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Error fetching field setup:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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 = [];
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const NewImageProducts = [];
|
|
|
|
|
|
console.log(unmatchedProducts, 'unmatchedProductsunmatchedProducts');
|
2026-01-27 18:27:29 +05:30
|
|
|
|
// 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);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
} else {
|
2026-01-28 15:50:57 +05:30
|
|
|
|
NewImageProducts.push(item?.parsedData);
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
2026-02-03 13:55:24 +05:30
|
|
|
|
console.log(NewImageProducts, 'NewImageProductsNewImageProducts');
|
2026-01-28 15:50:57 +05:30
|
|
|
|
// Bulk upload new image products
|
|
|
|
|
|
if (NewImageProducts.length > 0) {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const newProductsData = NewImageProducts.map((product) => ({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
AppId: AppId || 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
CompId: CompId || '',
|
|
|
|
|
|
BranchId: BranchId || '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
CreatedBy: UserId || 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
ProdName: product.description?.trim() || '',
|
|
|
|
|
|
ProdVariantName: '',
|
|
|
|
|
|
Size: 1 || '',
|
|
|
|
|
|
UOM: product.unit || '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
MRP: parseFloat(product.rate) || 0,
|
|
|
|
|
|
WhSalePrice: 0,
|
|
|
|
|
|
SellPrice: parseFloat(product.rate) || 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
ProdCat: 'General',
|
|
|
|
|
|
ProdSubCat: '',
|
|
|
|
|
|
Brand: '',
|
|
|
|
|
|
AutoGenerateQr: '',
|
|
|
|
|
|
QRCode: '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
StockAvailable: 'No',
|
2026-02-03 13:55:24 +05:30
|
|
|
|
TaxId: '',
|
|
|
|
|
|
HSNCode: '',
|
|
|
|
|
|
PartNumber: '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
Rack: 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
ManufDate: '',
|
|
|
|
|
|
ExpDate: '',
|
|
|
|
|
|
AvailableFrom: '',
|
|
|
|
|
|
AvailableTo: '',
|
|
|
|
|
|
ProdLogo: '',
|
|
|
|
|
|
OnePcsAvailable: 'No',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
AutoGenerateSingleQr: 'No',
|
|
|
|
|
|
TaxId: 'NIL - 0%',
|
2026-02-03 13:55:24 +05:30
|
|
|
|
OnePcQR: '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
TokenAvailable: 'No',
|
|
|
|
|
|
OpeningQty: 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
QtyBasedPrice: '',
|
|
|
|
|
|
InwardDate: '',
|
|
|
|
|
|
SuppId: suppId || '',
|
|
|
|
|
|
Reference: '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
ReceivedQty: 0,
|
|
|
|
|
|
AcceptedQty: 0,
|
|
|
|
|
|
RejectedQty: 0,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
RejectionReason: '',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
IssuedQty: 0,
|
|
|
|
|
|
BalanceQty: 0,
|
|
|
|
|
|
InwardPrice: 0,
|
|
|
|
|
|
OfferPrice: 0,
|
|
|
|
|
|
SpecialPrice: 0,
|
|
|
|
|
|
Cess: 0,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const bulkResponse = await dispatch(
|
|
|
|
|
|
bulkpostdata({ ProdDetails: newProductsData })
|
|
|
|
|
|
).unwrap();
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
if (bulkResponse?.data?.statusCode === 1) {
|
|
|
|
|
|
// After successful bulk upload, check the condition again
|
|
|
|
|
|
const updatedResponse = await dispatch(
|
2026-02-03 13:55:24 +05:30
|
|
|
|
getSupplaierIdBasedProducts({
|
|
|
|
|
|
CompId,
|
|
|
|
|
|
AppId,
|
|
|
|
|
|
BranchId,
|
|
|
|
|
|
SuppId: suppId,
|
|
|
|
|
|
})
|
2026-01-30 19:09:15 +05:30
|
|
|
|
).unwrap();
|
|
|
|
|
|
if (updatedResponse?.data?.statusCode === 1) {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const updatedAllSupplierProducts =
|
|
|
|
|
|
updatedResponse?.data?.data || [];
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const updatedMatchingProdIds = [];
|
|
|
|
|
|
|
|
|
|
|
|
unmatchedProducts.forEach((item) => {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const match =
|
|
|
|
|
|
updatedAllSupplierProducts?.[0]?.ProductDetails.find(
|
|
|
|
|
|
(supp) =>
|
|
|
|
|
|
supp?.ProdName?.toLowerCase() ===
|
|
|
|
|
|
item?.parsedData?.description?.toLowerCase()
|
|
|
|
|
|
);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (match) {
|
|
|
|
|
|
updatedMatchingProdIds.push(match.ProdId);
|
2026-01-28 15:50:57 +05:30
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (updatedMatchingProdIds.length > 0) {
|
|
|
|
|
|
matchingProdIds.push(...updatedMatchingProdIds);
|
2026-01-28 15:50:57 +05:30
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-28 15:50:57 +05:30
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
// 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(
|
2026-01-30 19:09:15 +05:30
|
|
|
|
item?.selectedProduct.ProdVariantName,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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(
|
2026-01-30 19:09:15 +05:30
|
|
|
|
item?.selectedProduct?.ProdVariantName,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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) => {
|
2026-01-28 15:50:57 +05:30
|
|
|
|
const value = e.target.value;
|
|
|
|
|
|
formRef.current?.setFieldsValue({ SuppInvoiceNo: value });
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setExtractorData((prev) => (prev ? { ...prev, invoiceNo: value } : null));
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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'
|
|
|
|
|
|
);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
if (
|
|
|
|
|
|
extractorData?.invoiceNo !== null &&
|
|
|
|
|
|
extractorData?.invoiceNo !== ''
|
|
|
|
|
|
) {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
formRef?.current?.setFieldsValue({
|
|
|
|
|
|
SuppInvoiceNo: extractorData?.invoiceNo,
|
|
|
|
|
|
});
|
2026-01-28 15:50:57 +05:30
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
formRef?.current?.setFieldsValue({
|
|
|
|
|
|
PaymentAmount: extractorData?.TotalAmtData,
|
|
|
|
|
|
});
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setPaymentAmount(extractorData?.TotalAmtData);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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 (
|
2026-01-30 19:09:15 +05:30
|
|
|
|
VariantName,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
ProdId,
|
|
|
|
|
|
option,
|
|
|
|
|
|
productsList,
|
|
|
|
|
|
extractedProduct = false,
|
|
|
|
|
|
extractedItem,
|
|
|
|
|
|
existingProducts
|
|
|
|
|
|
) => {
|
|
|
|
|
|
setProductSearchText('');
|
|
|
|
|
|
setSelectedProductName(option?.label ? option?.label : '');
|
|
|
|
|
|
formRef?.current?.resetFields(['VarProdId']);
|
|
|
|
|
|
setselectedProductVariantData(null);
|
|
|
|
|
|
setSelectedProductData(ProdId);
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// let x = (productsList || productData)?.find(
|
|
|
|
|
|
// (e) => e.ProdId == ProdId
|
|
|
|
|
|
// )?.ProdName;
|
2026-02-03 13:55:24 +05:30
|
|
|
|
let OnePcsAvailable =
|
|
|
|
|
|
(productsList || productData)?.find(
|
|
|
|
|
|
(e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName
|
|
|
|
|
|
)?.OnePcsAvailable == 'Y';
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// 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,
|
|
|
|
|
|
// }))
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
if (
|
|
|
|
|
|
true
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// cc?.[0]?.ProdVariantDetails?.length < 2 ||
|
|
|
|
|
|
// (extractedProduct ? cc?.[0]?.ProdVariantDetails?.length > 0 : false)
|
2026-01-27 18:27:29 +05:30
|
|
|
|
) {
|
|
|
|
|
|
// 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"]
|
2026-02-03 13:55:24 +05:30
|
|
|
|
if (
|
|
|
|
|
|
(existingProducts || PurchaseData)?.some(
|
|
|
|
|
|
(e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName
|
|
|
|
|
|
)
|
|
|
|
|
|
) {
|
|
|
|
|
|
const existingProduct = (existingProducts || PurchaseData)?.find(
|
|
|
|
|
|
(e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setMessageData(
|
|
|
|
|
|
`Product "${existingProduct?.ProdName} - ${existingProduct?.ProdVariantName}" already exists`
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return null;
|
2026-02-03 13:55:24 +05:30
|
|
|
|
} else {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
let ProductData1 = (productsList || productData)?.find(
|
2026-01-30 19:09:15 +05:30
|
|
|
|
(e) => e.ProdId == ProdId && e?.ProdVariantName == VariantName
|
2026-01-27 18:27:29 +05:30
|
|
|
|
);
|
|
|
|
|
|
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,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// NumberofPieceinside: ProductData1?.NoOfPcs,
|
|
|
|
|
|
// AmountPerPiece: ProductData1?.OnePcsPrice,
|
|
|
|
|
|
OnePcsPrice: ProductData1?.OnePcsPrice,
|
|
|
|
|
|
NoOfPcs: ProductData1?.NoOfPcs,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
TaxId: ProductData1?.TaxId,
|
|
|
|
|
|
TaxPercentage: ProductData1?.TaxPercentage,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
ProdVariantName: ProductData1?.ProdVariantName,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// ProdVariantName: 'Variant 1',
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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(
|
2026-01-30 19:09:15 +05:30
|
|
|
|
matchedProduct?.ProdVariantName,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`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,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
setDelete(false);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
form.setFieldsValue({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`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,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (applicationRestrictedFields.BatchAndModelDetails) {
|
|
|
|
|
|
form.setFieldsValue({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`BatchRef${localId}`]: record?.BatchRef,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const save = async (localId) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
try {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const row = await form.validateFields();
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
const modifiedObject = {};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
for (const key in row) {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// remove localId suffix from field names
|
|
|
|
|
|
if (key.endsWith(localId)) {
|
|
|
|
|
|
const newKey = key.replace(localId, '');
|
|
|
|
|
|
modifiedObject[newKey] = row[key];
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setPurchaseData((prev) =>
|
|
|
|
|
|
prev.map((item) =>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
item.localId === localId ? { ...item, ...modifiedObject } : item
|
2026-01-30 19:09:15 +05:30
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
setEditingKey('');
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('Save failed:', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handleKeyPress = async (e, record) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (e.key === 'Enter') {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await form.validateFields();
|
2026-01-30 19:09:15 +05:30
|
|
|
|
save(record.localId);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Save failed:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
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);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const updateRowValue = (localId, key, value) => {
|
|
|
|
|
|
setPurchaseData((prev) =>
|
|
|
|
|
|
prev.map((item) =>
|
|
|
|
|
|
item.localId === localId ? { ...item, [key]: value } : item
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
[`${key}${localId}`]: value,
|
|
|
|
|
|
});
|
2026-02-03 13:55:24 +05:30
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
const columns = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'SL.NO',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
key: 'sno',
|
|
|
|
|
|
render: (text, object, index) => (
|
|
|
|
|
|
<a style={{ color: 'black' }}>{index + 1}</a>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-01-30 19:09:15 +05:30
|
|
|
|
title: 'Name',
|
2026-01-27 18:27:29 +05:30
|
|
|
|
dataIndex: 'ProdName',
|
|
|
|
|
|
key: 'ProdName',
|
|
|
|
|
|
align: 'left',
|
|
|
|
|
|
render: (text, record, index) => (
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<a style={{ color: 'black' }}>{record?.ProdName}</a>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'Variant',
|
|
|
|
|
|
dataIndex: 'ProdVariantName',
|
|
|
|
|
|
key: 'ProdVariantName',
|
|
|
|
|
|
align: 'left',
|
|
|
|
|
|
render: (text, record, index) => (
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<a style={{ color: 'black' }}>{record?.ProdVariantName}</a>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
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
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onPressEnter={(e) => handleKeyPress(e, record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
onBlur={(e) => handleQtyChange(e, record)}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onChange={(e) => handleQtyChange(e, record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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">
|
2026-01-30 19:09:15 +05:30
|
|
|
|
Purchase Rate/unit
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</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
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onPressEnter={(e) => handleKeyPress(e, record)}
|
|
|
|
|
|
onChange={(e) => handlePurrateChange(e, record)}
|
|
|
|
|
|
onBlur={(e) => handlePurrateChange(e, record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// width: 120,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onPressEnter={(e) => handleKeyPress(e, record)}
|
|
|
|
|
|
onChange={(e) => handleTaxChange(e, record)}
|
|
|
|
|
|
onBlur={(e) => handleTaxChange(e, record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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,
|
|
|
|
|
|
},
|
2026-02-03 13:55:24 +05:30
|
|
|
|
...(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;
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
updateRowValues(record.localId, {
|
|
|
|
|
|
MRP: value,
|
|
|
|
|
|
SellPrice: value,
|
|
|
|
|
|
});
|
|
|
|
|
|
}}
|
|
|
|
|
|
onPressEnter={(e) => handleKeyPress(e, record)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
text
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
: []),
|
2026-01-27 18:27:29 +05:30
|
|
|
|
{
|
|
|
|
|
|
title: (
|
|
|
|
|
|
<Tooltip title="Selling price per unit" placement="top">
|
2026-01-30 19:09:15 +05:30
|
|
|
|
Selling Price
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</Tooltip>
|
|
|
|
|
|
),
|
|
|
|
|
|
dataIndex: 'SellPrice',
|
|
|
|
|
|
key: 'SellPrice',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
width: 70,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
editable: true,
|
|
|
|
|
|
render: (text, record, index) => {
|
|
|
|
|
|
return isEditing(record, index) ? (
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name={`SellPrice${record?.localId}`}
|
|
|
|
|
|
rules={[
|
|
|
|
|
|
{
|
|
|
|
|
|
validator: validateSellPrice(record),
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Input
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onPressEnter={(e) => handleKeyPress(e, record)}
|
|
|
|
|
|
onChange={(e) => handleSellPriceChange(e, record)}
|
|
|
|
|
|
onBlur={(e) => handleSellPriceChange(e, record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
...(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);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
form.setFieldsValue({
|
2026-02-03 13:55:24 +05:30
|
|
|
|
[`ManufDate${record?.localId}`]: formattedDate,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
});
|
2026-02-03 13:55:24 +05:30
|
|
|
|
}}
|
|
|
|
|
|
valueData={record?.ManufDate}
|
|
|
|
|
|
cancelFuture={true}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
formatDateForDisplay(text)
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
2026-01-30 19:09:15 +05:30
|
|
|
|
},
|
2026-02-03 13:55:24 +05:30
|
|
|
|
]
|
|
|
|
|
|
: []),
|
|
|
|
|
|
...(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;
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
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"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
: []),
|
2026-01-27 18:27:29 +05:30
|
|
|
|
{
|
|
|
|
|
|
title: 'Action',
|
|
|
|
|
|
dataIndex: 'Action',
|
|
|
|
|
|
key: 'Action',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
render: (_, record, index) => (
|
|
|
|
|
|
<a
|
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<DeleteFilled
|
|
|
|
|
|
style={{
|
|
|
|
|
|
color: '#FF4D4F',
|
|
|
|
|
|
}}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onClick={() => statusFormatters(record)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const statusFormatters = (record) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const localId = record?.localId;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// Remove row using localId (not index)
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const data = PurchaseData.filter((item) => item?.localId !== localId);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setDelete(true);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// Clear form fields for this row
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
[`BalanceQty${localId}`]: undefined,
|
|
|
|
|
|
[`ReceivedQty${localId}`]: undefined,
|
|
|
|
|
|
[`AcceptedQty${localId}`]: undefined,
|
|
|
|
|
|
[`RejectedQty${localId}`]: undefined,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`Freeqty${localId}`]: undefined,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
[`MRP${localId}`]: undefined,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`ManufDate${localId}`]: undefined,
|
|
|
|
|
|
[`ExpDate${localId}`]: undefined,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
[`SellPrice${localId}`]: undefined,
|
|
|
|
|
|
[`WhSalePrice${localId}`]: undefined,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`PurcDiscType${localId}`]: undefined,
|
|
|
|
|
|
[`Amount${localId}`]: undefined,
|
|
|
|
|
|
[`InwardPrice${localId}`]: undefined,
|
|
|
|
|
|
[`PurcDisc${localId}`]: undefined,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
[`offerSalePrice${localId}`]: undefined,
|
|
|
|
|
|
[`splSalePrice${localId}`]: undefined,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`OnePcsPrice${localId}`]: undefined,
|
|
|
|
|
|
[`NoOfPcs${localId}`]: undefined,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setVariants(undefined);
|
|
|
|
|
|
setPurchaseData(data);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setSelectedProductData(null);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
formRef?.current?.setFieldsValue({
|
|
|
|
|
|
ProdId: null,
|
|
|
|
|
|
});
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handleQtyChange = (e, record) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const { localId } = record;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
const sourceData = PurchaseData;
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const findIndex = sourceData.findIndex((item) => item?.localId === localId);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
if (findIndex === -1) return;
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const inputValue = e.target.value;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// ✅ Numeric validation
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (!/^\d*\.?\d*$/.test(inputValue)) {
|
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Only numeric values are allowed');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const qty = Number(inputValue) || 0;
|
|
|
|
|
|
const acceptedQty = qty;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
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: [],
|
|
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
|
|
setPurchaseData(newData);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// ✅ Sync form values
|
2026-01-27 18:27:29 +05:30
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
[`PurcDisc${localId}`]: 0,
|
|
|
|
|
|
[`BalanceQty${localId}`]: qty,
|
|
|
|
|
|
[`ReceivedQty${localId}`]: qty,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`AcceptedQty${localId}`]: acceptedQty,
|
|
|
|
|
|
[`RejectedQty${localId}`]: 0,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handlePurrateChange = (e, record) => {
|
|
|
|
|
|
const { localId, PurcDisc, PurcDiscType } = record;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const PurcRate = e.target.value;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// ✅ Numeric validation
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (!/^\d*\.?\d*$/.test(PurcRate)) {
|
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Only numeric values are allowed');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
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
|
2026-01-27 18:27:29 +05:30
|
|
|
|
let discountAmt = 0;
|
|
|
|
|
|
if (PurcDiscType === 'P') {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
discountAmt = (amount * Number(PurcDisc || 0)) / 100;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
} else {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
discountAmt = Number(PurcDisc || 0);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// 🧮 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);
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
formRef?.current?.setFieldsValue({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
PaymentAmount: totalAmount,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// 🔄 Sync row form fields
|
2026-01-27 18:27:29 +05:30
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
[`PurcDisc${localId}`]: 0,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`InwardPrice${localId}`]: Delete ? 0 : rate,
|
|
|
|
|
|
[`Amount${localId}`]: !isNaN(amount) ? amount : 0,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handleSellPriceChange = (e, record) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const { localId } = record;
|
|
|
|
|
|
const value = e?.target?.value;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// ✅ Numeric validation
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (!/^\d*\.?\d*$/.test(value)) {
|
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Only numeric values are allowed');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// 🔍 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)) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Only numeric values are allowed');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
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
|
2026-01-27 18:27:29 +05:30
|
|
|
|
form.setFieldsValue({
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`PurchaseTax${localId}`]: taxValue,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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 {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// ===============================
|
|
|
|
|
|
// 1️⃣ TAX VALIDATION
|
|
|
|
|
|
// ===============================
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const invalidTaxItems = PurchaseData?.filter((item) => {
|
|
|
|
|
|
const tax = item.PurchaseTax;
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (tax === undefined || tax === '' || tax === null) return false;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const num = Number(tax);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
return isNaN(num) || num < 0 || num > 99;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (invalidTaxItems.length > 0) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setMessageData(
|
|
|
|
|
|
'Please enter valid tax percentage (0–99%) for all items'
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// ===============================
|
|
|
|
|
|
// 2️⃣ SELL PRICE > MRP CHECK
|
|
|
|
|
|
// ===============================
|
2026-01-27 18:27:29 +05:30
|
|
|
|
if (
|
|
|
|
|
|
PurchaseData?.some(
|
|
|
|
|
|
(item) =>
|
|
|
|
|
|
item.SellPrice &&
|
|
|
|
|
|
item.MRP &&
|
2026-01-30 19:09:15 +05:30
|
|
|
|
Number(item.SellPrice) > Number(item.MRP)
|
2026-01-27 18:27:29 +05:30
|
|
|
|
)
|
|
|
|
|
|
) {
|
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Selling Price cannot be greater than MRP');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// ===============================
|
|
|
|
|
|
// 3️⃣ NO PRODUCT CHECK
|
|
|
|
|
|
// ===============================
|
|
|
|
|
|
if (!PurchaseData || PurchaseData.length === 0) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('No Product Selected');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// ===============================
|
|
|
|
|
|
// 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) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setMessageData('Please enter Qty and Amount for at least one product');
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// ===============================
|
|
|
|
|
|
// 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),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
// 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',
|
|
|
|
|
|
];
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
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,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
});
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const isPaidSelected = PurchaseTypeData?.some(
|
|
|
|
|
|
(item) =>
|
|
|
|
|
|
item.ConfigId === SelectedPurchaseType && item.ConfigName === 'Cash'
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (
|
|
|
|
|
|
(SupplierOpen !== 'own' || selectedSupplierName) &&
|
|
|
|
|
|
selectedSupplierData &&
|
|
|
|
|
|
isPaidSelected
|
|
|
|
|
|
) {
|
|
|
|
|
|
postData.PaymentAmount = PaymentAmount;
|
|
|
|
|
|
postData.PaymentType = selectedPaymentMode;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
postData.PaymentType = PaymentType;
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
postData.ProdDetails = processedData;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (formType === 'edit') {
|
|
|
|
|
|
postData.ProdId = editstate?.ProdId;
|
|
|
|
|
|
postData.InwardId = editstate?.InwardId;
|
|
|
|
|
|
postData.InwardDtlId = editstate?.InwardDtlId;
|
|
|
|
|
|
postData.UpdatedBy = UserId;
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
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',
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
|
navigate(`${subDirectory}setting/purchase-entry/`, {
|
|
|
|
|
|
state: {
|
|
|
|
|
|
Notiffy: {
|
|
|
|
|
|
messageType: 'success',
|
|
|
|
|
|
messageData: response?.data?.response,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
},
|
2026-01-30 19:09:15 +05:30
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
setMessageType('error');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setMessageData(response?.data?.response);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handleModelDataOpen = (selectedRowRecord) => {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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 || '',
|
|
|
|
|
|
}));
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
const newData = PurchaseData.map((item, index) =>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
index === selectedRowIndex
|
|
|
|
|
|
? { ...item, ProductIdentifierDtls: productIdentifierDtls }
|
|
|
|
|
|
: item
|
2026-01-30 19:09:15 +05:30
|
|
|
|
);
|
|
|
|
|
|
setPurchaseData(newData);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const handleFieldSetupSubmit = async () => {
|
|
|
|
|
|
const postData = {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
AppId: AppId,
|
|
|
|
|
|
CompId: CompId,
|
|
|
|
|
|
BranchId: BranchId,
|
|
|
|
|
|
Type: 'PE',
|
|
|
|
|
|
FormType: 'Purchase Entry',
|
|
|
|
|
|
TypeId: categoryId,
|
|
|
|
|
|
ConfigDtl: selectedFields?.map((field) => ({
|
|
|
|
|
|
ConfigId: field,
|
|
|
|
|
|
Access: 'Y',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
})),
|
2026-02-03 13:55:24 +05:30
|
|
|
|
CreatedBy: UserId,
|
|
|
|
|
|
};
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
const response = await dispatch(postFieldSetup(postData))?.unwrap();
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
|
setSelectedAdditionalColumn([...tempSelectedColumns]);
|
|
|
|
|
|
setShowColumnModal(false);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setTempSelectedColumns([]);
|
|
|
|
|
|
setMessageType('success');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
|
await getFieldSetup();
|
|
|
|
|
|
} else {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setMessageType('error');
|
|
|
|
|
|
setMessageData('Failed to set up fields');
|
2026-01-30 19:09:15 +05:30
|
|
|
|
}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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">
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<div className="userPageContent" style={{ paddingBottom: '1rem' }}>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<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)}
|
|
|
|
|
|
>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<TbUpload size={18} strokeWidth={3} />{' '}
|
|
|
|
|
|
<p> Scan Receipt (Auto-Fill)</p>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</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>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<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>
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<div className="inputFormSTOCKFORM">
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<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(
|
2026-02-03 13:55:24 +05:30
|
|
|
|
(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})`,
|
|
|
|
|
|
}))
|
2026-01-27 18:27:29 +05:30
|
|
|
|
: []
|
|
|
|
|
|
}
|
|
|
|
|
|
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'
|
|
|
|
|
|
) && (
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<>
|
|
|
|
|
|
<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 === ''
|
|
|
|
|
|
) {
|
2026-01-27 18:27:29 +05:30
|
|
|
|
return Promise.resolve();
|
2026-02-03 13:55:24 +05:30
|
|
|
|
}
|
|
|
|
|
|
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();
|
2026-01-27 18:27:29 +05:30
|
|
|
|
},
|
2026-02-03 13:55:24 +05:30
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<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>
|
|
|
|
|
|
</>
|
|
|
|
|
|
)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<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) => {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const [prodId, variantName] =
|
|
|
|
|
|
option.value.split('_');
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const product = productData.find(
|
2026-02-03 13:55:24 +05:30
|
|
|
|
(p) =>
|
|
|
|
|
|
p.ProdId === prodId &&
|
|
|
|
|
|
(p.ProdVariantName || 'Variant1') ===
|
|
|
|
|
|
variantName
|
2026-01-27 18:27:29 +05:30
|
|
|
|
);
|
|
|
|
|
|
const nameMatch = option.label
|
|
|
|
|
|
?.toLowerCase()
|
|
|
|
|
|
.includes(productSearchText?.toLowerCase());
|
|
|
|
|
|
const qrMatch =
|
|
|
|
|
|
product?.QRCode?.toLowerCase() ==
|
|
|
|
|
|
productSearchText?.toLowerCase();
|
|
|
|
|
|
return nameMatch || qrMatch;
|
|
|
|
|
|
}}
|
|
|
|
|
|
options={
|
|
|
|
|
|
!scanner
|
|
|
|
|
|
? productData?.map((option) => ({
|
2026-02-03 13:55:24 +05:30
|
|
|
|
value: `${option.ProdId}_${option.ProdVariantName}`,
|
|
|
|
|
|
label: `${option.ProdName} (${option.Size} ${option.UomName})${option?.BrandName ? ` - ${option?.BrandName}` : ''} - ${option.ProdVariantName}`,
|
|
|
|
|
|
}))
|
2026-01-27 18:27:29 +05:30
|
|
|
|
: []
|
|
|
|
|
|
}
|
|
|
|
|
|
onSelect={async (value, option) => {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const [prodId, variantName] = value.split('_');
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const product = productData.find(
|
|
|
|
|
|
(p) =>
|
|
|
|
|
|
p.ProdId === prodId &&
|
|
|
|
|
|
p.ProdVariantName === variantName
|
|
|
|
|
|
);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
const newProduct = await ProductDropDownChange(
|
2026-01-30 19:09:15 +05:30
|
|
|
|
product?.ProdVariantName,
|
|
|
|
|
|
prodId,
|
2026-01-27 18:27:29 +05:30
|
|
|
|
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'}
|
|
|
|
|
|
>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<FaLink
|
|
|
|
|
|
onClick={() => setIsModalOpen(true)}
|
|
|
|
|
|
size={18}
|
|
|
|
|
|
/>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
</Tooltip>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<Tooltip title={'Add All Products'} placement={'top'}>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<button
|
|
|
|
|
|
type="button"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
className="addallProductTBN"
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onClick={async () => {
|
|
|
|
|
|
const allProducts = await Promise.all(
|
|
|
|
|
|
productData.map(async (product) => {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
const newProduct =
|
|
|
|
|
|
await ProductDropDownChange(
|
|
|
|
|
|
product?.ProdVariantName, // Use actual variant name
|
|
|
|
|
|
product.ProdId,
|
|
|
|
|
|
{
|
|
|
|
|
|
label: `${product.ProdName} (${product.Size} ${product.UomName})${product?.BrandName ? ` - ${product?.BrandName}` : ''}`,
|
|
|
|
|
|
},
|
|
|
|
|
|
productData
|
|
|
|
|
|
);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
return newProduct;
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
const validProducts = allProducts.filter(Boolean);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setPurchaseData([
|
|
|
|
|
|
...validProducts,
|
|
|
|
|
|
...PurchaseData,
|
|
|
|
|
|
]);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
|
|
|
|
|
// Set form field values for all added products
|
2026-02-03 13:55:24 +05:30
|
|
|
|
validProducts.forEach((product) => {
|
2026-01-30 19:09:15 +05:30
|
|
|
|
const localId = product?.localId;
|
|
|
|
|
|
form?.setFieldsValue({
|
|
|
|
|
|
[`SellPrice${localId}`]: product?.SellPrice,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
[`PurchaseTax${localId}`]:
|
|
|
|
|
|
product?.PurchaseTax,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`BalanceQty${localId}`]: product?.BalanceQty,
|
2026-02-03 13:55:24 +05:30
|
|
|
|
[`ReceivedQty${localId}`]:
|
|
|
|
|
|
product?.ReceivedQty,
|
|
|
|
|
|
[`AcceptedQty${localId}`]:
|
|
|
|
|
|
product?.AcceptedQty,
|
|
|
|
|
|
[`RejectedQty${localId}`]:
|
|
|
|
|
|
product?.RejectedQty,
|
|
|
|
|
|
[`InwardPrice${localId}`]:
|
|
|
|
|
|
product?.InwardPrice,
|
2026-01-30 19:09:15 +05:30
|
|
|
|
[`Amount${localId}`]: product?.Amount,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
Add All
|
|
|
|
|
|
</button>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</Tooltip>
|
|
|
|
|
|
</Form.Item>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
{isModalOpen && (
|
|
|
|
|
|
<SupplierProductMappingForm
|
|
|
|
|
|
isModalOpen={isModalOpen}
|
|
|
|
|
|
setIsModalOpen={() => {
|
|
|
|
|
|
(setIsModalOpen(false),
|
|
|
|
|
|
handleSupplierDropDownChange(
|
|
|
|
|
|
selectedSupplierData
|
|
|
|
|
|
));
|
|
|
|
|
|
}}
|
|
|
|
|
|
CompId={CompId}
|
|
|
|
|
|
BranchId={BranchId}
|
|
|
|
|
|
AppId={AppId}
|
|
|
|
|
|
setMessage={setMessage}
|
|
|
|
|
|
onMappingAdded={handleModalSubmited}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<div className="productSearchRecipt">
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: '10px',
|
|
|
|
|
|
justifyContent: 'flex-end',
|
|
|
|
|
|
fontFamily: 'Poppins',
|
|
|
|
|
|
fontWeight: '500',
|
|
|
|
|
|
textDecoration: 'underline',
|
|
|
|
|
|
cursor: 'Pointer',
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
}}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
onClick={() => {
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setTempSelectedColumns([
|
|
|
|
|
|
...selectedAdditionalColumn,
|
|
|
|
|
|
]);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setShowColumnModal(true);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
}}
|
|
|
|
|
|
>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<Tooltip title="Add Fields" placement="left">
|
|
|
|
|
|
<IoSettingsOutline
|
|
|
|
|
|
style={{ cursor: 'pointer', fontSize: '20px' }}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
</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>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
className="Product-table stockformTabele"
|
|
|
|
|
|
style={{
|
|
|
|
|
|
maxwidth: '500px',
|
|
|
|
|
|
overflowX: 'auto',
|
|
|
|
|
|
scrollbarWidth: 'thin',
|
2026-02-03 13:55:24 +05:30
|
|
|
|
maxHeight: '50vh',
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}}
|
|
|
|
|
|
>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
{/* <Form form={form} component={false}>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<Table
|
|
|
|
|
|
className="purchase-receipt-table"
|
|
|
|
|
|
bordered
|
2026-01-30 19:09:15 +05:30
|
|
|
|
dataSource={filteredPurchaseData.length > 0 ? filteredPurchaseData : PurchaseData}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
columns={columns}
|
|
|
|
|
|
rowClassName="editable-row"
|
|
|
|
|
|
onRow={(record, index) => ({
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
edit(record, index);
|
|
|
|
|
|
},
|
|
|
|
|
|
})}
|
|
|
|
|
|
pagination={false}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
/> */}
|
|
|
|
|
|
<Form form={form} component={false}>
|
|
|
|
|
|
<Table
|
|
|
|
|
|
className="purchase-receipt-table"
|
|
|
|
|
|
bordered
|
2026-02-03 13:55:24 +05:30
|
|
|
|
dataSource={
|
|
|
|
|
|
isSearching ? filteredPurchaseData : PurchaseData
|
|
|
|
|
|
}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
columns={columns}
|
|
|
|
|
|
rowClassName="editable-row"
|
|
|
|
|
|
onRow={(record) => ({
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
edit(record);
|
|
|
|
|
|
},
|
|
|
|
|
|
})}
|
|
|
|
|
|
pagination={false}
|
|
|
|
|
|
locale={{
|
2026-02-03 13:55:24 +05:30
|
|
|
|
emptyText: isSearching
|
|
|
|
|
|
? 'No matching products found'
|
|
|
|
|
|
: 'No data',
|
2026-01-30 19:09:15 +05:30
|
|
|
|
}}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</Form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Form>
|
|
|
|
|
|
</div>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<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>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</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"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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) =>
|
2026-02-03 13:55:24 +05:30
|
|
|
|
(e.target.value = e.target.value.replace(
|
|
|
|
|
|
/[^0-9]/g,
|
|
|
|
|
|
''
|
|
|
|
|
|
))
|
2026-01-27 18:27:29 +05:30
|
|
|
|
}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="SuppEmail"
|
|
|
|
|
|
rules={[{ validator: validateEmail }]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<InputField
|
|
|
|
|
|
label={<label>MailId</label>}
|
|
|
|
|
|
autocomplete="off"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="SuppPOCEmail"
|
|
|
|
|
|
rules={[{ validator: validateEmail }]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<InputField
|
|
|
|
|
|
label={<label class="">POC MailId</label>}
|
|
|
|
|
|
autocomplete="off"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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>}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={(editstate?.SellPrice || QrcodeExistsData?.[0]?.SellPrice)? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="ProdCat"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// rules={[
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // required: true,
|
|
|
|
|
|
// message:"Please Select Category"
|
|
|
|
|
|
// },
|
|
|
|
|
|
// ]}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
>
|
|
|
|
|
|
<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}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// disabled={editstate?.Brand ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
<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)
|
|
|
|
|
|
}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// disabled={editstate?.QRCode ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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) && (
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<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();
|
2026-01-27 18:27:29 +05:30
|
|
|
|
},
|
2026-02-03 13:55:24 +05:30
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<ScannerInputField
|
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
|
label="Scanner / AddOnePcQrcode"
|
|
|
|
|
|
onKeyPress={handleKeyPressSingle}
|
|
|
|
|
|
valueData={QrcodeSingleFinalVal}
|
|
|
|
|
|
isOnChange={
|
|
|
|
|
|
QrcodeSingleFinalVal ? true : false
|
|
|
|
|
|
}
|
|
|
|
|
|
onChange={handleInputSingle}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
// disabled={editstate?.OnePcQR ? true : false}
|
2026-02-03 13:55:24 +05:30
|
|
|
|
/>
|
|
|
|
|
|
{QrcodeSingleExistsVal &&
|
|
|
|
|
|
QrcodeSingleExistsVal}
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
</>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{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"
|
2026-02-03 13:55:24 +05:30
|
|
|
|
// isOnChange={editstate?.NoOfPcs ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
|
|
|
|
|
</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}
|
2026-01-30 19:09:15 +05:30
|
|
|
|
width={600}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
buttonText="Submit"
|
|
|
|
|
|
children={
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<div className="imeiSNTable">
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<Table
|
|
|
|
|
|
components={components}
|
|
|
|
|
|
rowClassName={() => 'editable-row'}
|
|
|
|
|
|
bordered
|
|
|
|
|
|
dataSource={dataSource}
|
|
|
|
|
|
columns={IMEIcolumns}
|
|
|
|
|
|
pagination={{ showSizeChanger: false }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
}
|
|
|
|
|
|
handleSubmit={handleModelDataSumbitOrClose}
|
|
|
|
|
|
handleCancel={handleModelDataSumbitOrClose}
|
|
|
|
|
|
></DefaultModal>
|
|
|
|
|
|
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<DefaultModal
|
|
|
|
|
|
title="Select Additional Fields"
|
|
|
|
|
|
open={showColumnModal}
|
|
|
|
|
|
footer={true}
|
|
|
|
|
|
buttonText="Apply"
|
|
|
|
|
|
destroyOnClose={true}
|
|
|
|
|
|
handleSubmit={handleFieldSetupSubmit}
|
|
|
|
|
|
handleCancel={() => {
|
|
|
|
|
|
setShowColumnModal(false);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setSelectedFields([
|
|
|
|
|
|
...selectedAdditionalColumn
|
|
|
|
|
|
.map(
|
|
|
|
|
|
(col) =>
|
|
|
|
|
|
tableFieldPreferences?.find((pref) => pref.label === col)
|
|
|
|
|
|
?.value
|
|
|
|
|
|
)
|
|
|
|
|
|
.filter(Boolean),
|
|
|
|
|
|
]);
|
2026-01-30 19:09:15 +05:30
|
|
|
|
setTempSelectedColumns([...selectedAdditionalColumn]);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div style={{ padding: '20px' }}>
|
|
|
|
|
|
{tableFieldPreferences?.map((option) => (
|
2026-02-03 13:55:24 +05:30
|
|
|
|
<div key={option.value} className="Customized_QuickAdd">
|
2026-01-30 19:09:15 +05:30
|
|
|
|
<label>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
checked={selectedFields?.includes(option.value)}
|
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
|
const isChecked = e.target.checked;
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setSelectedFields((prev) =>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
isChecked
|
|
|
|
|
|
? [...prev, option.value]
|
2026-02-03 13:55:24 +05:30
|
|
|
|
: prev.filter((item) => item !== option.value)
|
2026-01-30 19:09:15 +05:30
|
|
|
|
);
|
2026-02-03 13:55:24 +05:30
|
|
|
|
setTempSelectedColumns((prev) =>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
isChecked
|
|
|
|
|
|
? [...prev, option.label]
|
2026-02-03 13:55:24 +05:30
|
|
|
|
: prev.filter((item) => item !== option.label)
|
2026-01-30 19:09:15 +05:30
|
|
|
|
);
|
|
|
|
|
|
}}
|
|
|
|
|
|
style={{ marginRight: '8px' }}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
/>
|
2026-01-30 19:09:15 +05:30
|
|
|
|
{option.label}
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</DefaultModal>
|
|
|
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
|
<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;
|