diff --git a/retail updated jan 27.zip b/retail updated jan 27.zip deleted file mode 100644 index c983482..0000000 Binary files a/retail updated jan 27.zip and /dev/null differ diff --git a/src/Pages/Product/Printstyles.js b/src/Pages/Product/Printstyles.js index 056e69c..1ebcbd6 100644 --- a/src/Pages/Product/Printstyles.js +++ b/src/Pages/Product/Printstyles.js @@ -297,7 +297,7 @@ height: 149mm; padding: 4px 4px; border-radius: 6px; } -.Qrcodeimage, +// .Qrcodeimage, // .Barcodeimage { // display: flex; // gap: 6px; @@ -341,61 +341,13 @@ height: 149mm; // width: 100%; // justify-content: space-evenly; // } -#25X502cross{ - margin: 0 !important; - padding: 0 !important; - width: 101.6mm; -} - .Cross25X50container{ - display: grid; - grid-template-columns: repeat(2, 50mm); - column-gap: 0.5mm; - width: 101.6mm; - } -#15X156cross{ - margin: 0 !important; - padding: 0 !important; -} + + + #StickerPrints0{ width: 90mm; } - -.labelGrid15 { - width: 92mm; -} - -@media print { - body { - margin: 0 !important; - padding: 0 !important; - } -} - -.label15 { - width: 15mm; - height: 15mm; - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; -} - -.BarQrprint2details { - display: flex; - flex-direction: column; - align-items: center; - gap: 1mm; - font-size: 6px; - font-weight: 600; - text-align: center; - padding : 3px; - .productNameBQ, -.MRPBQ { - line-height: 1; -} -} - .Sticker1 { width: 35mm; height: 22mm; @@ -432,14 +384,6 @@ height: 149mm; // 25x25 4 Cross Dummy -.text-ellipsis { - width: 90%; - white-space: nowrap; - overflow: hidden; - text-align: center; - text-overflow: ellipsis; -} - @media print { body { margin: 0 !important; @@ -579,6 +523,7 @@ height: 149mm; height: auto; object-fit: contain; } + .product-id2 { margin: 0; padding: 0; @@ -657,6 +602,205 @@ height: 149mm; } +// 22x35 3cross Dummy +#StickerPrints1 { + width: 105mm; + margin: 0; + padding: 0; +} + +.label-wrapper-22x35 { + width: 35mm; + height: 22mm; + + box-sizing: border-box; + padding: 1mm; + + display: flex; + align-items: center; + justify-content: center; + gap : 0; + background: #fff; +} + +.label-wrapper-22x35 p { + margin: 0; + padding: 0; + font-size: 10px; + font-weight: 600; + line-height: 1.1; +} + +.label-wrapper-22x35 p:last-child { + margin-top: 2px; + font-size: 8px; + font-weight: 600; +} + +.label-wrapper-22x35 img { + width: 14mm; + height: 14mm; + object-fit: contain; +} + +// 25x50 2 Cross + +#25X502cross { + margin: 0 !important; + padding: 0 !important; + width: 100mm; +} + +.grid25x50_2cross { + display: grid; + grid-template-columns: repeat(2, 50mm); + width: 100mm; + column-gap: 0; + padding: 0; +} + +.label25x50-wrapper { + width: 50mm; + height: 25mm; + + box-sizing: border-box; + padding: 1.5mm; + + display: flex; + align-items: center; + justify-content: center; + + background: #fff; +} + +.label25x50-name { + font-size: 10px; + line-height: 1; + white-space: nowrap; + font-weight: 600; +} + +.label25x50-mrp { + font-size: 9px; + line-height: 1; + white-space: nowrap; + font-weight: 600; +} + +.label25x50-container { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +.label25x50-container img { + width: 16mm; + height: 16mm; + object-fit: contain; +} + +// 25x50 2 Cross Dummy + +#StickerPrints3 { + width: 100mm; + margin: 0; + padding: 0; +} + +.label-25x50-content { + width: 50mm; + height: 25mm; + + box-sizing: border-box; + padding: 1.5mm; + + display: flex; + align-items: center; + justify-content: space-between; + + background: #fff; +} + +.label-25x50-content > div { + width: 60%; + display: flex; + flex-direction: column; + justify-content: center; + gap: 1mm; + font-weight: 600; +} + +.label-25x50-content p { + margin: 0; + padding: 0; + font-size: 10px; + line-height: 1; +} + +.label-25x50-content p:last-child { + font-size: 9px; + white-space: nowrap; +} + +.label-25x50-content img { + width: 20mm; /* QR SAFE SIZE */ + height: 20mm; + object-fit: contain; +} + +// 15x15 6 Cross + +#label-15X156cross { + width: 92mm; + margin: 0 !important; + padding: 0 !important; +} + +.label-15x15-container { + display: grid; + grid-template-columns: repeat(6, 15mm); + width: 100%; + column-gap: 0.5mm; + row-gap: 0; + align-items: flex-start; +} + +.label-15x15-wrapper { + width: 15mm; + height: 15mm; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + + background: #fff; +} + +.label-15x15-content { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + text-align: center; +} + +.label-15x15-name, +.label-15x15-mrp { + font-size: 6px; + white-space: nowrap; +} + +.label-15x15-wrapper img { + width: 7.5mm; + height: 7.5mm; + object-fit: contain; +} + + .text-ellipsis { width: 90%; white-space: nowrap; @@ -664,6 +808,15 @@ height: 149mm; text-align: center; text-overflow: ellipsis; } + +.text-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + line-height: 1.1; + max-height: 2.8em; +} `; export const getPageStyle = (width) => ` diff --git a/src/Pages/Product/ProductList.jsx b/src/Pages/Product/ProductList.jsx index 2370773..cced5d0 100644 --- a/src/Pages/Product/ProductList.jsx +++ b/src/Pages/Product/ProductList.jsx @@ -1951,8 +1951,8 @@ const ProductList = () => { switch (dropdownValue) { case '15X15 6cross': // COMPLETE await printDiv( - templateAvailable ? '15X156cross' : 'StickerPrints0', - style + getPageStyle(92) + templateAvailable ? 'label-15X156cross' : 'StickerPrints0', + (style + getPageStyle(92)) ); handleQRStickerPrinterModelCancel(); break; @@ -1973,7 +1973,7 @@ const ProductList = () => { case '25X50 2cross': //Need to check await printDiv( templateAvailable ? '25X502cross' : 'StickerPrints3', - style + style + getPageStyle(100) ); handleQRStickerPrinterModelCancel(); break; @@ -4036,12 +4036,12 @@ const ProductList = () => { const copyCount = generateQRCodeCopy(record?.QRCode); return Array?.from({ length: copyCount })?.map((_, copyIndex) => (
8 ? 'text-ellipsis' : ''}`} + className={`${nickName ? '' : (proName + ' (' + size + ')')?.length > 8 ? 'text-clamp-2' : ''}`} > {record.ProdName} ({record.Size} {record.UomName}) @@ -4055,15 +4055,14 @@ const ProductList = () => { templateOptions?.codeType ) || base64Image } - style={{ width: '52px', height: '52px' }} />
8 ? 'text-ellipsis' : ''}`} > @@ -4073,7 +4072,6 @@ const ProductList = () => {
12 ? 'text-ellipsis' : ''}`} + className={`${nickName ? '' : ((record?.NickName || record?.ProdName) + ' (' + record?.Size + ')')?.length > 12 ? 'text-clamp-2' : ''}`} > {record?.NickName || record?.ProdName} ({record?.Size} {record?.UomName}) @@ -4223,10 +4221,10 @@ const ProductList = () => { )) }) : Array.from({ length: copies })?.map((_, index) => ( -
12 ? 'text-ellipsis' : ''}`} + className={`${nickName ? '' : (proName + ' (' + size + ')')?.length > 12 ? 'text-clamp-2' : ''}`} > {proName} ({size})
@@ -4234,7 +4232,6 @@ const ProductList = () => {-
+ } + } + + , + } ]; const Proddetailcolumns = [ { @@ -856,6 +897,52 @@ const StockList = () => {{`${value} (${record?.Size} ${record?.UOMName})`}
), }, { - title: 'Variant Name', - dataIndex: 'VariantName', - key: 'VariantName', + title: "Variant Name", + dataIndex: "VariantName", + key: "VariantName", width: 180, }, { - title: 'Batch No', - dataIndex: 'BatchRef', - key: 'BatchRef', + title: "Batch No", + dataIndex: "BatchRef", + key: "BatchRef", width: 180, }, - { - title: 'Stock', - dataIndex: 'Stock', - key: 'Stock', - width: 80, - }, - { - title: 'Stock Date', - dataIndex: 'StockDate', - key: 'StockDate', - width: 80, - }, - { - title: 'Old MRP', - dataIndex: 'OldMRP', - key: 'OldMRP', - width: 100, - }, - { - title: 'Old SP', - dataIndex: 'OldSP', - key: 'OldSP', - width: 100, - }, - { - title: 'Old Wholesale Price', - dataIndex: 'OldWholeSalePrice', - key: 'OldWholeSalePrice', - width: 140, - }, + ...(hasFieldExists("Stock") + ? [ + { + title: "Stock", + dataIndex: "Stock", + key: "Stock", + width: 80, + }, + ] + : []), + ...(hasFieldExists("Stock Date") + ? [ + { + title: "Stock Date", + dataIndex: "StockDate", + key: "StockDate", + width: 80, + }, + ] + : []), + ...(hasFieldExists("Old MRP") + ? [ + { + title: "Old MRP", + dataIndex: "OldMRP", + key: "OldMRP", + width: 100, + }, + ] + : []), + ...(hasFieldExists("Old SP") + ? [ + { + title: "Old SP", + dataIndex: "OldSP", + key: "OldSP", + width: 100, + }, + ] + : []), + ...(hasFieldExists("Old Wholesale Price") + ? [ + { + title: "Old Wholesale Price", + dataIndex: "OldWholeSalePrice", + key: "OldWholeSalePrice", + width: 140, + }, + ] + : []), // ✅ EDITABLE { - title: 'New MRP', - dataIndex: 'NewMRP', - key: 'NewMRP', + title: "New MRP", + dataIndex: "NewMRP", + key: "NewMRP", width: 120, render: (_, record, index) => ({text ? text : 'Enter MRP'}
, + render: (text, record) =>{text ? text : "Enter MRP"}
, width: 100, }, { - title: 'New SP', - dataIndex: 'CurrentAmt', - key: 'CurrentAmt', - align: 'right', + title: "New SP", + dataIndex: "CurrentAmt", + key: "CurrentAmt", + align: "right", editable: true, - render: (text, record) =>{text ? text : 'Enter Price'}
, + render: (text, record) =>{text ? text : "Enter Price"}
, width: 100, }, { - title: 'Action', - dataIndex: 'SellPrice', - key: 'SellPrice', - align: 'center', - width: '100px', + title: "Action", + dataIndex: "SellPrice", + key: "SellPrice", + align: "center", + width: "100px", render: (_, record, index) => ({text ? text : 'Enter MRP'}
, + render: (text, record) =>{text ? text : "Enter MRP"}
, width: 100, }, { - title: 'New SP', - dataIndex: 'CurrentAmt', - key: 'CurrentAmt', - align: 'center', - with: '4rem', + title: "New SP", + dataIndex: "CurrentAmt", + key: "CurrentAmt", + align: "center", + with: "4rem", editable: true, - render: (text, record) =>{text ? text : 'Enter Price'}
, + render: (text, record) =>{text ? text : "Enter Price"}
, width: 100, }, + ...(hasField("New Wholesale Price") + ? [ + { + title: "New Wholesale Price", + dataIndex: "CurrentWhAmt", + key: "CurrentWhAmt", + align: "center", + with: "4rem", + editable: true, + render: (text, record) => ( +{text ? text : "Enter Wholesale Price"}
+ ), + width: 120, + }, + ] + : []), ]; const HandleStockNames = (e, option) => { @@ -1023,7 +1200,7 @@ const StockPriceUpdate = () => { // Check if any of the new products already exist in StockDetails setStockDetails((prevStockDetails) => { const existingInwardDtlIds = new Set( - prevStockDetails?.map((item) => item.InwardDtlId) + prevStockDetails?.map((item) => item.InwardDtlId), ); const uniqueNewStockDetails = newStockDetails @@ -1078,17 +1255,18 @@ const StockPriceUpdate = () => { // }; const HandlePutData = async () => { - if (RadioSelection == 'Bulk') { + if (RadioSelection == "Bulk") { const filteredCurrentAmtData = BulkProductData?.filter( (item) => - item.CurrentAmt !== undefined && - item.CurrentAmt !== null && - item.CurrentMRP !== '' && - item.CurrentAmt !== '' && - item.CurrentMRP !== undefined && - item.CurrentMRP !== null && - item.CurrentMRP !== '' && - item.CurrentAmt !== '' + (item.CurrentAmt !== undefined && + item.CurrentAmt !== null && + item.CurrentAmt !== "" && + item.CurrentMRP !== undefined && + item.CurrentMRP !== null && + item.CurrentMRP !== "") || + (item.CurrentWhAmt !== undefined && + item.CurrentWhAmt !== null && + item.CurrentWhAmt !== ""), ); const hasInvalidData = BulkProductData.every((item) => { const isAbsent = item.CurrentAmt == null && item.CurrentMRP == null; @@ -1102,45 +1280,47 @@ const StockPriceUpdate = () => { let Postdata = { CompId: CompId, BranchId: BranchId, + Type: "Variant", ProductDetails: filteredCurrentAmtData?.map((item) => ({ ProdId: item?.ProdId, - MRP: item?.CurrentMRP, - SellPrice: item?.CurrentAmt, - AdjComment: 'string', + NewMRP: item?.CurrentMRP, + NewSellPrice: item?.CurrentAmt, + AdjComment: "string", InwardDtlId: item?.InwardDtlId, + NewWholeSalePrice: item.CurrentWhAmt, })), }; - let response = await dispatch(PutStockPrice(Postdata)).unwrap(); + let response = await dispatch(bulkPriceUpdate(Postdata)).unwrap(); if (response?.data?.statusCode == 1) { setProductName(); - setMessageType('success'); + setMessageType("success"); setMessageData(response?.data?.response); fetchData(); - setBulksearchedText(''); + setBulksearchedText(""); setStockDetails([]); setBulkProductData([]); } else { - setMessageType('error'); + setMessageType("error"); setMessageData(response?.data?.response); } } else { - setMessageType('error'); - setMessageData('Please give all details'); + setMessageType("error"); + setMessageData("Please give all details"); } } else { const filteredStockDetails = StockDetails?.filter( (item) => item?.CurrentMRP && - item?.CurrentMRP !== '' && + item?.CurrentMRP !== "" && item?.CurrentAmt && - item?.CurrentAmt !== '' + item?.CurrentAmt !== "", ); if (filteredStockDetails?.length === 0) { - setMessageType('error'); - setMessageData('Please enter price details for at least one product'); + setMessageType("error"); + setMessageData("Please enter price details for at least one product"); return; } @@ -1151,7 +1331,7 @@ const StockPriceUpdate = () => { ProdId: item?.ProdId, MRP: item?.CurrentMRP, SellPrice: item?.CurrentAmt, - AdjComment: 'string', + AdjComment: "string", InwardDtlId: item?.InwardDtlId, })), UpdatedBy: 1, @@ -1163,11 +1343,11 @@ const StockPriceUpdate = () => { setStockNames(res?.data?.data); if (response?.data?.statusCode == 1) { setProductName(); - setMessageType('success'); + setMessageType("success"); setMessageData(response?.data?.response); fetchData(); } else { - setMessageType('error'); + setMessageType("error"); setMessageData(response?.data?.response); } setStockDetails([]); @@ -1276,108 +1456,140 @@ const StockPriceUpdate = () => { setFieldSetup(true); }; + const handleExcelFieldSetup = () => { + setExcelFieldSetup(true); + }; + const showPriceChangeModal = () => { setPriceChangeModalOpen(true); }; - const handleExport = async (isStockVariantBased = 'Yes') => { + const handleExport = async (isStockVariantBased = "Yes") => { setExportLoading(true); setPriceChangeModalOpen(false); const uniqueBulkProductData = - isStockVariantBased === 'Yes' + isStockVariantBased === "Yes" ? BulkProductData || [] : (BulkProductData || [])?.filter( - (item, index, self) => - index === self.findIndex((p) => p.ProdId === item.ProdId) - ); + (item, index, self) => + index === self.findIndex((p) => p.ProdId === item.ProdId), + ); if (!uniqueBulkProductData?.length) { - setMessageType('error'); - setMessageData('No data available to export'); + setMessageType("error"); + setMessageData("No data available to export"); setExportLoading(false); return; } const workbook = new ExcelJS.Workbook(); - const worksheet = workbook.addWorksheet('Products'); + const worksheet = workbook.addWorksheet("Products"); /* ---------------- COLUMN DEFINITIONS ---------------- */ const columns = [ - { header: 'Product Name', key: 'ProdName', width: 20 }, - ...(isStockVariantBased === 'Yes' - ? [{ header: 'Variant Name', key: 'ProdVariantName', width: 20 }] + { header: "Product Name", key: "ProdName", width: 20 }, + ...(isStockVariantBased === "Yes" + ? [{ header: "Variant Name", key: "ProdVariantName", width: 20 }] : []), - ...(isStockVariantBased === 'Yes' - ? [{ header: 'Batch No', key: 'BatchRef', width: 20 }] + ...(isStockVariantBased === "Yes" + ? [{ header: "Batch No", key: "BatchRef", width: 20 }] : []), - { header: 'Stock Date', key: 'StockDate', width: 15 }, - { header: 'Exp Date', key: 'ExpDate', width: 15 }, - { header: 'Stock', key: 'Stock', width: 10 }, - { header: 'Old MRP', key: 'OldMRP', width: 10 }, - { header: 'Old SP', key: 'OldSP', width: 10 }, - { header: 'Old Wholesale Price', key: 'WhSalePrice', width: 14 }, - { header: 'Size', key: 'Size', width: 10 }, - { header: 'Stock Maintainence', key: 'StockAvailable', width: 18 }, - { header: 'UOMName', key: 'UOMName', width: 15 }, - { header: 'New MRP', key: 'NewMRP', width: 12 }, - { header: 'New SP', key: 'NewSP', width: 12 }, - { header: 'New Wholesale Price', key: 'NewWhSalePrice', width: 14 }, - { header: 'ProdId', key: 'ProdId', width: 1 }, + ...(hasExcelField("Stock Date") + ? [{ header: "Stock Date", key: "StockDate", width: 15 }] + : []), + ...(hasExcelField("Expiry Date") + ? [{ header: "Exp Date", key: "ExpDate", width: 15 }] + : []), + ...(hasExcelField("Stock") + ? [{ header: "Stock", key: "Stock", width: 10 }] + : []), + ...(hasExcelField("Old MRP") + ? [{ header: "Old MRP", key: "OldMRP", width: 10 }] + : []), + ...(hasExcelField("Old SP") + ? [{ header: "Old SP", key: "OldSP", width: 10 }] + : []), + ...(hasExcelField("Old Wholesale Price") + ? [{ header: "Old Wholesale Price", key: "WhSalePrice", width: 14 }] + : []), + ...(hasExcelField("Size") + ? [{ header: "Size", key: "Size", width: 10 }] + : []), + ...(hasExcelField("Stock Maintainence") + ? [{ header: "Stock Maintainence", key: "StockAvailable", width: 18 }] + : []), + ...(hasExcelField("UOM Name") + ? [{ header: "UOMName", key: "UOMName", width: 15 }] + : []), + // ...(hasExcelField("New MRP & New SP") + // ? [ + { header: "New MRP", key: "NewMRP", width: 12 }, + { header: "New SP", key: "NewSP", width: 12 }, + // ] + // : []), - ...(isStockVariantBased === 'Yes' - ? [{ header: 'InwardDtlId', key: 'InwardDtlId', width: 1 }] + ...(hasExcelField("New Wholesale Price") + ? [{ header: "New Wholesale Price", key: "NewWhSalePrice", width: 14 }] : []), - { header: 'key', key: 'key', width: 1 }, - { header: 'downloadType', key: 'downloadType', width: 1 }, + // --- Hidden system columns (always included) --- + { header: "ProdId", key: "ProdId", width: 1 }, + + ...(isStockVariantBased === "Yes" + ? [{ header: "InwardDtlId", key: "InwardDtlId", width: 1 }] + : []), + + { header: "key", key: "key", width: 1 }, + { header: "downloadType", key: "downloadType", width: 1 }, ]; worksheet.columns = columns; - worksheet.views = [{ state: 'frozen', xSplit: 1, ySplit: 1 }]; + worksheet.views = [{ state: "frozen", xSplit: 1, ySplit: 1 }]; const headerRow = worksheet.getRow(1); - const newMRPCol = headerRow.values.indexOf('New MRP'); - const newSPCol = headerRow.values.indexOf('New SP'); + const newMRPCol = headerRow.values.indexOf("New MRP"); + const newSPCol = headerRow.values.indexOf("New SP"); + const hasNewMRPAndSP = newMRPCol > 0 && newSPCol > 0; /* ---------------- HEADER STYLE ---------------- */ worksheet.getRow(1).eachCell((cell) => { const header = cell.value; const isHiddenCol = - header === 'key' || - header === 'ProdId' || - header === 'InwardDtlId' || - header === 'downloadType'; + header === "key" || + header === "ProdId" || + header === "InwardDtlId" || + header === "downloadType"; cell.font = { bold: true, size: isHiddenCol ? 1 : 11, - color: { argb: isHiddenCol ? 'FFFFFFFF' : 'FF000000' }, + color: { argb: isHiddenCol ? "FFFFFFFF" : "FF000000" }, }; cell.alignment = { - horizontal: 'center', - vertical: 'middle', + horizontal: "center", + vertical: "middle", wrapText: true, // ✅ prevents overflow in header }; cell.fill = { - type: 'pattern', - pattern: 'solid', + type: "pattern", + pattern: "solid", fgColor: { - argb: isHiddenCol ? 'FFFFFFFF' : 'FF52C41A', + argb: isHiddenCol ? "FFFFFFFF" : "FF52C41A", }, }; cell.border = isHiddenCol ? undefined : { - right: { style: 'thin', color: { argb: 'FF000000' } }, - bottom: { style: 'thin', color: { argb: 'FF000000' } }, - }; + right: { style: "thin", color: { argb: "FF000000" } }, + bottom: { style: "thin", color: { argb: "FF000000" } }, + }; }); /* ---------------- ADD DATA ---------------- */ @@ -1387,7 +1599,7 @@ const StockPriceUpdate = () => { ProdVariantName: product?.ProdVariantName, BatchRef: product?.BatchRef, StockDate: product?.InwardDate, - ExpDate: product?.ExpDate || '-', + ExpDate: product?.ExpDate || "-", Stock: product?.BalanceQty, OldMRP: product?.MRP, OldSP: product?.SellPrice, @@ -1396,35 +1608,37 @@ const StockPriceUpdate = () => { StockAvailable: product?.StockAvailable, UOMName: product?.UOMName, key: product?.key, - downloadType: isStockVariantBased === 'Yes' ? 'Variant' : 'Product', - NewMRP: '', - NewSP: '', - NewWhSalePrice: '', + downloadType: isStockVariantBased === "Yes" ? "Variant" : "Product", + NewMRP: "", + NewSP: "", + NewWhSalePrice: "", ProdId: product?.ProdId, InwardDtlId: - isStockVariantBased === 'Yes' ? product?.InwardDtlId : undefined, + isStockVariantBased === "Yes" ? product?.InwardDtlId : undefined, }); }); // ---------------- VALIDATION: New SP <= New MRP ---------------- - worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => { - if (rowNumber === 1) return; // skip header + if (hasNewMRPAndSP) { + worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => { + if (rowNumber === 1) return; // skip header - const newMRPCell = row.getCell(newMRPCol); - const newSPCell = row.getCell(newSPCol); + const newMRPCell = row.getCell(newMRPCol); + const newSPCell = row.getCell(newSPCol); - newSPCell.dataValidation = { - type: 'custom', - allowBlank: true, - formulae: [ - `IFERROR(VALUE(${newSPCell.address}),0) <= IFERROR(VALUE(${newMRPCell.address}),0)`, - ], - showErrorMessage: true, - errorStyle: 'stop', - errorTitle: 'Invalid Selling Price', - error: 'New SP cannot be greater than New MRP', - }; - }); + newSPCell.dataValidation = { + type: "custom", + allowBlank: true, + formulae: [ + `IFERROR(VALUE(${newSPCell.address}),0) <= IFERROR(VALUE(${newMRPCell.address}),0)`, + ], + showErrorMessage: true, + errorStyle: "stop", + errorTitle: "Invalid Selling Price", + error: "New SP cannot be greater than New MRP", + }; + }); + } /* ---------------- UNLOCK EVERYTHING ---------------- */ worksheet.eachRow({ includeEmpty: true }, (row) => { @@ -1448,38 +1662,38 @@ const StockPriceUpdate = () => { const header = worksheet.getRow(1).getCell(colNumber).value; const isHiddenCol = - header === 'key' || - header === 'ProdId' || - header === 'InwardDtlId' || - header === 'downloadType'; + header === "key" || + header === "ProdId" || + header === "InwardDtlId" || + header === "downloadType"; const isEditable = - header === 'New MRP' || - header === 'New SP' || - header === 'New Wholesale Price'; + header === "New MRP" || + header === "New SP" || + header === "New Wholesale Price"; cell.protection = { locked: !isEditable }; cell.alignment = { - vertical: 'middle', + vertical: "middle", wrapText: true, }; if (isHiddenCol) { cell.font = { size: 1, - color: { argb: 'FFFFFFFF' }, + color: { argb: "FFFFFFFF" }, }; cell.fill = { - type: 'pattern', - pattern: 'solid', - fgColor: { argb: 'FFFFFFFF' }, + type: "pattern", + pattern: "solid", + fgColor: { argb: "FFFFFFFF" }, }; } }); }); /* ---------------- PROTECT SHEET ---------------- */ - await worksheet.protect('', { + await worksheet.protect("", { selectLockedCells: false, selectUnlockedCells: true, formatCells: false, @@ -1491,12 +1705,12 @@ const StockPriceUpdate = () => { /* ---------------- DOWNLOAD ---------------- */ const buffer = await workbook.xlsx.writeBuffer(); const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", }); - const link = document.createElement('a'); + const link = document.createElement("a"); link.href = URL.createObjectURL(blob); - link.download = 'PriceChange_Data.xlsx'; + link.download = "PriceChange_Data.xlsx"; link.click(); setExportLoading(false); @@ -1507,20 +1721,23 @@ const StockPriceUpdate = () => { }; const handleFileUpload = (e) => { + setFileLoading(true); const file = e.target.files[0]; if (!file) { dispatch(emptyExcelData()); + setFileLoading(false); return; } const isAllowed = allowedExcelTypes?.includes(file.type); if (!isAllowed) { Modal.error({ - title: 'Invalid File Type', - content: 'Only Excel files (.xls, .xlsx) are allowed.', + title: "Invalid File Type", + content: "Only Excel files (.xls, .xlsx) are allowed.", }); handleCancelData(); + setFileLoading(false); return; } @@ -1531,14 +1748,16 @@ const StockPriceUpdate = () => { const extractedData = extractPriceChangeDataFromExcel(arrayBuffer); - console.log(extractedData, 'extractedData'); + console.log(extractedData, "extractedData"); if ((extractedData || [])?.length === 0) { - setMessageData('No Data Found in Uploaded Sheet'); - setMessageType('error'); + setMessageData("No Data Found in Uploaded Sheet"); + setMessageType("error"); handleCancelData(); + setFileLoading(false); return; } setUploadedData(extractedData); + setFileLoading(false); // setFormValuesFromExtractedData(extractedData); }; @@ -1571,40 +1790,41 @@ const StockPriceUpdate = () => { }; const extractPriceChangeDataFromExcel = (arrayBuffer) => { - const workbook = read(arrayBuffer, { type: 'array' }); + const workbook = read(arrayBuffer, { type: "array" }); const worksheet = workbook.Sheets[workbook.SheetNames[0]]; const rows = utils.sheet_to_json(worksheet, { header: 1, raw: false, - defval: '', + defval: "", }); if (!rows.length) return []; const header = rows[0]; + setHeaders(header); const dataRows = rows.slice(1); // Helper to safely get column value const getVal = (row, colName) => { const idx = header.indexOf(colName); - return idx !== -1 ? row[idx] : ''; + return idx !== -1 ? row[idx] : ""; }; const result = dataRows .map((row) => { - const prodId = getVal(row, 'ProdId')?.toString().trim(); + const prodId = getVal(row, "ProdId")?.toString().trim(); if (!prodId) return null; const newMRP = - getVal(row, 'New MRP') !== '' ? Number(getVal(row, 'New MRP')) : null; + getVal(row, "New MRP") !== "" ? Number(getVal(row, "New MRP")) : null; const newSP = - getVal(row, 'New SP') !== '' ? Number(getVal(row, 'New SP')) : null; + getVal(row, "New SP") !== "" ? Number(getVal(row, "New SP")) : null; const newWholesale = - getVal(row, 'New Wholesale Price') !== '' - ? Number(getVal(row, 'New Wholesale Price')) + getVal(row, "New Wholesale Price") !== "" + ? Number(getVal(row, "New Wholesale Price")) : null; // ❌ Must have at least one change @@ -1616,37 +1836,37 @@ const StockPriceUpdate = () => { // 🔹 Product identity localId: uuidv4(), ProdId: prodId, - InwardDtlId: getVal(row, 'InwardDtlId') - ? getVal(row, 'InwardDtlId').toString() + InwardDtlId: getVal(row, "InwardDtlId") + ? getVal(row, "InwardDtlId").toString() : null, // 🔹 Product info - VariantName: getVal(row, 'Variant Name') || null, - BatchRef: getVal(row, 'Batch No') || null, - ProductName: getVal(row, 'Product Name') || null, - Size: getVal(row, 'Size') || null, - UOMName: getVal(row, 'UOMName') || null, - StockMaintainence: getVal(row, 'Stock Maintainence') || null, + VariantName: getVal(row, "Variant Name") || null, + BatchRef: getVal(row, "Batch No") || null, + ProductName: getVal(row, "Product Name") || null, + Size: getVal(row, "Size") || null, + UOMName: getVal(row, "UOMName") || null, + StockMaintainence: getVal(row, "Stock Maintainence") || null, // 🔹 Stock / dates - StockDate: getVal(row, 'Stock Date') || null, - ExpDate: getVal(row, 'Exp Date') || null, - downloadType: getVal(row, 'downloadType') || null, + StockDate: getVal(row, "Stock Date") || null, + ExpDate: getVal(row, "Exp Date") || null, + downloadType: getVal(row, "downloadType") || null, Stock: - getVal(row, 'Stock') !== '' ? Number(getVal(row, 'Stock')) : null, + getVal(row, "Stock") !== "" ? Number(getVal(row, "Stock")) : null, // 🔹 Old prices OldMRP: - getVal(row, 'Old MRP') !== '' - ? Number(getVal(row, 'Old MRP')) + getVal(row, "Old MRP") !== "" + ? Number(getVal(row, "Old MRP")) : null, OldSP: - getVal(row, 'Old SP') !== '' ? Number(getVal(row, 'Old SP')) : null, + getVal(row, "Old SP") !== "" ? Number(getVal(row, "Old SP")) : null, OldWholeSalePrice: - getVal(row, 'Old Wholesale Price') !== '' - ? Number(getVal(row, 'Old Wholesale Price')) + getVal(row, "Old Wholesale Price") !== "" + ? Number(getVal(row, "Old Wholesale Price")) : null, // 🔹 New prices (normalized) @@ -1663,13 +1883,14 @@ const StockPriceUpdate = () => { const handleCancelData = () => { dispatch(emptyExcelData()); if (fileInputRef.current) { - fileInputRef.current.value = ''; + fileInputRef.current.value = ""; } setUploadedData([]); }; const handleSubmit = async () => { try { + setLoading(true); const formValues = excelDataRef.current?.getFieldsValue(); // Validate all records @@ -1680,26 +1901,26 @@ const StockPriceUpdate = () => { // If MRP is present, SP must also be present if (newMRP && !newSP) { - setMessageType('error'); + setMessageType("error"); setMessageData( - 'If New MRP is provided, New SP must also be provided' + "If New MRP is provided, New SP must also be provided", ); return; } // If SP is present, MRP must also be present if (newSP && !newMRP) { - setMessageType('error'); + setMessageType("error"); setMessageData( - 'If New SP is provided, New MRP must also be provided' + "If New SP is provided, New MRP must also be provided", ); return; } // New SP cannot be greater than New MRP if (newMRP && newSP && parseFloat(newSP) > parseFloat(newMRP)) { - setMessageType('error'); - setMessageData('New SP cannot be greater than New MRP'); + setMessageType("error"); + setMessageData("New SP cannot be greater than New MRP"); return; } } @@ -1722,7 +1943,7 @@ const StockPriceUpdate = () => { NewSellPrice: data?.NewSellPrice, NewMRP: data?.NewMRP, NewWholeSalePrice: data?.NewWholeSalePrice, - AdjComment: 'string', + AdjComment: "string", })); const putData = { @@ -1737,26 +1958,86 @@ const StockPriceUpdate = () => { const res = await dispatch(bulkPriceUpdate(putData))?.unwrap(); if (res?.data?.statusCode === 1) { - setMessageData(res?.data?.response || 'Price Updated Successfully'); - setMessageType('success'); + setMessageData(res?.data?.response || "Price Updated Successfully"); + setMessageType("success"); setUploadedData([]); handleCancelData(); setExcelModalOpen(false); await fetchData(); } else { setMessageData(res?.data?.response); - setMessageType('error'); + setMessageType("error"); } // If validation passes, proceed with submission - console.log('Form validation passed', updatedData); + console.log("Form validation passed", updatedData); } catch (error) { - setMessageType('error'); - setMessageData('Please check all fields and try again'); + setMessageType("error"); + setMessageData("Please check all fields and try again"); + } finally { + setLoading(false); + } + }; + + const handleFieldSetupSubmit = async () => { + const postData = { + AppId: AppId, + CompId: CompId, + BranchId: BranchId, + Type: "GB", + FormType: fieldSetup ? "Price Change" : "Price Change Sheet", + TypeId: fieldSetup ? categoryId : excelCategoryId, + ConfigDtl: (fieldSetup ? selectedFields : selectedExcelFields)?.map( + (field) => ({ + ConfigId: field, + Access: "Y", + }), + ), + CreatedBy: UserId, + }; + + const response = await dispatch(postFieldSetup(postData))?.unwrap(); + + if (response?.data?.statusCode === 1) { + setMessageType("success"); + setMessageData(response?.data?.response); + if (fieldSetup) { + await getFieldSetup(); + } else { + await getExcelFieldSetup(); + } + } else { + setMessageType("error"); + setMessageData("Failed to set up fields"); + } + }; + + const handleFieldSelect = (value) => { + if (fieldSetup) { + setSelectedFields((prev) => { + if (prev.includes(value)) { + return prev; + } + return [value, ...prev]; + }); + } else { + setSelectedExcelFields((prev) => { + if (prev.includes(value)) { + return prev; + } + return [value, ...prev]; + }); + } + }; + + const handleFieldRemove = (id) => { + if (fieldSetup) { + setSelectedFields((prev) => prev.filter((field) => field !== id)); + } else { + setSelectedExcelFields((prev) => prev.filter((field) => field !== id)); } }; - return (