Merge pull request 'combo-table-qty-price-edit' (#129) from combo-table-qty-price-edit into main

Reviewed-on: Pozomind/pozo-retail-app#129
This commit is contained in:
karthikalakshmi 2026-02-11 15:55:12 +05:30
commit 509b2aae37
5 changed files with 111 additions and 37 deletions

View File

@ -82,16 +82,16 @@ export const ReprintDetails = createAsyncThunk(
const { AppId, CompId, BranchId, OrderFromDate, OrderToDate, OrderId } = data || {};
if (OrderId && !OrderFromDate && !OrderToDate) {
return await axiosRetailInstanceData.get(
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&OrderId=${OrderId}&pageNumber=${data.PageNumber}`
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&OrderId=${OrderId}&pageNumber=${data.PageNumber}&Type=${data.Type}`
);
}
if (OrderFromDate && OrderToDate) {
return await axiosRetailInstanceData.get(
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&orderFromDate=${OrderFromDate}&orderToDate=${OrderToDate} &pageNumber=${data.PageNumber}`
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&orderFromDate=${OrderFromDate}&orderToDate=${OrderToDate} &pageNumber=${data.PageNumber}&Type=${data.Type}`
);
} else {
return await axiosRetailInstanceData.get(
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&pageNumber=${data.PageNumber}`
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&pageNumber=${data.PageNumber}&Type=${data.Type}`
);
}
}

View File

@ -87,6 +87,7 @@ import { v4 as uuidv4 } from 'uuid';
import { changeOrderOfferDetail } from '../../../../../Features/Offer/Offer.js';
import { ChangeFullFreeProductList, changeFullOfferAppliedProducts, changeLoyaltyConsumedQuantities } from '../../../../../Features/Offer/Offernew/BookingOffernew.js';
import { ChangeTotalAmount } from '../../../../../Features/ExteraCharges/ExtraCharges.js';
import { Radio } from 'antd';
const RetailApiurl = import.meta.env.ENV_API_URL;
@ -127,12 +128,17 @@ function BSReprint({ setOpenModel = () => { } }) {
const SettingDataSelector = useSelector(PreferenceData);
const salesBillEdit = useSelector(GlobalSalesBillEdit);
const custDisable = useSelector(GlobalSelectedCustDisable);
console.log(SettingDataSelector, 'SettingDataSelector');
console.log(SettingDataSelector, 'SettingDataSelectoraa');
const MobileA4Print = SettingDataSelector?.[0]?.SettingDtlDetails?.find(
(setting) =>
setting?.SettingIdName?.toLowerCase() === 'mobilea4' &&
setting?.SettingValue === 'Y'
);
const preferenceEstimate =
SettingDataSelector?.[0]?.['SettingDtlDetails']?.find(
(item) => item.SettingIdName === 'Estimation'
)?.SettingValue === 'Y';
console.log(preferenceEstimate, 'preferenceEstimate');
const editBill = SettingDataSelector?.[0]?.SettingDtlDetails?.find(
(setting) =>
setting?.SettingIdName?.toLowerCase() === 'editbill' &&
@ -160,10 +166,10 @@ function BSReprint({ setOpenModel = () => { } }) {
const AuthToken = sessionStorage.getItem('auth');
const SessionMobileNo = getSession('MobileNo');
const [dateStrings, setDateStrings] = useState([]);
const [type, setType] = useState("Sales");
// ---- 1. Fetch Function ----
const fetchData = async ({ queryKey }) => {
const [_, dates, page] = queryKey;
const [_, dates, page,type] = queryKey;
const Response = await dispatch(
ReprintDetails({
CompId,
@ -172,6 +178,7 @@ function BSReprint({ setOpenModel = () => { } }) {
OrderFromDate: dates?.[0] ?? '',
OrderToDate: dates?.[1] ?? '',
PageNumber: page,
Type:type
})
).unwrap();
if (Response?.data?.statusCode === 1) {
@ -182,7 +189,7 @@ function BSReprint({ setOpenModel = () => { } }) {
};
const { data, isLoading, error } = useQuery({
queryKey: ['reprint', dateStrings, page],
queryKey: ['reprint', dateStrings, page,type],
queryFn: fetchData,
enabled: true,
staleTime: 1000 * 60 * 5,
@ -242,6 +249,8 @@ function BSReprint({ setOpenModel = () => { } }) {
}
};
commonMasterApiCall();
}, []);
useEffect(() => {
DefaultReprintReason();
}, []);
useEffect(() => {
@ -254,7 +263,9 @@ function BSReprint({ setOpenModel = () => { } }) {
dispatch(getPrinterMappingDetails(data)).unwrap();
const Data1 = { AppId, CompId, BranchId };
dispatch(getPrintSelectionComponentData(Data1)).unwrap();
}, []);
const handleDateChange = (dates, dateStrings) => {
// setDateRange(dateStrings);
if (dateStrings[0] && dateStrings[1]) {
@ -1394,6 +1405,15 @@ function BSReprint({ setOpenModel = () => { } }) {
}
}
const typeOptions = [
{ label: "Sales", value: "Sales" },
{ label: "Estimate", value: "Est" },
];
const typeChange = (e) => {
setType(e.target.value);
};
return (
<>
<div>
@ -1432,20 +1452,16 @@ function BSReprint({ setOpenModel = () => { } }) {
/>
<div style={{ width: '100%' }}>
<div className="bsreprintmodaltable-flex">
{preferenceEstimate && <div>
<Radio.Group
options={typeOptions}
onChange={typeChange}
value={type}
optionType="button"
buttonStyle="solid" // optional
/>
</div>}
<div>
{selectedRows.length > 0 && (
<div className="action-icons-reprint">
<FaDownload
onClick={() => mutiplePrint('download')}
className="icon-download"
/>
<MdEmail onClick={() => handleEmail()} className="icon-email" />
<FaWhatsapp
onClick={() => mutiplePrint('whatsapp')}
className="icon-whatsapp"
/>
</div>
)}
<RangePicker
placeholder={['Start Date', 'End Date']}
format="YYYY-MM-DD"
@ -1473,6 +1489,22 @@ function BSReprint({ setOpenModel = () => { } }) {
Reprintformdata();
}}
/>
<div>
{selectedRows.length > 0 && (
<div className="action-icons-reprint">
<FaDownload
onClick={() => mutiplePrint('download')}
className="icon-download"
/>
<MdEmail onClick={() => handleEmail()} className="icon-email" />
<FaWhatsapp
onClick={() => mutiplePrint('whatsapp')}
className="icon-whatsapp"
/>
</div>
)}
</div>
</div>
{/* <div className="Re-Print-table"> */}
<div className="bsreprintmodaltable">

View File

@ -1,5 +1,7 @@
import { Tooltip } from 'antd';
import { Tooltip, message } from 'antd';
import { useState, useEffect, useCallback } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { Messages } from '../../Components/Notifications/Messages';
const AddAllProductsButton = ({
productData = [],
@ -13,6 +15,9 @@ const AddAllProductsButton = ({
}) => {
// This function just returns a prepared product object, no state changes
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const ProductDropDownChange = async (
VariantName,
ProdId,
@ -74,24 +79,34 @@ const AddAllProductsButton = ({
localId: uuidv4(),
};
};
const handleAddAll = async () => {
const existingProdIds = new Set(
purchaseData?.map((p) => `${p.ProdId}_${p.ProdVariantName}`)
);
const productsToAdd = productData?.filter(
(p) => !existingProdIds?.has(`${p.ProdId}_${p.ProdVariantName}`)
);
if (productsToAdd.length === 0) {
setMessageData('All products are already added');
setMessageType('warning');
return;
}
try {
setIsLoading(true);
setLoadingText('Adding products...');
// allow UI paint
await new Promise((r) => requestAnimationFrame(r));
const allValidProducts = [];
const allFormValues = {};
for (let i = 0; i < productData.length; i += batchSize) {
const batch = productData.slice(i, i + batchSize);
for (let i = 0; i < productsToAdd.length; i += batchSize) {
const batch = productsToAdd.slice(i, i + batchSize);
setLoadingText(
`Processing ${Math.min(i + batchSize, productData.length)} / ${
productData.length
`Processing ${Math.min(i + batchSize, productsToAdd.length)} / ${productsToAdd.length
}`
);
@ -101,8 +116,7 @@ const AddAllProductsButton = ({
product.ProdVariantName,
product.ProdId,
{
label: `${product.ProdName} (${product.Size} ${product.UomName})${
product.BrandName ? ` - ${product.BrandName}` : ''
label: `${product.ProdName} (${product.Size} ${product.UomName})${product.BrandName ? ` - ${product.BrandName}` : ''
}`,
},
productData
@ -128,19 +142,25 @@ const AddAllProductsButton = ({
await new Promise((r) => setTimeout(r, 0));
}
// ONE state update
setPurchaseData((prev) => [...allValidProducts, ...prev]);
// ONE form update
form?.setFieldsValue(allFormValues);
} finally {
setIsLoading(false);
setLoadingText('');
}
};
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
return (
<Tooltip title="Add All Products" placement="top">
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<button type="button" className="addallProductTBN" onClick={handleAddAll}>
Add All
</button>

View File

@ -13,6 +13,7 @@ import {
getSupplaierIdBasedProducts
} from '../../Features/SupplierProductMapping/SupplierProductMapping.js';
import { getsupplierBasedOnCmpId, getsupplierBasedOnCmpIdBrId } from '../../Features/SupplierMaster/SupplierMaster.js';
import "../../Pages/SupplierProductMapping/SupplierProductMapping.scss"
const SupplierProductMappingForm = ({
isModalOpen = false,
@ -36,6 +37,8 @@ const SupplierProductMappingForm = ({
const [modalSelectedProduct, setModalSelectedProduct] = useState(null);
const [tabledata, setTabledata] = useState([]);
const [filteredTableData, setFilteredTableData] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(8);
const details = {
name: "tamil",
address: {
@ -199,7 +202,9 @@ const SupplierProductMappingForm = ({
key: "ProdId",
align: "center",
width: "80px",
render: (text, object, index) => <span>{index + 1}</span>,
render: (text, object, index) => (
<span>{(currentPage - 1) * pageSize + index + 1}</span>
),
},
{
title: "Product Name",
@ -274,7 +279,7 @@ const SupplierProductMappingForm = ({
isOnchanges={false}
alphabetfilter="Yes"
/>
<button style={{ padding: '10px 10px', margin: '0px 15px', borderRadius: '6px',fontFamily:'poppins', background: '#901D77', color: 'white', border: 'none', cursor: 'pointer' }}
<button style={{ padding: '10px 10px', margin: '0px 15px', borderRadius: '6px', fontFamily: 'poppins', background: '#901D77', color: 'white', border: 'none', cursor: 'pointer' }}
onClick={allProductMap}>Add All</button>
<div style={{ position: "absolute", left: "16rem", top: "1px" }}>
@ -293,12 +298,22 @@ const SupplierProductMappingForm = ({
)}
</div>
<div className="modal-table" style={{ marginTop: "1rem" }}>
<div className="ProductMappingTable" style={{ marginTop: "1rem" }}>
<Tables
columns={tableColumns}
data={modelTableData}
dataSource={modelTableData}
pagination={false}
pagination={{
current: currentPage,
pageSize: pageSize,
total: modelTableData.length,
showSizeChanger: false,
onChange: (page, size) => {
setCurrentPage(page);
setPageSize(size);
},
}}
ownPagination={true}
rowKey="ProdId"
/>
</div>

View File

@ -97,3 +97,10 @@
}
}
}
.ProductMappingTable {
margin-top: 20px;
height: 300px;
overflow-y: auto;
border-radius: 6px;
}