import { useState, useEffect, useCallback } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { PlusOutlined, EyeOutlined } from '@ant-design/icons';
import { Table } from 'antd';
import {
changeBreadCrumb,
getEmpAccess,
} from '../../Features/AppPage/CenterPage.js';
import { Tables } from '../../Components/Tables/Table';
import FormHeader from '../PageComponents/FormHeader.jsx';
import Search from '../../Components/Forms/Search.jsx';
import Buttons from '../../Components/Forms/Buttons';
import { getSession, dateFormatChange, ExtractDateFormate } from '../../Services/Others';
import { Messages } from '../../Components/Notifications/Messages';
import {
getStockData,
getProductData,
getalltVariantData,
Bulkstockpost,
purchaseDataSelector,
getPurchaseData,
} from '../../Features/StockMaster/StockMaster.js';
import {
supplierSelector,
getSupplierData,
productDataSelector,
taxSelector,
getAdmin,
} from '../../Features/ProductPage/ProductPage.js';
import {
emptyExcelData,
excelDataSelector,
} from '../../Features/ExcelUploadPage/ExcelUploadPage.js';
import moment from 'moment';
import StockExcel from '../StockMaster/StockBulkUpload.jsx';
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
import TertiaryButton from '../../Components/Forms/tertiaryButton.jsx';
import { extractLastNumberOrderId } from '../../Services/Others.js';
import '../../Styles/Employee/EmpMaster.scss';
import { IoEye } from 'react-icons/io5';
import { useAuth } from '../../AuthContext.jsx';
import { getPreferenceData } from '../../Features/BookingScreen/BookingData/BookingData.js';
const subDirectory = import.meta.env.BASE_URL;
const items = [
{
name: 'Home',
link: `${subDirectory}app-page/home`,
},
{
name: 'Product Receipt',
link: `${subDirectory}setting/purchase-entry`,
},
];
const StockList = () => {
const { SadminuserAccess } = useAuth();
let SAAccessCommonMaster = SadminuserAccess?.find(
(e) => e?.MenuName === 'Purchase Entry'
);
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const AppId = getSession('AppId');
const UserId = getSession('UserId');
const UserType = getSession('UserType');
const StockData = useSelector(purchaseDataSelector);
const SupplierData = useSelector(supplierSelector);
const excelDataValues = useSelector(excelDataSelector);
const TaxData = useSelector(taxSelector);
const [filteredInfo, setFilteredInfo] = useState({});
const [sortedInfo, setSortedInfo] = useState({});
const [searchedText, setSearchedText] = useState('');
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [empData, setEmpData] = useState();
const [addnewAccess, setaddnewAccess] = useState(true);
const [page, setpage] = useState(1);
const [open, setOpen] = useState(false);
const [Exceldatasubmit, setExceldatasubmit] = useState(null);
const [Totaltax, setTotaltax] = useState(null);
const [Totalamount, setTotalamount] = useState(null);
const [Taxdatas, setTaxdatas] = useState();
const [Billamount, setBillamount] = useState(null);
const [Productdata, setProductdata] = useState();
const [Varientdata, setVarientdata] = useState();
const [ProddtlModal, setProddtlModal] = useState(false);
const [ImeiSerialModal, setImeiSerialModal] = useState(false);
const [allowDecimal, setAllowDecimal] = useState(false);
const [PurcProddetail, setPrucProddetail] = useState([]);
const [IMEISeriandata, setIMEISeriandata] = useState([]);
useEffect(() => {
try {
fetchData();
// dispatch(
// getStockData({ CompId: CompId, BranchId: BranchId, AppId: AppId })
// ).unwrap();
} catch (err) {
console.log(err, 'err');
}
getPreference();
// if (UserType === "Employee") {
// fetchApi()
// }
}, []);
useEffect(() => {
if (UserType === 'Employee') {
fetchApi();
}
}, [UserType]);
useEffect(() => {
let hasAccess = false;
if (UserType === 'Admin' || UserType === 'Super Admin') {
hasAccess = true;
} else if (UserType === 'Employee') {
hasAccess = empData?.AddAccess === 'Y';
} else if (UserType === 'Super Admin User') {
hasAccess = SAAccessCommonMaster?.AddAccess === 'Y';
}
setaddnewAccess(!hasAccess);
}, [empData, SAAccessCommonMaster, UserType]);
const fetchApi = async () => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
EmpId: UserId,
};
let response = await dispatch(getEmpAccess(data)).unwrap();
let datas = response?.data?.data?.[0]?.EmpAccessDetails?.filter(
(item) => item.ConfigName === 'Purchase Entry'
);
setEmpData(datas?.[0]);
};
useEffect(() => {
dispatch(changeBreadCrumb({ items: items }));
}, []);
async function fetchData() {
if (location?.state?.Notiffy) {
setMessageType(location?.state?.Notiffy.messageType);
setMessageData(location?.state?.Notiffy.messageData);
}
}
const handleChange = (pagination, filters, sorter) => {
setFilteredInfo(filters);
setSortedInfo(sorter);
};
const handlePageChange = (current) => {
setpage(current);
};
const onSearch = (value) => {
setSearchedText(value);
};
const onSearchChange = (e) => {
setSearchedText(e?.target?.value);
};
const getPreference = async () => {
const data = { AppId: AppId, CompId: CompId, BranchId: BranchId };
const { data: res } = await dispatch(getPreferenceData(data)).unwrap()
const decimalSetting = res?.data?.[0]?.SettingDtlDetails?.find((setting) => setting?.SettingIdName?.toLowerCase() === "decimal" && setting?.SettingValue === 'Y');
if (decimalSetting) {
setAllowDecimal(true)
}
}
const actionsFormatter = async (row, rowIndex) => {
navigate(
`${subDirectory}setting/purchase-entry/update`,
{ state: { editstate: row } },
{ key: rowIndex }
);
};
const ViewProductdetails = (proddetails) => {
setPrucProddetail(proddetails);
setProddtlModal(true);
};
const handleProductmodalCancel = () => {
setPrucProddetail([]);
setProddtlModal(false);
};
const handleIMEISerialmodalCancel = () => {
setImeiSerialModal(false);
};
// WRITED BY SREE
function safeRound(amountStr) {
if (amountStr == null) return allowDecimal ? '0.00' : '0';
const cleaned = String(amountStr).replace(/[^0-9.-]+/g, '');
const num = Number(cleaned);
if (isNaN(num)) return allowDecimal ? '0.00' : '0';
return allowDecimal ? num.toFixed(2) : Math.round(num).toString();
}
const columns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
render: (text, object, index) => (
{(page - 1) * 10 + index + 1}
),
},
{
title: 'Invoice No',
dataIndex: 'InvoiceNo',
key: 'InvoiceNo',
align: 'center',
render: (text, row) => (
{extractLastNumberOrderId(text, row?.FYStatus)}
),
filteredValue: [searchedText],
onFilter: (value, record) => {
return extractLastNumberOrderId(record.InvoiceNo, record?.FYStatus)?.toString()
.toLowerCase()
.includes(value.toLowerCase());
},
},
{
title: 'Invoice Amount',
dataIndex: 'NetAmount',
key: 'NetAmount',
align: 'right',
// ellipsis: true,
render: (text) => {safeRound(text)},
},
{
title: 'Supp Name',
dataIndex: 'CustSuppName',
key: 'CustSuppName',
align: 'center',
render: (text, row) => (
{row?.CustSuppName || '-'}
),
},
{
title: 'Supp Invoice No',
dataIndex: 'SuppInvoiceNo',
key: 'SuppInvoiceNo',
align: 'center',
render: (text, row) => (
{row?.SuppInvoiceNo || '-'}
),
},
{
title: 'Date',
dataIndex: 'InvoiceDate',
key: 'InvoiceDate',
align: 'center',
render: (text) => (
{ExtractDateFormate(text)}
),
},
{
title: 'Product Details',
key: 'ProdDetails',
dataIndex: 'ProdDetails',
align: 'center',
render: (ProdDetails, record) => (
ViewProductdetails(ProdDetails)}
/>
),
},
];
const Proddetailcolumns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
render: (text, object, index) => (
{(page - 1) * 10 + index + 1}
),
},
{
title: 'Product Name',
dataIndex: 'ProdName',
key: 'ProdName',
},
{
title: 'UOM',
dataIndex: 'UOMName',
key: 'UOMName',
align: 'center',
render: (text, row) => (
{row.Size} {row.UOMName}
),
},
{
title: 'MRP',
dataIndex: 'MRP',
key: 'MRP',
align: 'right',
render: (text) => {safeRound(text)},
},
{
title: 'Retail Price',
dataIndex: 'SellPrice',
key: 'SellPrice',
align: 'right',
render: (text) => {safeRound(text)},
},
{
title: 'Accepted Quantity',
dataIndex: 'AcceptedQty',
key: 'AcceptedQty',
align: 'right',
render: (text) => {text},
},
{
title: 'IMEI/SERIAL-NO',
dataIndex: 'AcceptedQty',
key: 'AcceptedQty',
align: 'right',
render: (text, record, index) => {
return (
<>
{' '}
HandleimedSerialData(record)}
className="shape-preview"
/>
>
);
},
},
];
const HandleimedSerialData = (record) => {
setImeiSerialModal(true);
const merged = record.ProductIdentifierDtls.map((device, index) => ({
...device,
...record.ProductIdentifierDtls[index], // Add ProductIdentifierDtls data if it exists
}));
setIMEISeriandata(merged);
};
const IMEISerialcolumns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
render: (text, object, index) => (
{(page - 1) * 10 + index + 1}
),
},
{
title: 'IMEI1',
dataIndex: 'IMEI1',
key: 'IMEI1',
render: (text) => {text ? text : '-'},
},
{
title: 'IMEI2',
dataIndex: 'IMEI2',
key: 'IMEI2',
align: 'center',
render: (text) => {text ? text : '-'},
},
{
title: 'Mac Id',
dataIndex: 'MacId',
key: 'MacId',
align: 'center',
render: (text) => {text ? text : '-'},
},
{
title: 'SerialNumber',
dataIndex: 'SerialNumber',
key: 'SerialNumber',
align: 'center',
render: (text) => {text ? text : '-'},
},
];
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const handelAddButton = () => {
navigate(`${subDirectory}setting/purchase-entry/new`);
};
//------------------------------------------------------------------------------------------------------------------------------
useEffect(() => {
Bulkuploadsubdata();
}, []);
const Bulkuploadsubdata = async () => {
dispatch(
getSupplierData({ AppId: AppId, BranchId: BranchId, CompId: CompId })
);
dispatch(
getPurchaseData({ AppId: AppId, BranchId: BranchId, CompId: CompId })
);
let ProdData = {
AppId: AppId,
BranchId: BranchId,
CompId: CompId,
StockAvailable: 'Y',
};
let res = await dispatch(getProductData(ProdData)).unwrap();
setProductdata(res?.data?.data);
let data = { CompId: CompId, BranchId: BranchId, AppId: AppId };
let Varientdatas = await dispatch(getalltVariantData(data)).unwrap();
setVarientdata(Varientdatas.data?.data);
dispatch(getAdmin({ AppId: AppId, CompId: CompId }));
};
const handleCancel = () => {
setOpen(false);
handleResetExcelData();
};
const openModal = () => {
setOpen(true);
// setEditState(false);
};
const handleResetExcelData = () => {
dispatch(emptyExcelData());
};
useEffect(() => {
let Totaltax = Taxdatas?.reduce((accumulator, currentValue) => {
return accumulator + (currentValue.TaxAmt || 0);
}, 0);
let Totalamount = Taxdatas?.reduce((accumulator, currentValue) => {
return accumulator + parseInt(currentValue.Amount, 10);
}, 0);
let Billamount = Totalamount - Totaltax;
setTotaltax(Totaltax);
setTotalamount(Totalamount);
setBillamount(Billamount);
}, [Taxdatas]);
useEffect(() => {
let updatedExceldatasubmit = Exceldatasubmit?.map((excelItem) => {
const [productName, sizeAndUom] = (excelItem?.ProductName?.split(' (')) || [];
const [size, uomName] = (sizeAndUom ? sizeAndUom.slice(0, -1).split(' ') : []);
const matchingProduct = Productdata?.find(
(product) =>
product.ProdName === productName &&
product.Size.toString() === size &&
product.UomName === uomName
);
if (matchingProduct) {
const TaxAmt =
(parseInt(excelItem?.Amount) *
parseInt(matchingProduct.TaxPercentage)) /
(100 + parseInt(matchingProduct.TaxPercentage))?.toFixed(2);
return {
...excelItem,
TaxId: matchingProduct.TaxId,
TaxPercentage: matchingProduct.TaxPercentage,
TaxAmt: TaxAmt,
};
}
return excelItem;
});
setTaxdatas(updatedExceldatasubmit);
}, [Exceldatasubmit]);
const handleSubmitbulk = (excelData) => {
setExceldatasubmit(excelData);
};
const createGroupKey = (data) => {
if (data.OwnWithPaid === 'Own') {
// For "Own", only check OwnWithPaid, InwardDate, and DueDate
return `Own|${data.InwardDate}|${data.DueDate}`;
} else {
// For "With Paid", check all fields
let key = `WithPaid|${data.InwardDate}|${data.DueDate}|${data.PaymentType}|${data.PaymentMode}`;
if (data.InvoiceDeliveryChallan === 'Invoice') {
key += `|Invoice|${data.SupplierInvoiceNumber}|${data.SupplierInvoiceDate}`;
} else if (data.InvoiceDeliveryChallan === 'Delivery Challan') {
key += `|DeliveryChallan|${data.DeliveryChallanNo}|${data.DeliveryInvoiceDate}`;
}
return key;
}
};
// Helper function to check if product already exists in ProdDetails
const isDuplicateProduct = (prodDetails, newItem) => {
return prodDetails.some(item =>
item.ProdName === newItem.ProdName &&
item.VariantName === newItem.VariantName &&
item.MRP === newItem.MRP &&
item.SalesPrice === newItem.SalesPrice &&
item.Quantity === newItem.Quantity &&
item.RejectedQty === newItem.RejectedQty
);
};
const handleSubmit = async () => {
let FilterData = Exceldatasubmit?.filter((a) => a['ProductName'] != '');
if (FilterData && FilterData.length > 0) {
const groupedData = {};
FilterData.forEach((data) => {
const groupKey = createGroupKey(data);
if (!groupedData[groupKey]) {
groupedData[groupKey] = {
groupInfo: {
Supplier: data.Supplier,
OwnWithPaid: data.OwnWithPaid,
InvoiceDeliveryChallan: data.InvoiceDeliveryChallan,
PaymentType: data.PaymentType,
PaymentMode: data.PaymentMode,
InwardDate: data.InwardDate,
SupplierInvoiceNumber: data.SupplierInvoiceNumber,
SupplierInvoiceDate: data.SupplierInvoiceDate,
DeliveryChallanNo: data.DeliveryChallanNo,
DeliveryInvoiceDate: data.DeliveryInvoiceDate,
DueDate: data.DueDate,
},
products: []
};
}
// Check if product is not duplicate before adding
if (!isDuplicateProduct(groupedData[groupKey].products, data)) {
groupedData[groupKey].products.push(data);
}
});
const commonData = {
AppId: getSession('AppId'),
CompId: getSession('CompId'),
BranchId: getSession('BranchId'),
CreatedBy: getSession('UserId'),
};
const formattedData = Object.values(groupedData).map((group) => {
const { groupInfo, products } = group;
// Calculate totals based on products
const Totaltax = products.reduce((acc, item) => {
return acc + (parseFloat(item.TaxAmt?.replace(/,/g, '')) || 0);
}, 0);
const Totalamount = products.reduce((acc, item) => {
return acc + parseFloat(item.Amount?.replace(/,/g, '') || 0);
}, 0);
const Billamount = Totalamount - Totaltax;
// Calculate PaymentAmount from products
const PaymentAmount = products.reduce((acc, item) => {
const amount = parseFloat(item.PaymentAmount?.replace(/,/g, '') || 0);
return acc + amount;
}, 0);
return {
...commonData, // Assuming commonData is defined elsewhere
SuppName: groupInfo.Supplier,
OwnWithPaid: groupInfo.OwnWithPaid,
InvoiceDeliveryChallan: groupInfo.InvoiceDeliveryChallan,
PayType: groupInfo.PaymentType,
PaymentType: groupInfo.PaymentMode || groupInfo.PaymentType,
PaymentMode: groupInfo.PaymentMode,
PaymentAmount: PaymentAmount.toFixed(2),
InvoiceDate: groupInfo.InwardDate
? moment(groupInfo.InwardDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
SuppInvoiceNo: groupInfo.SupplierInvoiceNumber,
SuppInvoiceDate: groupInfo.SupplierInvoiceDate
? moment(groupInfo.SupplierInvoiceDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
DeliveryChallanNo: groupInfo.DeliveryChallanNo,
DeliveryInvoiceDate: groupInfo.DeliveryInvoiceDate
? moment(groupInfo.DeliveryInvoiceDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
DueDate: groupInfo.DueDate
? moment(groupInfo.DueDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
InvoiceAmount: Totalamount.toFixed(2),
TaxAmount: Totaltax.toFixed(2),
TotalAmount: Totalamount.toFixed(2),
BillAmount: Billamount.toFixed(2),
PaymentStatus: "S",
PurOrderStatus: "P",
ProdDetails: products.map((item) => ({
ProdName: item.ProductName,
ProdVariantName: item.VariantName,
Quantity: item.Quantity,
ReceivedQty: item.ReceivedQty,
RejectedQty: item.RejectedQty,
AcceptedQty: item.AcceptedQty,
FreeQty: item.FreeQty,
ManufDate: item.ManufactureDate
? moment(item.ManufactureDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
ExpDate: item.ExpireDate
? moment(item.ExpireDate, 'YYYY-MM-DD').format('YYYY-MM-DDTHH:mm:ss')
: null,
BatchNo: item.BatchNo,
ModelNo: item.ModelNo,
InwardPrice: item.PurchaseRate,
Amount: item.Amount,
MRP: item.MRP,
SellPrice: item.SalesPrice,
OnePcsPrice: item.AmountPerPiece,
NoOfPcs: item.NumberofPieceInside,
})),
};
});
let postDatas = { ...commonData, StockDetails: formattedData };
let response = await dispatch(Bulkstockpost(postDatas)).unwrap();
if (response?.data?.statusCode == 1) {
setMessageType('success');
setMessageData(response?.data?.response);
// dispatch(
// getStockData({
// AppId: AppId,
// BranchId: BranchId,
// CompId: CompId,
// StockAvailable: 'Y',
// })
// );
await Bulkuploadsubdata();
} else {
setMessageType('error');
setMessageData(response?.data?.response);
}
handleResetExcelData();
handleCancel();
} else {
setMessageType('error');
setMessageData('No data to submit. Please upload an Excel file.');
}
};
// const ProductName = Productdata ?.map((e)=>e.ProdName+' '(+e.Size+' '+e.UomName))
const ProductName = Productdata?.map(
(e) => `${e.ProdName} (${e.Size} ${e.UomName})`
);
// const ProductName = Varientdata?.map((e)=>e.ProdName)
// const ProductName = Productdata?.map((e)=>e.ProdName)
// const ProductSize = Productdata ?.map((e)=>e.Size)
// const ProductUomName = Productdata ?.map((e)=>e.UomName)
const SupplierNames = SupplierData?.map((e) => e.SuppName);
const TaxDatas = TaxData.map((e) => e.TaxIdName);
const TaxData1 = TaxData.map((e) => e.TaxPercentage);
const combinedTaxData = TaxDatas.map(
(taxIdName, index) => `${taxIdName} - ${TaxData1[index]}%`
);
// const ProductName = Productdata?.map((e) => `${e.ProdName} (${e.Size} ${e.UomName})`);
const ProductId = Productdata?.map((e) => e.ProdId);
const VarientName = Varientdata?.map((e) => e.ProdVariantName);
const InwardDtlIds = Varientdata?.map((e) => e.InwardDtlId);
const StockProductId = Varientdata?.map((e) => e.ProdId);
// let proddetail = StockData?.map((e) => {
// return {
// ...e,
// ProdDetails: e.ProdDetails?.map((d) => ({
// ...d,
// InvoiceNo: e.InvoiceNo,
// InvoiceDate: e.InvoiceDate,
// InvoiceAmt: e.InvoiceAmount
// }))
// };
// });
// let subObjectsArray = [];
// // Iterate over mainObjects and concatenate subObjects arrays
// proddetail.forEach(obj => {
// subObjectsArray = subObjectsArray.concat(obj.ProdDetails);
// });
// function safeRound(amountStr) {
// if (amountStr == null) return allowDecimal ? '0.00' : '0';
// const cleaned = String(amountStr).replace(/[^0-9.-]+/g, '');
// const num = Number(cleaned);
// if (isNaN(num)) return allowDecimal ? '0.00' : '0';
// return allowDecimal ? num.toFixed(2) : Math.round(num).toString();
// }
return (
handelAddButton()}
disabled={addnewAccess}
color="901D77"
icon={}
>
OPEN
0 ? 3000 : 600}
children={
<>
>
}
handleSubmit={handleSubmit}
handleCancel={handleCancel}
/>
}
/>
}
/>
);
};
export default StockList;