import React from 'react'; import { useSelector } from 'react-redux'; import { GlobalPritdummyData, GlobalSelectedPrintHeaderColor, } from '../../../../Features/ThemeChange/ThemeChange'; import { isMobile } from 'react-device-detect'; import { extractLastNumberOrderId } from '../../../../Services/Others'; import moment from 'moment'; import { settingDataSelector } from '../../../../Features/PreferenceMaster/PreferenceMaster'; import { PreferenceData } from '../../../../Features/BookingScreen/BookingData/BookingData'; const TaxInvoice = ({ index, table2Data, Date1, CashierName, totalQuantity, OrderDetailGST, OrderDetailIGST, OrderDetailVAT, PaymentStatus, ReprintType, printDatas, }) => { const GlobaldummyData = useSelector(GlobalPritdummyData); const SettingData = useSelector(PreferenceData); const estimatePrintHeader = SettingData?.[0]?.SettingDtlDetails?.find( (setting) => setting?.SettingIdName?.toLowerCase() === 'estimateprintheader' )?.SettingValue === 'Y'; let BillName = printDatas?.PrintHdrName; let companyColour = printDatas?.PrintHdrColor ?? '#00000'; const SelectedHeaderColor = useSelector(GlobalSelectedPrintHeaderColor); // Function to convert number to words const numberToWords = (num) => { const a = [ '', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen', ]; const b = [ '', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety', ]; if (num === 0) return 'Zero'; if (num < 20) return a[num]; if (num < 100) return b[Math.floor(num / 10)] + (num % 10 ? ' ' + a[num % 10] : ''); if (num < 1000) return ( a[Math.floor(num / 100)] + ' Hundred' + (num % 100 ? ' and ' + numberToWords(num % 100) : '') ); if (num < 100000) return ( numberToWords(Math.floor(num / 1000)) + ' Thousand' + (num % 1000 ? ' ' + numberToWords(num % 1000) : '') ); if (num < 10000000) return ( numberToWords(Math.floor(num / 100000)) + ' Lakh' + (num % 100000 ? ' ' + numberToWords(num % 100000) : '') ); if (num < 1000000000) return ( numberToWords(Math.floor(num / 10000000)) + ' Crore' + (num % 10000000 ? ' ' + numberToWords(num % 10000000) : '') ); return 'Number too large'; }; // Helper to format date as 7-Aug-2025 function formatDateToDDMMMYYYY(dateStr) { console.log(dateStr, 'dateStrdateStr'); if (!dateStr) return ''; const date = new Date(dateStr); if (isNaN(date)) return dateStr; // fallback if invalid date const day = date.getDate(); const month = date.toLocaleString('en-US', { month: 'short' }); const year = date.getFullYear(); return `${day}-${month}-${year}`; } function removeTimeFromDate(dateStr) { if (!dateStr) return ''; // Split on ":" — first part will be "DD-MM-YYYY" const parts = dateStr.split(':'); return parts[0] || dateStr; } const invoiceData = { // Company Details - mapped from A4Standard companyName: table2Data?.CompName || table2Data?.BrName || '', companyspecname: table2Data?.AppSpecificName || '', companyAddress: { address1: table2Data?.AddressDetails?.[0]?.Address1 || '', address2: table2Data?.AddressDetails?.[0]?.Address2 || '', city: table2Data?.AddressDetails?.[0]?.City || '', state: table2Data?.AddressDetails?.[0]?.State || '', zip: table2Data?.AddressDetails?.[0]?.Zip || '', }, companyGSTIN: table2Data?.CompGSTIN || table2Data?.BrGSTIN || '', companyEmail: table2Data?.CompanyEmail || table2Data?.BrEmail || '', companyMobile: table2Data?.BrMobile || '', companyMobile2: table2Data?.BrMobile2 || '', // Invoice Details - mapped from A4Standard invoiceNo: table2Data?.OrderId ? extractLastNumberOrderId(table2Data?.OrderId, table2Data?.FYStatus) : '', invoiceDate: moment(Date1).format('DD-MMM-YYYY'), // Customer Details - mapped from A4Standard CustomerDetails array customerName: table2Data?.CustomerDetails?.[0]?.CustSuppName || table2Data?.CustSuppName || '', customerMobile: table2Data?.CustomerDetails?.[0]?.MobileNo || table2Data?.MobileNo || '', customerGSTIN: table2Data?.CustomerDetails?.[0]?.CustGSTNo || table2Data?.CustGSTIN || '', customerAddress: { address1: table2Data?.CustomerDetails?.[0]?.Address1 || '', address2: table2Data?.CustomerDetails?.[0]?.Address2 || '', state: table2Data?.CustomerDetails?.[0]?.State || '', }, // Product Details - mapped from A4Standard productDetails productDetails: table2Data?.productDetails || [], // Totals - mapped from A4Standard totalAmount: Number(table2Data?.BillAmount || table2Data?.TotalAmt), taxAmount: Number(OrderDetailGST), grandTotal: Number(table2Data?.NetAmount || table2Data?.GrandTotal), totalBillAmount: Number( table2Data?.BillAmount || table2Data?.NetAmount || 0 ), // Bank Details - mapped from A4Standard bankDetails: table2Data?.BankDetails?.[0] || null, }; let PageSize = printDatas?.PageSize; const TakeawayData = table2Data?.productDetails?.filter( (item) => item.BookingTypeName?.toLowerCase() === 'takeaway' ); const DineInData = table2Data?.productDetails?.filter( (item) => item.BookingTypeName?.toLowerCase() === 'dine in' ); let PaymentStatusSuccess = PaymentStatus?.filter( (ps) => ps.PaymentStatus === 'S' ); // Calculate GST/IGST totals const cgstTotal = OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce((sum, item) => sum + (item.CGST || 0), 0) )?.toFixed(2) : 0; const sgstTotal = OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce((sum, item) => sum + (item.SGST || 0), 0) )?.toFixed(2) : 0; const igstTotal = OrderDetailIGST && OrderDetailIGST.length > 0 ? Number( OrderDetailIGST?.reduce((sum, item) => sum + (item.TaxAmt || 0), 0) )?.toFixed(2) : 0; // Calculate round off value const roundOffValue = Number(invoiceData.grandTotal) - (Number(invoiceData.totalBillAmount) + Number(cgstTotal) + Number(sgstTotal) + Number(igstTotal)); const roundOffEstimateValue = Number(invoiceData.grandTotal); console.log( Number(invoiceData.totalBillAmount), cgstTotal, sgstTotal, igstTotal, 'roundoff vaules' ); function RoundOffFun(amount) { const roundedAmount = Math.round(amount); const roundOffValue = parseFloat((roundedAmount - amount).toFixed(2)); // const symbol = roundOffValue > 0 ? '+' : ''; // Add "+" symbol for positive values ${symbol} console.log( 'Rounded Amount:', roundedAmount, 'Round Off Value:', roundOffValue ); return `${roundOffValue.toFixed(2)}`; } console.log('=== DEBUG INFO ==='); console.log('table2Data?.productDetails:', table2Data?.productDetails); console.log('GlobaldummyData:', GlobaldummyData); console.log('TakeawayData:', TakeawayData); console.log('DineInData:', DineInData); console.log('PageSize:', PageSize); // Allow up to 10 items per page const chunkSize = table2Data?.OrderType !== 'E' ? isMobile ? 7 : PageSize == 'A5' ? 9 : 7 : isMobile ? 10 : PageSize == 'A5' ? 12 : 11; let dataSource = []; // Simplified data source logic - always use all product details dataSource = table2Data?.productDetails || []; // Ensure dataSource is always an array if (!Array.isArray(dataSource)) { dataSource = []; } console.log( 'Final DataSource:', dataSource, 'Length:', dataSource.length, 'ChunkSize:', chunkSize ); const paginatedChunks = []; // Always create at least one chunk, even if empty if (dataSource.length === 0) { paginatedChunks.push([]); } else { // Split data into chunks for (let i = 0; i < dataSource.length; i += chunkSize) { const chunk = dataSource.slice(i, i + chunkSize); paginatedChunks.push(chunk); } } const lastChunkRows = paginatedChunks.length > 0 ? paginatedChunks[paginatedChunks.length - 1].length : 0; // If last page has more than 6 items, move footer to new page const shouldFooterBeOnNewPage = lastChunkRows === chunkSize; // If footer should be on new page, add an empty chunk for footer-only page if (shouldFooterBeOnNewPage && paginatedChunks.length > 0) { paginatedChunks.push([]); // Empty chunk for footer-only page } console.log( 'Paginated Chunks:', paginatedChunks.length, 'Chunks:', paginatedChunks.map((chunk, i) => `Chunk ${i}: ${chunk.length} items`) ); console.log('Should footer be on new page:', shouldFooterBeOnNewPage); return (
{paginatedChunks?.map((dataChunk, chunkIndex) => (
0 ? ' print-page-break' : ''}` } style={{ display: 'flex', flexDirection: 'column', // justifyContent: ((chunkIndex === paginatedChunks.length - 1) && (!shouldFooterBeOnNewPage)) ? "space-between" : "", height: isMobile ? '275mm' : PageSize == 'A5' ? '130mm' : '245mm', marginBottom: '0', pageBreakAfter: chunkIndex < paginatedChunks.length - 1 ? 'always' : 'auto', }} > {renderInvoiceContent(dataChunk, chunkIndex)}
))}
); function renderInvoiceContent(dataChunk, chunkIndex) { console.log( `Rendering page ${chunkIndex + 1}, chunk has ${dataChunk.length} items:`, dataChunk ); const isFirstPage = chunkIndex === 0; const isLastPage = chunkIndex === paginatedChunks.length - 1; const isFooterOnlyPage = isLastPage && dataChunk.length === 0 && shouldFooterBeOnNewPage; const isLastDataChunk = chunkIndex === paginatedChunks.length - 1 - (shouldFooterBeOnNewPage ? 1 : 0); const shouldShowTaxDetails = isLastDataChunk && dataChunk.length > 0; console.log( `Page ${chunkIndex + 1}: isFirstPage=${isFirstPage}, isLastPage=${isLastPage}, isFooterOnlyPage=${isFooterOnlyPage},datachunkslength=${dataChunk.length}` ); return ( <> {/* Header - Only on first page */} {isFirstPage && ( <>

{table2Data?.OrderType === 'E' ? 'Estimate' : BillName ? BillName : 'TAX INVOICE'}

{ReprintType == 'Duplicate' ? '(DUPLICATE FOR RECIPIENT)' : '(ORIGINAL FOR RECIPIENT)'}
)} {/* Main Container - Always show */}
{/* Top Section - Company and Invoice Details - Only on first page */} {isFirstPage && (
{/* Left - Company Details */}
{!estimatePrintHeader && table2Data?.OrderType === 'E' ? ( '' ) : (
{invoiceData.companyName}
{invoiceData.companyspecname}
{invoiceData.companyAddress.address1}
{invoiceData.companyAddress.address2}
{invoiceData.companyAddress.city}{' '} {invoiceData.companyAddress.zip ? ` - ${invoiceData.companyAddress.zip}` : ''}
{invoiceData.companyAddress.state}
{invoiceData.companyGSTIN && (
GSTIN/UIN: {invoiceData.companyGSTIN}
)} {/*
State Name: Tamil Nadu, Code: 33
*/} {invoiceData.companyEmail && (
E-Mail: {invoiceData.companyEmail}
)} {invoiceData.companyMobile && (
Mobile: +91 {invoiceData.companyMobile} {invoiceData.companyMobile2 ? `, ${invoiceData.companyMobile2}` : ''}
)}
)} {/* Buyer Details */}
Buyer (Bill to)
{invoiceData.customerName}
{invoiceData.customerAddress.address1 && (
{invoiceData.customerAddress.address1}
)} {invoiceData.customerAddress.address2 && (
{invoiceData.customerAddress.address2}
)} {invoiceData.customerMobile && (
Mobile: {invoiceData.customerMobile}
)} {invoiceData.customerGSTIN && table2Data?.OrderType !== 'E' && (
GSTIN/UIN: {invoiceData.customerGSTIN}
)} {invoiceData.customerAddress.state && (
State Name: {invoiceData.customerAddress.state}
)}
{/* Right - Invoice Details */}
{/* Invoice No and Date */}
Invoice No.
{invoiceData.invoiceNo}
Dated
{invoiceData.invoiceDate}
{/* Delivery Note and Payment Terms */}
Delivery Note
Mode/Terms of Payment
{/* Reference and Other References */}
Reference No. & Date
Other References
{/* Buyer's Order */}
Buyer's Order No.
Dated
{/* Dispatch Details */}
Dispatch Doc No.
Delivery Note Date
{/* Dispatched through and Destination */}
Dispatched through
Destination
{/* Terms of Delivery */}
Terms of Delivery
)} {/* Continuation header for non-first pages */} {!isFirstPage && (

{isFooterOnlyPage ? 'Tax Invoice' : 'Tax Invoice '}

Invoice No: {invoiceData.invoiceNo}
)} {/* Items Table - Show only if there are items or not a footer-only page */} {(dataChunk.length > 0 || !isFooterOnlyPage) && (
{/* Table Header */}
SL.No
Description of Goods
HSN/SAC
Quantity
Rate
{/*
per
*/}
Amount
{/* Table Rows - Dynamic data from dataChunk */} {dataChunk && dataChunk.length > 0 ? ( <> {dataChunk?.map((item, index) => (
{chunkIndex * chunkSize + index + 1}
{item.ProdName || 'Product Name'}
{item.BrandName && (
{item.BrandName}{' '}
)} {item?.ProductIdentifierDtls?.length > 0 ? item?.ProductIdentifierDtls.filter( (items) => items.SerialNumber && items.SerialNumber !== '' )?.map((a, i) => (
{a.SerialNumber}
)) : ''} {item?.ProductIdentifierDtls?.length > 0 ? item?.ProductIdentifierDtls.filter( (id) => id.IMEI1 !== '' || id.IMEI2 !== '' )?.map((id, i) => { const imei1 = id.IMEI1 || ''; const imei2 = id.IMEI2 || ''; return (
{[imei1, imei2].filter(Boolean).join(',')}
); }) : ''}
{item.HSN || ''}
{item.SalesQty || 1} {item.UomName || 'NOS'}
{Number( table2Data?.OrderType !== 'E' ? item.Rate - item.ProdTaxAmt : item.Rate || 0 ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
{/*
{item.UomName || 'NOS'}
*/}
{Number( table2Data?.OrderType !== 'E' ? item.WithoutTaxRate : item.TotalAmt || 0 ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
))} {/* Tax summary */} {shouldShowTaxDetails && ( <> {/* Total without tax amount */}
{/*
*/}
₹{' '} {Number( table2Data?.OrderType !== 'E' ? invoiceData?.totalBillAmount : invoiceData?.grandTotal ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
{table2Data?.OrderType !== 'E' && ( <> {/* CGST */} {OrderDetailGST && OrderDetailGST.length > 0 && ( <>
CGST
{/*
*/}
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.CGST || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{/* SGST */}
SGST
{/*
*/}
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.SGST || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
)} {/* IGST */} {OrderDetailIGST && OrderDetailIGST.length > 0 && (
IGST
{/*
*/}
{OrderDetailIGST && OrderDetailIGST.length > 0 ? Number( OrderDetailIGST?.reduce( (sum, item) => sum + (item.TaxAmt || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
)} )} {/* Rounding Off */}
ROUNDING OFF
{/*
*/}
{RoundOffFun( table2Data?.OrderType !== 'E' ? roundOffValue : roundOffEstimateValue )}
{Array.from({ length: chunkSize - dataChunk.length, })?.map((_, idx) => (
 
 
 
 
 
{/*
 
*/}
 
))} {/* Total */}
Total
{totalQuantity || invoiceData.productDetails?.reduce( (sum, item) => sum + (item.SalesQty || 0), 0 ) || 0}{' '} NOS
{/*
*/}
₹{' '} {Number(invoiceData.grandTotal).toLocaleString( 'en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}
)} ) : ( // Show empty row when no data
-
No items to display
-
-
-
-
-
)}
)} {/* Tax summary - Only on last page */} {/* Footer content - Only on last page */} {isLastPage && ( <> {/* Amount in Words */}
Amount Chargeable (in words)
INR {numberToWords(Math.floor(invoiceData.grandTotal))} Only

E. & O.E

{table2Data?.OrderType !== 'E' && ( <> {/* Tax Breakdown Table */}
{OrderDetailGST && OrderDetailGST.length > 0 ? ( <> {/* Tax Table Header - Main Headers */}
HSN/SAC
Taxable Value
CGST
SGST/UTGST
Tax Amount
{/* Tax Table Sub-Headers */}
Rate
Amount
Rate
Amount
{/* Tax Table Rows - Dynamic from OrderDetailGST */} {OrderDetailGST?.map((taxItem, index) => (
{taxItem.HSN || ''}
{Number( taxItem.WithOutTaxAmount || 0 ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
{taxItem.TaxPercentage ? taxItem.TaxPercentage / 2 + '%' : '0%'}
{Number(taxItem.CGST || 0).toLocaleString( 'en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}
{taxItem.TaxPercentage ? taxItem.TaxPercentage / 2 + '%' : '0%'}
{Number(taxItem.SGST || 0).toLocaleString( 'en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}
{Number( (taxItem.CGST || 0) + (taxItem.SGST || 0) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
))}
Total
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.WithOutTaxAmount || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.CGST || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.SGST || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{OrderDetailGST && OrderDetailGST.length > 0 ? Number( OrderDetailGST?.reduce( (sum, item) => sum + (item.CGST || 0) + (item.SGST || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
) : OrderDetailIGST && OrderDetailIGST.length > 0 ? ( <> {/* Tax Table Header - Main Headers */}
HSN/SAC
Taxable Value
IGST
Tax Amount
{/* Tax Table Sub-Headers */}
Rate
Amount
{/* Tax Table Rows - Dynamic from OrderDetailGST */} {OrderDetailIGST?.map((taxItem, index) => (
{taxItem.HSN || ''}
{Number( taxItem.WithOutTaxAmount || 0 ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}
{taxItem.TaxPercentage ? taxItem.TaxPercentage + '%' : '0%'}
{Number(taxItem.TaxAmt || 0).toLocaleString( 'en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}
{Number(taxItem.TaxAmt || 0).toLocaleString( 'en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}
))}{' '}
Total
{OrderDetailIGST && OrderDetailIGST.length > 0 ? Number( OrderDetailIGST?.reduce( (sum, item) => sum + (item.WithOutTaxAmount || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{OrderDetailIGST && OrderDetailIGST.length > 0 ? Number( OrderDetailIGST?.reduce( (sum, item) => sum + (item.TaxAmt || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
{OrderDetailIGST && OrderDetailIGST.length > 0 ? Number( OrderDetailIGST?.reduce( (sum, item) => sum + (item.TaxAmt || 0), 0 ) ).toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2, }) : '0.00'}
) : ( <> {/* Tax Table Header - Main Headers */}
HSN/SAC
Taxable Value
CGST
SGST/UTGST
Tax Amount
{/* Tax Table Sub-Headers */}
Rate
Amount
Rate
Amount
-
0.00
0%
0.00
0%
0.00
0.00
{/* Tax Table Total */}
Total
{'0.00'}
{'0.00'}
{'0.00'}
{'0.00'}
)}
{/* Tax Amount in Words */}
Tax Amount (in words):{' '} INR{' '} {numberToWords( Math.floor( invoiceData.taxAmount || OrderDetailGST?.reduce( (sum, item) => sum + (item.CGST || 0) + (item.SGST || 0), 0 ) || Number( OrderDetailIGST?.reduce( (sum, item) => sum + (item.TaxAmt || 0), 0 ) ) || 0 ) )}{' '} Only
)} {/* Bank Details and Signature */}
{/* Declaration */}
Declaration
We declare that this invoice shows the actual price of the goods described and that all particulars are true and correct.
{/* Signature Section */}
{/* Bank Details */}
{!estimatePrintHeader && table2Data?.OrderType === 'E' ? ( '' ) : (
Company's Bank Details
)} {!estimatePrintHeader && table2Data?.OrderType === 'E' ? ( '' ) : (
A/c Holder's Name: {' '} {invoiceData.companyName}
Bank Name: {' '} {invoiceData.bankDetails?.BankName || ''}
A/c No.:{' '} {invoiceData.bankDetails?.AccountNo || ''}
Branch & IFS Code:{' '} {invoiceData.bankDetails?.BankBranch || ''} &{' '} {invoiceData.bankDetails?.IFSCCode || ''}
{invoiceData.bankDetails?.SWIFTCode && (
SWIFT Code: {' '} {invoiceData.bankDetails?.SWIFTCode || ''}
)}
)}
{!estimatePrintHeader && table2Data?.OrderType === 'E' ? ( '' ) : (
for {invoiceData.companyName}
)}
{/*
DD
TECHNOLOGIES
ELECTRONICS
*/}
Authorised Signatory
)}
{/* Footer - Only on last page */} {isLastPage && (
This is a Computer Generated Invoice
)} ); } }; export default TaxInvoice;