shareneus 1.7.4 → 1.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +1 -0
  2. package/dist/accounting/invoice/invoice-pdf/invoice-pdf.service.js +18 -45
  3. package/dist/accounting/invoice/reports/excel/analysis-excel.service.js +17 -7
  4. package/dist/accounting/invoice/reports/excel/category-wise-item-excel.service.js +17 -7
  5. package/dist/accounting/invoice/reports/excel/cust-wise-sales-details.js +17 -7
  6. package/dist/accounting/invoice/reports/excel/cust-wise-sales-summary-excel.service.js +17 -7
  7. package/dist/accounting/invoice/reports/excel/invoice-wise-excel.service.js +17 -7
  8. package/dist/accounting/invoice/reports/excel/item-wise-doctor-sale-excel.service.js +17 -7
  9. package/dist/accounting/invoice/reports/excel/items-wise-sales-excel.service.js +17 -7
  10. package/dist/accounting/invoice/reports/excel/manf-wise-sales-excel.service.js +17 -7
  11. package/dist/accounting/invoice/reports/excel/operator-wise-details.js +17 -7
  12. package/dist/accounting/invoice/reports/excel/operator-wise-summary.js +17 -7
  13. package/dist/accounting/invoice/reports/excel/sa-wise-labor-sales-excel.service.js +17 -7
  14. package/dist/accounting/invoice/reports/excel/sa-wise-part-sales-excel.service.js +17 -7
  15. package/dist/accounting/invoice/reports/excel/sale-summary-excel.service.js +17 -7
  16. package/dist/accounting/invoice/reports/excel/sales-by-service-summary-excel.service.js +17 -7
  17. package/dist/accounting/invoice/reports/excel/scheduled-drug-summary-excel.service.js +17 -7
  18. package/dist/accounting/invoice/reports/excel/scheduled-drugs-excel.service.js +17 -7
  19. package/dist/accounting/invoice/unified-invoice-pdf.service.d.ts +1 -1
  20. package/dist/accounting/payment-receive/reports/excel/cust-balance-excel.service.js +17 -7
  21. package/dist/accounting/payment-receive/reports/excel/payment-receive-excel.service.js +17 -7
  22. package/dist/common/reports/excel/product-without-owner-excel.service.js +17 -7
  23. package/dist/gst/excel/GSTR-RO-excel.service.js +17 -7
  24. package/dist/gst/excel/GSTR1-excel.service.js +17 -7
  25. package/dist/gst/excel/GSTR2-excel.service.js +17 -7
  26. package/dist/gst/excel/hsn-summary.js +17 -7
  27. package/dist/gst/excel/tally-sales-import.service.js +17 -7
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.js +6 -6
  30. package/dist/inventory/items/reports/excel/expiring-drugs-excel.service.js +17 -7
  31. package/dist/inventory/items/reports/excel/item-wise-mout-details.js +17 -7
  32. package/dist/inventory/items/reports/excel/item-wise-mout-summary.js +17 -7
  33. package/dist/inventory/items/reports/excel/spares-issue-excel.service.js +17 -7
  34. package/dist/inventory/items/reports/excel/stock-excel.service.js +17 -7
  35. package/dist/purchases/payment-made/reports/excel/payments-made-excel.service.js +17 -7
  36. package/dist/purchases/payment-made/reports/excel/ven-balance-excel.service.js +17 -7
  37. package/dist/services/reports/excel/insurance-expire-excel.service.js +17 -7
  38. package/dist/services/reports/excel/next-service-date-excel.service.js +17 -7
  39. package/dist/services/reports/excel/repair-orders-excel.service.js +17 -7
  40. package/dist/shared/table-section/pdf-table.header.d.ts +1 -1
  41. package/dist/shared/table-section/pdf-table.header.js +14 -2
  42. package/dist/shared/table-section/pdf-table.section.js +6 -13
  43. package/dist/{accounting/invoice/invoice-pdf.service.js → shared/transactions-pdf.service.js} +15 -15
  44. package/package.json +1 -1
  45. package/src/accounting/counter-sales/auto-sales-receipt-pdf.service.ts +569 -0
  46. package/src/accounting/counter-sales/pos-receipt-pdf.ts +577 -0
  47. package/src/accounting/counter-sales/sales-receipt-pdf.service.ts +628 -0
  48. package/src/accounting/counter-sales/sales-receipt-print.service.ts +506 -0
  49. package/src/accounting/credit-note/cn-print.service.ts +264 -0
  50. package/src/accounting/credit-note/credit-note-pdf.service.ts +602 -0
  51. package/src/accounting/credit-note/credit-note-totals.service.ts +424 -0
  52. package/src/accounting/debit-note/debit-note-pdf.service.ts +681 -0
  53. package/src/accounting/debit-note/debit-note-print.service.ts +276 -0
  54. package/src/accounting/debit-note/debit-note-totals.service.ts +361 -0
  55. package/src/accounting/invoice/hc-inv-pdf.service.ts +880 -0
  56. package/src/accounting/invoice/inv-pdf.service.ts +812 -0
  57. package/src/accounting/invoice/inv-print.service.ts +532 -0
  58. package/src/accounting/invoice/invoice-landscape-pdf.service.ts +947 -0
  59. package/src/accounting/invoice/invoice-letterhead-pdf.service.ts +813 -0
  60. package/src/accounting/invoice/invoice-pdf/invoice-pdf.service.ts +359 -0
  61. package/src/accounting/invoice/invoice-portrait-pdf.ts +972 -0
  62. package/src/accounting/invoice/invoice-print.service.ts +2906 -0
  63. package/src/accounting/invoice/invoice-total.service.ts +834 -0
  64. package/src/accounting/invoice/reports/excel/analysis-excel.service.ts +291 -0
  65. package/src/accounting/invoice/reports/excel/category-wise-item-excel.service.ts +267 -0
  66. package/src/accounting/invoice/reports/excel/cust-wise-sales-details.ts +321 -0
  67. package/src/accounting/invoice/reports/excel/cust-wise-sales-summary-excel.service.ts +300 -0
  68. package/src/accounting/invoice/reports/excel/invoice-wise-excel.service.ts +859 -0
  69. package/src/accounting/invoice/reports/excel/item-wise-doctor-sale-excel.service.ts +255 -0
  70. package/src/accounting/invoice/reports/excel/items-wise-sales-excel.service.ts +312 -0
  71. package/src/accounting/invoice/reports/excel/manf-wise-sales-excel.service.ts +273 -0
  72. package/src/accounting/invoice/reports/excel/operator-wise-details.ts +258 -0
  73. package/src/accounting/invoice/reports/excel/operator-wise-summary.ts +259 -0
  74. package/src/accounting/invoice/reports/excel/sa-wise-labor-sales-excel.service.ts +230 -0
  75. package/src/accounting/invoice/reports/excel/sa-wise-part-sales-excel.service.ts +231 -0
  76. package/src/accounting/invoice/reports/excel/sale-summary-excel.service.ts +326 -0
  77. package/src/accounting/invoice/reports/excel/sales-by-service-details-excel.service.ts +0 -0
  78. package/src/accounting/invoice/reports/excel/sales-by-service-summary-excel.service.ts +432 -0
  79. package/src/accounting/invoice/reports/excel/scheduled-drug-summary-excel.service.ts +373 -0
  80. package/src/accounting/invoice/reports/excel/scheduled-drugs-excel.service.ts +372 -0
  81. package/src/accounting/invoice/reports/pdf/analysis-pdf.service.ts +113 -0
  82. package/src/accounting/invoice/reports/pdf/category-wise-item-pdf.service.ts +107 -0
  83. package/src/accounting/invoice/reports/pdf/cust-wise-sales-details-pdf.service.ts +125 -0
  84. package/src/accounting/invoice/reports/pdf/cust-wise-sales-summary-pdf.service.ts +119 -0
  85. package/src/accounting/invoice/reports/pdf/item-wise-doctor-sale-pdf.service.ts +180 -0
  86. package/src/accounting/invoice/reports/pdf/item-wise-sales-pdf.service.ts +193 -0
  87. package/src/accounting/invoice/reports/pdf/manf-wise-sales-pdf.service.ts +188 -0
  88. package/src/accounting/invoice/reports/pdf/operator-wise-details-pdf.service.ts +118 -0
  89. package/src/accounting/invoice/reports/pdf/operator-wise-summary-pdf.ts +116 -0
  90. package/src/accounting/invoice/reports/pdf/sales-by-service-pdf.service.ts +132 -0
  91. package/src/accounting/invoice/reports/pdf/scheduled-drug-pdf.service.ts +191 -0
  92. package/src/accounting/invoice/reports/pdf/scheduled-drug-summary-pdf.service.ts +202 -0
  93. package/src/accounting/invoice/shared-inv-pdf.service.ts +787 -0
  94. package/src/accounting/invoice/unified-invoice-pdf.service.ts +937 -0
  95. package/src/accounting/payment-receive/payment-pdf.service.ts +410 -0
  96. package/src/accounting/payment-receive/payment-receipt-pdf/receipt-pdf.service.ts +470 -0
  97. package/src/accounting/payment-receive/receipt-print.service.ts +71 -0
  98. package/src/accounting/payment-receive/reports/excel/cust-balance-excel.service.ts +298 -0
  99. package/src/accounting/payment-receive/reports/excel/payment-receive-excel.service.ts +221 -0
  100. package/src/accounting/payment-receive/reports/pdf/customer-balances-pdf.service.ts +182 -0
  101. package/src/accounting/payment-receive/reports/pdf/payment-report-pdf.service.ts +116 -0
  102. package/src/aggregation/aggregation.ts +58 -0
  103. package/src/appointments/appointments/appointment-total.service.ts +298 -0
  104. package/src/appointments/consultations/consultation-fee-receipt.service.ts +407 -0
  105. package/src/appointments/consultations/consultation-full-pdf.service.ts +238 -0
  106. package/src/appointments/consultations/consultation-letterhead-pdf.service.ts +430 -0
  107. package/src/appointments/consultations/consultation-pdf.service.ts +417 -0
  108. package/src/common/reports/excel/product-without-owner-excel.service.ts +308 -0
  109. package/src/common/reports/pdf/product-without-owner-pdf.service.ts +146 -0
  110. package/src/enums/cache-enums.ts +33 -0
  111. package/src/enums/code-enums.ts +291 -0
  112. package/src/enums/country-enums.ts +9 -0
  113. package/src/enums/enums.ts +364 -0
  114. package/src/enums/industry-enums.ts +26 -0
  115. package/src/enums/treatment-enums.ts +9 -0
  116. package/src/gst/excel/GSTR-RO-excel.service.ts +926 -0
  117. package/src/gst/excel/GSTR1-excel.service.ts +313 -0
  118. package/src/gst/excel/GSTR2-excel.service.ts +314 -0
  119. package/src/gst/excel/hsn-summary.ts +314 -0
  120. package/src/gst/excel/tally-sales-import.service.ts +767 -0
  121. package/src/gst/pdf/hsn-summary-pdf.ts +176 -0
  122. package/src/index.ts +194 -0
  123. package/src/inventory/items/adjustment-pdf.service.ts +177 -0
  124. package/src/inventory/items/issue-parts-pdf.service.ts +795 -0
  125. package/src/inventory/items/item-bar-code-label-pdf.ts +194 -0
  126. package/src/inventory/items/item-detais-pdf.ts +141 -0
  127. package/src/inventory/items/item-price-for-pricelist.ts +368 -0
  128. package/src/inventory/items/reports/excel/expiring-drugs-excel.service.ts +290 -0
  129. package/src/inventory/items/reports/excel/item-wise-mout-details.ts +284 -0
  130. package/src/inventory/items/reports/excel/item-wise-mout-summary.ts +279 -0
  131. package/src/inventory/items/reports/excel/spares-issue-excel.service.ts +494 -0
  132. package/src/inventory/items/reports/excel/stock-excel.service.ts +319 -0
  133. package/src/inventory/items/reports/pdf/expiring-drugs-pdf.service.ts +172 -0
  134. package/src/inventory/items/reports/pdf/item-wise-mout-details-pdf.ts +122 -0
  135. package/src/inventory/items/reports/pdf/item-wise-mout-summary-pdf.ts +115 -0
  136. package/src/inventory/items/reports/pdf/reorder-point-pdf.service.ts +163 -0
  137. package/src/inventory/material-out/mout-pdf.service.ts +545 -0
  138. package/src/inventory/transfer-order/transfer-order-pdf.service.ts +154 -0
  139. package/src/purchases/bills/bill-pdf/bill-pdf.service.ts +211 -0
  140. package/src/purchases/bills/bill-pdf.service.ts +21 -0
  141. package/src/purchases/payment-made/reports/excel/payments-made-excel.service.ts +313 -0
  142. package/src/purchases/payment-made/reports/excel/ven-balance-excel.service.ts +307 -0
  143. package/src/purchases/payment-made/reports/pdf/vendor-balances-pdf.service.ts +114 -0
  144. package/src/purchases/purchase-order/po-totals.service.ts +343 -0
  145. package/src/purchases/purchase-order/purchase-order-pdf.service.ts +1016 -0
  146. package/src/purchases/purchase-order/purchase-order-print.service.ts +279 -0
  147. package/src/purchases/purchase-order/purchase-order-totals.service.ts +637 -0
  148. package/src/purchases/vendor-credit-note/vendor-credit-note-pdf.service.ts +1055 -0
  149. package/src/purchases/vendor-credit-note/vendor-credit-note-print.service.ts +145 -0
  150. package/src/purchases/vendor-credit-note/vendor-credit-note-totals.service.ts +399 -0
  151. package/src/purchases/vendor-debit-note/vendor-debit-note-pdf.service.ts +582 -0
  152. package/src/purchases/vendor-debit-note/vendor-debit-note-print.service.ts +295 -0
  153. package/src/purchases/vendor-debit-note/vendor-debit-note-totals.service.ts +377 -0
  154. package/src/sales/delivery-challan/dc-landscape-pdf.service.ts +922 -0
  155. package/src/sales/delivery-challan/dc-landscape-without-price-pdf.service.ts +869 -0
  156. package/src/sales/delivery-challan/dc-without-price-pdf.service.ts +505 -0
  157. package/src/sales/delivery-challan/delivery-challan-pdf.service.ts +461 -0
  158. package/src/sales/delivery-challan/delivery-challan-print.service.ts +229 -0
  159. package/src/sales/delivery-challan/delivery-challan-totals.ts +466 -0
  160. package/src/sales/sales/equipment-design-pdf.service.ts +153 -0
  161. package/src/sales/sales/pack-ship-pdf.service.ts +128 -0
  162. package/src/sales/sales/pack-ship-print.service.ts +198 -0
  163. package/src/sales/sales/sales-pdf.service.ts +658 -0
  164. package/src/sales/sales/sales-print.service.ts +376 -0
  165. package/src/sales/sales/sales-totals.service.ts +500 -0
  166. package/src/sales-receive/sales-receive-pdf.service.ts +602 -0
  167. package/src/sales-receive/sales-receive-print.service.ts +242 -0
  168. package/src/sales-receive/sales-receive-totals.service.ts +651 -0
  169. package/src/services/checklist-pdf.ts +151 -0
  170. package/src/services/checklists-pdf.ts +133 -0
  171. package/src/services/est.print-service.ts +1155 -0
  172. package/src/services/reports/excel/insurance-expire-excel.service.ts +292 -0
  173. package/src/services/reports/excel/next-service-date-excel.service.ts +317 -0
  174. package/src/services/reports/excel/repair-orders-excel.service.ts +249 -0
  175. package/src/services/reports/pdf/insurance-expire-pdf.service.ts +115 -0
  176. package/src/services/reports/pdf/next-service-date-pdf.service.ts +198 -0
  177. package/src/services/reports/pdf/repair-orders-pdf.service.ts +184 -0
  178. package/src/services/ro-pdf.service.ts +1917 -0
  179. package/src/services/ro-print-service.ts +881 -0
  180. package/src/services/ro-totals.service.ts +1314 -0
  181. package/src/services/separate-wo-print.service.ts +396 -0
  182. package/src/services/service-history-pdf.service.ts +145 -0
  183. package/src/services/service-price-for-pricelist.ts +649 -0
  184. package/src/services/technician-pdf.service.ts +234 -0
  185. package/src/services/technician-print.service.ts +95 -0
  186. package/src/shared/header-footer-section/pdf-header-footer.section.ts +519 -0
  187. package/src/shared/header-footer-section/pdf-shared.utils.ts +46 -0
  188. package/src/shared/math-operations.ts +208 -0
  189. package/src/shared/party-details-section/pdf-party-details.section.ts +602 -0
  190. package/src/shared/shared-pdf.service.ts +3042 -0
  191. package/src/shared/shared-print.service.ts +879 -0
  192. package/src/shared/table-section/pdf-table.config.ts +8 -0
  193. package/src/shared/table-section/pdf-table.header.ts +396 -0
  194. package/src/shared/table-section/pdf-table.row.ts +248 -0
  195. package/src/shared/table-section/pdf-table.section.ts +447 -0
  196. package/src/shared/totals-section/pdf-totals.section.ts +921 -0
  197. package/src/shared/transactions-pdf.service.ts +191 -0
  198. package/src/shared/util.ts +101 -0
  199. package/src/tasks/meetings/meeting-pdf.ts +410 -0
  200. package/src/tasks/tasks/task-pdf.service.ts +238 -0
  201. package/src/tasks/tasks/task-reports-pdf.service.ts +313 -0
  202. package/src/tax/index.ts +86 -0
  203. package/src/tax/tax-calculator.ts +1025 -0
  204. package/src/tax/tax.types.ts +535 -0
  205. package/src/transaction-calculations/discounts-distribution.ts +343 -0
  206. package/src/transaction-calculations/index.ts +3 -0
  207. package/src/transaction-calculations/total-calculation.ts +443 -0
  208. package/src/transaction-calculations/transaction-calculation-engine.ts +903 -0
  209. package/src/utils/my-date.ts +111 -0
  210. package/src/utils/tr-utils.ts +104 -0
  211. package/tsconfig.json +2 -2
  212. /package/dist/{accounting/invoice/invoice-pdf.service.d.ts → shared/transactions-pdf.service.d.ts} +0 -0
@@ -0,0 +1,921 @@
1
+
2
+ import { MyDate } from '../../utils/my-date';
3
+ import { normalizeHeaderData } from '../header-footer-section/pdf-header-footer.section';
4
+ import { firstValue } from '../header-footer-section/pdf-shared.utils';
5
+ import { Add } from '../math-operations';
6
+ import { formatAmount, readNumericValue } from '../table-section/pdf-table.section';
7
+
8
+ export function buildInvoiceTotalsAndNotesSection(invoiceData: any, availableWidth: number, PrintConfigData: any = {}) {
9
+ const normalizedInvoice = invoiceData || {};
10
+ const sType = firstValue(normalizedInvoice?.SType);
11
+ const companyName = firstValue(
12
+ normalizedInvoice?.Entity?.CName,
13
+ normalizedInvoice?.Entity?.Name,
14
+ normalizedInvoice?.CName,
15
+ normalizedInvoice?.CompanyName
16
+ );
17
+ const hideTopSection = isTruthy(normalizedInvoice?.Settings?.NoPr);
18
+ const isPoSPrint = isTruthy(PrintConfigData?.IsPoSPrint);
19
+ const shouldShowTaxSummary = resolveShowTaxSummary(normalizedInvoice, PrintConfigData);
20
+ const taxSummary = resolveTaxSummary(normalizedInvoice, shouldShowTaxSummary);
21
+ const showBankDetails = resolveShowBankDetails(normalizedInvoice, PrintConfigData);
22
+ const showDueSection = shouldShowDueSection(PrintConfigData);
23
+ const bankDetails = showBankDetails ? resolveBankDetails(normalizedInvoice) : { lines: [], hasData: false };
24
+ const totals = resolveTotals(normalizedInvoice, taxSummary.totalTax, PrintConfigData);
25
+ const totalInWords = resolveTotalInWords(normalizedInvoice);
26
+ const notes = firstValue(
27
+ normalizedInvoice?.Notes,
28
+ normalizedInvoice?.Note,
29
+ normalizedInvoice?.Remarks,
30
+ normalizedInvoice?.Remark
31
+ );
32
+ const terms = firstValue(
33
+ normalizedInvoice?.TermsAndConditions,
34
+ normalizedInvoice?.TermsCondition,
35
+ normalizedInvoice?.Terms,
36
+ normalizedInvoice?.TC
37
+ );
38
+ const dueInfo = resolveDueInfo(normalizedInvoice, totals);
39
+ const qrPayload = resolveQrPayload(normalizedInvoice, PrintConfigData);
40
+
41
+ const hasTopSection = !hideTopSection && (taxSummary.hasData || bankDetails.hasData || totals.hasData);
42
+ const hasBottomSection = !!(notes || terms || totalInWords || (showDueSection && dueInfo.hasData) || qrPayload);
43
+ if (!hasTopSection && !hasBottomSection) {
44
+ return [];
45
+ }
46
+
47
+ // const dividerLine = {
48
+ // canvas: [
49
+ // { type: 'line', x1: 0, y1: 0, x2: Math.max(1, availableWidth), y2: 0, lineWidth: 1, lineColor: '#1f2937' }
50
+ // ],
51
+ // margin: [0, 5, 0, 5]
52
+ // };
53
+
54
+ const topColumns = {
55
+ columns: buildTopSectionColumns(taxSummary, sType, showBankDetails, bankDetails, totals, totalInWords),
56
+ columnGap: 20,
57
+ margin: [0, 2, 0, 8]
58
+ };
59
+ const bottomColumns = buildPostTotalsInfoSection({
60
+ totalInWords,
61
+ notes,
62
+ terms,
63
+ companyName,
64
+ paidAmount: dueInfo.paid,
65
+ dueAmount: dueInfo.due,
66
+ qrPayload,
67
+ upiPhone: resolveUpiPhone(normalizedInvoice),
68
+ showInWords: taxSummary.hasData || showBankDetails,
69
+ showDueSection,
70
+ isPoSPrint
71
+ });
72
+ if (hasTopSection && hasBottomSection) {
73
+ return [ topColumns, bottomColumns];
74
+ }
75
+ if (hasTopSection) {
76
+ return [ topColumns];
77
+ }
78
+ return [ bottomColumns];
79
+ }
80
+
81
+ function buildTopSectionColumns(
82
+ taxSummary: { hasData: boolean; rows: any[] },
83
+ sType: string,
84
+ showBankDetails: boolean,
85
+ bankDetails: { lines: Array<{ label: string; value: string }>; hasData: boolean },
86
+ totals: { lines: Array<{ label: string; value: string }>; hasData: boolean },
87
+ totalInWords: string
88
+ ) {
89
+ const inWords = totalInWords || '-';
90
+
91
+ if (taxSummary.hasData) {
92
+ return [
93
+ { width: '42%', stack: buildTaxSummaryTableStack(null, taxSummary.rows, sType), marginTop: 2 },
94
+ { width: '28%', stack: showBankDetails ? buildInfoCardStack('Bank Details', bankDetails.lines) : [{ text: '' }] },
95
+ { width: '30%', stack: buildInfoCardStack(null, totals.lines, { rightAlign: true }) }
96
+ ];
97
+ }
98
+
99
+ if (showBankDetails) {
100
+ return [
101
+ { width: '40%', stack: buildInfoCardStack('Bank Details', bankDetails.lines) },
102
+ { width: '60%', stack: buildInfoCardStack(null, totals.lines, { rightAlign: true }) }
103
+ ];
104
+ }
105
+
106
+ return [
107
+ {
108
+ width: '70%',
109
+ columns: [
110
+ { width: 'auto', text: 'In Words :', bold: true, fontSize: 9, color: '#111827' },
111
+ { width: '*', text: inWords, bold: true, fontSize: 9, color: '#111827' }
112
+ ],
113
+ columnGap: 6,
114
+ margin: [0, 2, 0, 4]
115
+ },
116
+ { width: '30%', stack: buildInfoCardStack(null, totals.lines, { rightAlign: true }) }
117
+ ];
118
+ }
119
+
120
+ function buildPostTotalsInfoSection(data: {
121
+ totalInWords: string;
122
+ notes: string;
123
+ terms: string;
124
+ companyName: string;
125
+ paidAmount: number;
126
+ dueAmount: number;
127
+ qrPayload: string;
128
+ upiPhone: string;
129
+ showInWords: boolean;
130
+ showDueSection: boolean;
131
+ isPoSPrint: boolean;
132
+ }) {
133
+ const hasQr = !!firstValue(data.qrPayload);
134
+ const inWords = data.totalInWords || '-';
135
+ const termsText = firstValue(data.terms);
136
+ const leftStack: any[] = [
137
+
138
+ ];
139
+ if (data.showInWords) {
140
+ leftStack.push(
141
+ {
142
+ columns: [
143
+ { width: 'auto', text: 'In Words :', bold: true, fontSize: 9, color: '#111827' },
144
+ { width: '*', text: inWords, bold: true, fontSize: 9, color: '#111827' }
145
+ ],
146
+ columnGap: 6,
147
+ margin: [0, 2, 0, 4]
148
+ }
149
+ )
150
+ }
151
+ if (data.showDueSection && !data.isPoSPrint) {
152
+ const paidText = `Paid : Rs.${formatAmountFixed2(data.paidAmount)}`;
153
+ const dueText = `Due : Rs.${formatAmountFixed2(data.dueAmount)}`;
154
+ leftStack.push({
155
+ table: {
156
+ widths: ['*', '*'],
157
+ body: [[
158
+ { text: paidText, fontSize: 8, color: '#111827', margin: [4, 2, 4, 2], alignment: 'left' },
159
+ { text: dueText, fontSize: 8, color: '#111827', margin: [4, 2, 4, 2], alignment: 'right' }
160
+ ]]
161
+ },
162
+ layout: {
163
+ hLineWidth: () => 0.5,
164
+ vLineWidth: () => 0.5,
165
+ hLineColor: () => '#d3d3d3',
166
+ vLineColor: () => '#d3d3d3'
167
+ },
168
+ margin: [0, 0, 0, 6]
169
+ });
170
+ }
171
+
172
+ if (data.isPoSPrint) {
173
+ leftStack.push({
174
+ columns: [
175
+ {
176
+ width: '60%',
177
+ stack: [
178
+ { text: '* Goods once sold will not be taken back or exchanged', fontSize: 6, color: '#111827' },
179
+ { text: '* PLEASE GET YOUR MEDICINES CHECKED BY YOUR DOCTOR BEFORE USE', fontSize: 6, color: '#111827' }
180
+ ],
181
+ margin: [5, 0, 0, 6],
182
+ lineHeight: 1.1
183
+ },
184
+ {
185
+ width: '40%',
186
+ text: `For ${data.companyName || ''}`.trim(),
187
+ fontSize: 9,
188
+ bold: true,
189
+ color: '#111827',
190
+ alignment: 'right'
191
+ }
192
+ ],
193
+ columnGap: 6,
194
+ margin: [0, 2, 0, 0]
195
+ });
196
+ }
197
+
198
+
199
+ if (termsText) {
200
+ leftStack.push({
201
+ text: `\u2022 ${termsText}`,
202
+ fontSize: 8,
203
+ color: '#111827',
204
+ lineHeight: 1.1
205
+ });
206
+ }
207
+ const leftColumn = {
208
+ width: hasQr ? '74%' : '*',
209
+ stack: leftStack
210
+ };
211
+
212
+ const columns: any[] = [leftColumn];
213
+ if (hasQr) {
214
+ columns.push({
215
+ width: '26%',
216
+ stack: [
217
+ {
218
+ qr: data.qrPayload,
219
+ fit: 95,
220
+ alignment: 'right'
221
+ },
222
+ {
223
+ text: 'Scan To Pay',
224
+ fontSize: 8,
225
+ bold: true,
226
+ alignment: 'right',
227
+ margin: [0, 2, 0, 0]
228
+ },
229
+ ...(firstValue(data.upiPhone) ? [{
230
+ text: `UPIPhone: ${data.upiPhone}`,
231
+ fontSize: 8,
232
+ bold: true,
233
+ alignment: 'right',
234
+ margin: [0, 2, 0, 0]
235
+ }] : [])
236
+ ]
237
+ });
238
+ }
239
+
240
+ return {
241
+ columns,
242
+ columnGap: hasQr ? 12 : 0,
243
+ margin: [0, 0, 0, 10]
244
+ };
245
+ }
246
+
247
+ export function buildSignatureSection(PrintConfig: any, invoiceData: any, availableWidth: number) {
248
+ const headerData = normalizeHeaderData(PrintConfig?.headerData ?? {});
249
+ const isPoSPrint = isTruthy(PrintConfig?.IsPoSPrint ?? PrintConfig?.isPoSPrint);
250
+ const companyName = firstValue(
251
+ headerData?.organization?.cName,
252
+ invoiceData?.Entity?.CName,
253
+ invoiceData?.Entity?.Name,
254
+ invoiceData?.CName
255
+ );
256
+ const withPass = !!(PrintConfig?.withPass || invoiceData?.withPass || invoiceData?.WithPass);
257
+ if (isPoSPrint) {
258
+ return [];
259
+ }
260
+ const signatureRows: any[] = [
261
+ {
262
+ columns: [
263
+ { width: '*', text: '' },
264
+ { width: '*', text: `For ${companyName || ''}`.trim(), fontSize: 9, bold: true, color: '#111827', alignment: 'right' }
265
+ ],
266
+ margin: [0, 4, 0, 0]
267
+ }
268
+ ];
269
+
270
+ if (!isPoSPrint) {
271
+ signatureRows.push({
272
+ text: '',
273
+ margin: [0, 10, 0, 0]
274
+ });
275
+ signatureRows.push({
276
+ columns: [
277
+ { width: '*', text: 'Customer Signature', fontSize: 9, color: '#111827', alignment: 'left' },
278
+ { width: '*', text: 'Authorised Signatory', fontSize: 9, color: '#111827', alignment: 'right' }
279
+ ],
280
+ margin: [0, 0, 0, 0]
281
+ });
282
+ }
283
+
284
+ if (!withPass) {
285
+ return signatureRows;
286
+ }
287
+
288
+ return [...signatureRows, ...buildGatePassSection(companyName, invoiceData, availableWidth)];
289
+ }
290
+
291
+ function buildGatePassSection(companyName: string, invoiceData: any, availableWidth: number) {
292
+ const customerName = firstValue(
293
+ invoiceData?.Customer?.Name,
294
+ invoiceData?.Cust?.Name,
295
+ invoiceData?.BillTo?.Name,
296
+ invoiceData?.CustomerName
297
+ );
298
+ const serviceAdvisor = firstValue(
299
+ invoiceData?.Name,
300
+ invoiceData?.ServiceAdvisor,
301
+ invoiceData?.AdvisorName,
302
+ invoiceData?.SAName
303
+ );
304
+ const chassisNo = firstValue(
305
+ invoiceData?.Prod?.CIN,
306
+ invoiceData?.Prod?.ChassisNo,
307
+ invoiceData?.Product?.VIN,
308
+ invoiceData?.Vehicle?.VIN
309
+ );
310
+ const regnNo = firstValue(
311
+ invoiceData?.Prod?.RegnNo,
312
+ invoiceData?.Product?.RegNo,
313
+ invoiceData?.Veh?.RegNo,
314
+ invoiceData?.Vehicle?.RegNo,
315
+ invoiceData?.VehicleNo,
316
+ invoiceData?.VehNo
317
+ );
318
+ const vehicleModel = firstValue(
319
+ invoiceData?.Prod?.Model,
320
+ invoiceData?.Product?.Model,
321
+ invoiceData?.Vehicle?.Model
322
+ );
323
+ const gatePassDate = MyDate.ConvertUTCDateToReadable(MyDate.GetDateTimeNowInUTC(invoiceData?.Entity?.User?.TZ))
324
+
325
+ const dividerLine = {
326
+ canvas: [
327
+ { type: 'line', x1: 0, y1: 0, x2: Math.max(1, availableWidth), y2: 0, lineWidth: 1, lineColor: '#1f2937' }
328
+ ],
329
+ margin: [0, 5, 0, 5]
330
+ };
331
+
332
+ return [
333
+ {
334
+ canvas: [
335
+ { type: 'line', x1: 0, y1: 0, x2: 555, y2: 0, lineWidth: 0.8, lineColor: '#374151' }
336
+ ],
337
+ margin: [0, 10, 0, 5]
338
+ },
339
+ {
340
+ columns: [
341
+ { width: '*', text: '' },
342
+ { width: 'auto', text: 'Gate Pass', bold: true, fontSize: 10, alignment: 'center' },
343
+ { width: '*', text: `Date: ${gatePassDate}`, fontSize: 9, alignment: 'right' }
344
+ ],
345
+ margin: [0, 0, 0, 4]
346
+ },
347
+ {
348
+ text: companyName || '-',
349
+ alignment: 'center',
350
+ bold: true,
351
+ fontSize: 11,
352
+ margin: [0, 0, 0, 6]
353
+ },
354
+ {
355
+ columns: [
356
+ {
357
+ width: '50%',
358
+ table: {
359
+ widths: ['auto', 8, '*'],
360
+ body: [
361
+ [
362
+ { text: 'Customer Name', fontSize: 8, bold: true },
363
+ { text: ':', fontSize: 8, bold: true, alignment: 'center' },
364
+ { text: customerName || '-', fontSize: 8 }
365
+ ],
366
+ [
367
+ { text: 'Service Advisor', fontSize: 8, bold: true },
368
+ { text: ':', fontSize: 8, bold: true, alignment: 'center' },
369
+ { text: serviceAdvisor || '-', fontSize: 8 }
370
+ ]
371
+ ]
372
+ },
373
+ layout: 'noBorders'
374
+ },
375
+ {
376
+ width: '50%',
377
+ table: {
378
+ widths: ['auto', 8, '*'],
379
+ body: [
380
+ [
381
+ { text: 'Chassis No', fontSize: 8, bold: true },
382
+ { text: ':', fontSize: 8, bold: true, alignment: 'center' },
383
+ { text: chassisNo || '-', fontSize: 8 }
384
+ ],
385
+ [
386
+ { text: 'Regn. No', fontSize: 8, bold: true },
387
+ { text: ':', fontSize: 8, bold: true, alignment: 'center' },
388
+ { text: regnNo || '-', fontSize: 8 }
389
+ ],
390
+ [
391
+ { text: 'Vehicle Model', fontSize: 8, bold: true },
392
+ { text: ':', fontSize: 8, bold: true, alignment: 'center' },
393
+ { text: vehicleModel || '-', fontSize: 8 }
394
+ ]
395
+ ]
396
+ },
397
+ layout: 'noBorders'
398
+ }
399
+ ],
400
+ columnGap: 12,
401
+ margin: [0, 0, 0, 0]
402
+ },
403
+ {
404
+ text: 'Vehicle has been received from workshop and work done as per my satisfaction.',
405
+ fontSize: 7,
406
+ color: '#111827',
407
+ margin: [0, 8, 0, 10]
408
+ },
409
+ {
410
+ columns: [
411
+ { width: '*', text: 'Customer Signature', fontSize: 8, color: '#111827', alignment: 'left' },
412
+ { width: '*', text: 'Authorised Signatory', fontSize: 8, color: '#111827', alignment: 'right' }
413
+ ],
414
+ margin: [0, 0, 0, 0]
415
+ }
416
+ ];
417
+ }
418
+
419
+ // function formatGatePassDate(value: string) {
420
+ // const raw = firstValue(value);
421
+ // if (!raw) {
422
+ // return formatAsDDMMYYYY(new Date());
423
+ // }
424
+ // const parsed = new Date(raw);
425
+ // if (Number.isNaN(parsed.getTime())) {
426
+ // return raw;
427
+ // }
428
+ // return formatAsDDMMYYYY(parsed);
429
+ // }
430
+
431
+ // function formatAsDDMMYYYY(dateValue: Date) {
432
+ // const day = leftPadWithZero(dateValue.getDate());
433
+ // const month = leftPadWithZero(dateValue.getMonth() + 1);
434
+ // const year = dateValue.getFullYear();
435
+ // return `${day}/${month}/${year}`;
436
+ // }
437
+
438
+ // function leftPadWithZero(value: number) {
439
+ // const text = String(value);
440
+ // return text.length >= 2 ? text : `0${text}`;
441
+ // }
442
+
443
+ function buildSimpleTextCardStack(title: string, value: string) {
444
+ return [
445
+ { text: title, bold: true, fontSize: 9, color: '#374151', margin: [0, 0, 0, 4] },
446
+ {
447
+ text: value || '-',
448
+ fontSize: 8,
449
+ color: '#111827',
450
+ lineHeight: 1.1
451
+ }
452
+ ];
453
+ }
454
+
455
+ function buildInfoCardStack(title: string | null, lines: Array<{ label: string; value: string }>, options: { rightAlign?: boolean } = {}) {
456
+ const body = Array.isArray(lines) ? lines : [];
457
+ const isRightAlign = !!options.rightAlign;
458
+ const heading = firstValue(title);
459
+ return [
460
+ ...(heading ? [{
461
+ text: heading,
462
+ bold: true,
463
+ fontSize: 9,
464
+ color: '#374151',
465
+ margin: [0, 0, 0, 4],
466
+ alignment: isRightAlign ? 'right' : 'left'
467
+ }] : []),
468
+ {
469
+ table: {
470
+ widths: isRightAlign ? ['*', 6, 'auto'] : ['auto', 6, '*'],
471
+ body: (body.length > 0 ? body : [{ label: '', value: '-' }]).map((line: any) => {
472
+ const displayValue = hasDisplayValue(line?.value) ? String(line.value) : '-';
473
+ return [
474
+ { text: line.label || '', bold: true, fontSize: 8, color: '#111827', alignment: isRightAlign ? 'right' : 'left' },
475
+ { text: ':', bold: true, fontSize: 8, color: '#111827', alignment: 'center' },
476
+ { text: displayValue, fontSize: 8, color: '#111827', alignment: isRightAlign ? 'right' : 'left' }
477
+ ];
478
+ })
479
+ },
480
+ layout: 'noBorders'
481
+ }
482
+ ];
483
+ }
484
+
485
+ function buildTaxSummaryTableStack(
486
+ title: string | null,
487
+ rows: Array<{ taxRate: string; taxableAmount: string; cgstAmount: string; sgstAmount: string; igstAmount: string }>,
488
+ sType: string = ''
489
+ ) {
490
+ const isInter = sType === 'Inter';
491
+ const normalizedRows = Array.isArray(rows) ? rows : [];
492
+ const tableRows = normalizedRows.length > 0
493
+ ? normalizedRows.map((row: any) => (
494
+ isInter
495
+ ? [
496
+ { text: row.taxRate || '-', fontSize: 7, color: '#111827' },
497
+ { text: row.taxableAmount || '-', fontSize: 7, color: '#111827', alignment: 'right' },
498
+ { text: row.igstAmount || '-', fontSize: 7, color: '#111827', alignment: 'right' }
499
+ ]
500
+ : [
501
+ { text: row.taxRate || '-', fontSize: 7, color: '#111827' },
502
+ { text: row.taxableAmount || '-', fontSize: 7, color: '#111827', alignment: 'right' },
503
+ { text: row.cgstAmount || '-', fontSize: 7, color: '#111827', alignment: 'right' },
504
+ { text: row.sgstAmount || '-', fontSize: 7, color: '#111827', alignment: 'right' }
505
+ ]
506
+ ))
507
+ : [
508
+ isInter
509
+ ? [
510
+ { text: '-', fontSize: 7, color: '#111827' },
511
+ { text: '-', fontSize: 7, color: '#111827', alignment: 'right' },
512
+ { text: '-', fontSize: 7, color: '#111827', alignment: 'right' }
513
+ ]
514
+ : [
515
+ { text: '-', fontSize: 7, color: '#111827' },
516
+ { text: '-', fontSize: 7, color: '#111827', alignment: 'right' },
517
+ { text: '-', fontSize: 7, color: '#111827', alignment: 'right' },
518
+ { text: '-', fontSize: 7, color: '#111827', alignment: 'right' }
519
+ ]
520
+ ];
521
+
522
+ return [
523
+ // { text: title, bold: true, fontSize: 9, color: '#374151', margin: [0, 0, 0, 4] },
524
+ {
525
+ table: {
526
+ headerRows: 0,
527
+ widths: isInter ? ['auto', '*', '*'] : ['auto', '*', '*', '*'],
528
+ body: [
529
+ isInter
530
+ ? [
531
+ { text: 'Tax Rate', bold: true, fontSize: 7, fillColor: '#eeeeee' },
532
+ { text: 'Taxable Amount', bold: true, fontSize: 7, fillColor: '#eeeeee', alignment: 'right' },
533
+ { text: 'IGST(Rs)', bold: true, fontSize: 7, fillColor: '#eeeeee', alignment: 'right' }
534
+ ]
535
+ : [
536
+ { text: 'Tax Rate', bold: true, fontSize: 7, fillColor: '#eeeeee' },
537
+ { text: 'Taxable Amount', bold: true, fontSize: 7, fillColor: '#eeeeee', alignment: 'right' },
538
+ { text: 'CGST(Rs)', bold: true, fontSize: 7, fillColor: '#eeeeee', alignment: 'right' },
539
+ { text: 'SGST(Rs)', bold: true, fontSize: 7, fillColor: '#eeeeee', alignment: 'right' }
540
+ ],
541
+ ...tableRows
542
+ ]
543
+ },
544
+ layout: {
545
+ hLineWidth: (lineIndex: number) => lineIndex === 1 ? 0.5 : 0,
546
+ vLineWidth: () => 0,
547
+ hLineColor: () => '#d3d3d3',
548
+ paddingLeft: () => 4,
549
+ paddingRight: () => 4,
550
+ paddingTop: () => 3,
551
+ paddingBottom: () => 3
552
+ }
553
+ }
554
+ ];
555
+ }
556
+
557
+ function resolveTaxSummary(invoiceData: any, shouldShowTaxSummary: boolean) {
558
+ if (!shouldShowTaxSummary) {
559
+ return {
560
+ rows: [],
561
+ totalTax: 0,
562
+ hasData: false
563
+ };
564
+ }
565
+
566
+ const sourceRows = Array.isArray(invoiceData?.TaxSummary) ? invoiceData.TaxSummary : [];
567
+ const rows = sourceRows.map((entry: any) => {
568
+ const taxRate = firstValue(
569
+ entry?.Tax,
570
+ entry?.TaxRate,
571
+ entry?.CombinedTaxPercentage,
572
+ entry?.Perc,
573
+ entry?.Percentage
574
+ );
575
+ const taxable = readNumericValue(entry, ['TaxableAmount', 'TotalTaxableAmount', 'TaxableValue', 'Amount']);
576
+ const cgst = readNumericValue(entry, ['CGSTAmount', 'CGSTAmt', 'CGST']);
577
+ const sgst = readNumericValue(entry, ['SGSTAmount', 'SGSTAmt', 'SGST', 'UGSTAmount', 'UGSTAmt', 'UGST']);
578
+ const igst = readNumericValue(entry, ['IGSTAmount', 'IGSTAmt', 'IGST']);
579
+
580
+ return {
581
+ taxRate: formatTaxRate(taxRate),
582
+ taxableAmount: formatAmount(taxable),
583
+ cgstAmount: formatAmount(cgst),
584
+ sgstAmount: formatAmount(sgst),
585
+ igstAmount: formatAmount(igst),
586
+ totalTaxAmount: cgst + sgst + igst
587
+ };
588
+ });
589
+
590
+ const totalTax = rows.reduce((sum: number, row: any) => sum + (row.totalTaxAmount || 0), 0);
591
+ return {
592
+ rows,
593
+ totalTax,
594
+ hasData: rows.length > 0
595
+ };
596
+ }
597
+
598
+ function resolveShowTaxSummary(invoiceData: any, printConfigData: any = {}) {
599
+ const value = firstValue(
600
+ printConfigData?.ShowTaxSummary,
601
+ invoiceData?.ShowTaxSummary
602
+ );
603
+ return isTruthy(value);
604
+ }
605
+
606
+ function resolveBankDetails(invoiceData: any) {
607
+ const bank = invoiceData?.Entity?.Bank
608
+ || invoiceData?.Entity?.BankDetails
609
+ || invoiceData?.Bank
610
+ || invoiceData?.BankDetails
611
+ || {};
612
+
613
+ const lines = [
614
+ { label: 'Bank', value: firstValue(bank?.Name, bank?.BankName, bank?.BName) },
615
+ { label: 'A/C No', value: firstValue(bank?.ACNo, bank?.AccountNo, bank?.AccNo) },
616
+ { label: 'A/C Holder Name', value: firstValue(bank?.ACName, bank?.AccountHolderName, bank?.AccHolderName, bank?.AccHolder) },
617
+ { label: 'IFSC', value: firstValue(bank?.IFSC, bank?.Ifsc) },
618
+ { label: 'Branch', value: firstValue(bank?.Branch, bank?.Bran) },
619
+ // { label: 'UPI', value: firstValue(bank?.UPI, bank?.Upi) }
620
+ ].filter((line: any) => !!line.value);
621
+
622
+ return {
623
+ lines,
624
+ hasData: lines.length > 0
625
+ };
626
+ }
627
+
628
+ function resolveShowBankDetails(invoiceData: any, printConfigData: any = {}) {
629
+ const value = firstValue(
630
+ printConfigData?.ShowBankDetails,
631
+ invoiceData?.ShowBankDetails,
632
+ invoiceData?.Entity?.ShowBankDetails
633
+ );
634
+ return isTruthy(value);
635
+ }
636
+
637
+ function shouldShowDueSection(printConfigData: any = {}) {
638
+ const type = firstValue(printConfigData?.Type);
639
+ if (!type) {
640
+ return false;
641
+ }
642
+ const normalizedType = String(type).trim().toLowerCase();
643
+ return normalizedType === 'invoice' || normalizedType === 'bill';
644
+ }
645
+
646
+ function isTruthy(value: any) {
647
+ if (typeof value === 'boolean') {
648
+ return value;
649
+ }
650
+ if (typeof value === 'number') {
651
+ return value !== 0;
652
+ }
653
+ if (typeof value === 'string') {
654
+ const normalized = value.trim().toLowerCase();
655
+ return normalized === 'true' || normalized === '1' || normalized === 'yes';
656
+ }
657
+ return false;
658
+ }
659
+
660
+ function hasDisplayValue(value: any) {
661
+ if (value === undefined || value === null) {
662
+ return false;
663
+ }
664
+ if (typeof value === 'number') {
665
+ return Number.isFinite(value);
666
+ }
667
+ if (typeof value === 'string') {
668
+ return value.trim().length > 0;
669
+ }
670
+ return true;
671
+ }
672
+
673
+ function resolveTotals(invoiceData: any, totalTax: number, printConfigData: any = {}) {
674
+ const subtotal = readNumericValue(invoiceData, ['SIndTotal', 'STotal', 'SubTotal', 'SubTot', 'TaxableAmount', 'TaxableValue']);
675
+ const isPoSPrint = isTruthy(printConfigData?.IsPoSPrint ?? printConfigData?.isPoSPrint);
676
+ const showDetailedDisc = isTruthy(firstValue(printConfigData?.ShowDetailedDisc));
677
+ const itemsDiscount = parseNumber(firstValue(invoiceData?.PDisc));
678
+ const servicesDiscount = parseNumber(firstValue(invoiceData?.LDisc));
679
+ const overallDiscount = parseNumber(firstValue(invoiceData?.Disc, invoiceData?.Discount, invoiceData?.TotDisc));
680
+ const overalItemsDiscount = parseNumber(firstValue(invoiceData?.CustPartsDiscTotal || invoiceData?.PartsDiscTotal));
681
+ const overalServicesDiscount = parseNumber(firstValue(invoiceData?.CustLaborDiscTotal || invoiceData?.ServiceDiscTotal));
682
+ const hasDetailedDiscSource =
683
+ firstValue(invoiceData?.PDisc) !== ''
684
+ || firstValue(invoiceData?.LDisc) !== ''
685
+ || firstValue(invoiceData?.Disc, invoiceData?.Discount, invoiceData?.TotDisc) !== '';
686
+ const discount = hasDetailedDiscSource
687
+ ? itemsDiscount + servicesDiscount + overallDiscount
688
+ : readNumericValue(invoiceData, ['Disc', 'Discount', 'TotDisc']);
689
+ const roundOff = readNumericValue(invoiceData, ['Round', 'RoundOff']);
690
+ const taxFromInvoice = readNumericValue(invoiceData, ['TotalTax', 'TaxTotal', 'TaxAmt', 'GSTTotal', 'CustItemITax']);
691
+ const totalTaxValue = taxFromInvoice !== 0 ? taxFromInvoice : totalTax;
692
+ const returnTotal = firstValue(invoiceData?.RetTotal);
693
+ const finalTotalRaw = firstValue(invoiceData?.FinalTotal, invoiceData?.Total, invoiceData?.GrandTotal, invoiceData?.NetTotal);
694
+ const finalTotal = parseNumber(finalTotalRaw);
695
+ const paidAmount = readNumericValue(invoiceData, ['Paid', 'PaidAmount', 'PaidAmt', 'ReceivedAmount', 'RecAmt']);
696
+ let totalBeforeRound = readNumericValue(invoiceData, ['TotalBeforeRound', 'BeforeRoundTotal', 'PreRoundTotal']);
697
+ if (totalBeforeRound === 0) {
698
+ if (finalTotalRaw) {
699
+ totalBeforeRound = finalTotal - roundOff;
700
+ } else if (subtotal !== 0 || discount !== 0 || totalTaxValue !== 0) {
701
+ totalBeforeRound = subtotal - discount + totalTaxValue;
702
+ } else {
703
+ totalBeforeRound = finalTotal;
704
+ }
705
+ }
706
+ const resolvedFinalTotal = finalTotalRaw ? finalTotal : totalBeforeRound + roundOff;
707
+ const dueFromInvoice = readNumericValue(invoiceData, ['Due', 'DueAmount', 'DueAmt', 'Balance', 'BalAmt']);
708
+ const dueAmount = dueFromInvoice !== 0 ? dueFromInvoice : Math.max(0, resolvedFinalTotal - paidAmount);
709
+
710
+ const discountLines = (showDetailedDisc
711
+ ? [
712
+ { label: 'Items Discount', amount: itemsDiscount },
713
+ { label: 'Services Discount', amount: servicesDiscount },
714
+ { label: 'Overall Discount', amount: overallDiscount }
715
+ ]
716
+ : [
717
+ { label: 'Discount', amount: Add(overalItemsDiscount, overalServicesDiscount) }
718
+ ])
719
+ .filter((line: any) => parseNumber(line?.amount) !== 0);
720
+
721
+ const totalLines = [
722
+ { label: 'SubTotal', amount: subtotal },
723
+ ...discountLines,
724
+ { label: 'Total Tax', amount: totalTaxValue },
725
+ { label: 'Return Total', amount: returnTotal },
726
+ { label: 'Total', amount: totalBeforeRound },
727
+ { label: 'Rounding', amount: roundOff },
728
+ ...(roundOff !== 0 ? [{ label: 'Final Total', amount: resolvedFinalTotal }] : []),
729
+ ...(isPoSPrint ? [{ label: 'Due', amount: dueFromInvoice }] : [])
730
+ ];
731
+
732
+ const lines = totalLines
733
+ .filter((line: any) => line?.label === 'Due' || parseNumber(line?.amount) !== 0)
734
+ .map((line: any) => ({ label: line.label, value: formatAmountFixed2(parseNumber(line?.amount)) }));
735
+
736
+ const hasData = lines.some((line: any) => hasDisplayValue(line?.value));
737
+ return {
738
+ lines,
739
+ hasData
740
+ };
741
+ }
742
+
743
+ function resolveDueInfo(invoiceData: any, totals: any) {
744
+ const paid = readNumericValue(invoiceData, ['Paid', 'PaidAmount', 'PaidAmt', 'ReceivedAmount', 'RecAmt']);
745
+ const dueFromInvoice = readNumericValue(invoiceData, ['Due', 'DueAmount', 'DueAmt', 'Balance', 'BalAmt']);
746
+ const finalTotal = parseNumber(firstValue(invoiceData?.Total, invoiceData?.FinalTotal, invoiceData?.GrandTotal, invoiceData?.NetTotal));
747
+ const due = dueFromInvoice !== 0 ? dueFromInvoice : Math.max(0, finalTotal - paid);
748
+ return {
749
+ paid,
750
+ due,
751
+ hasData: paid !== 0 || due !== 0 || !!totals?.hasData
752
+ };
753
+ }
754
+
755
+ function resolveQrPayload(invoiceData: any, printConfigData: any = {}) {
756
+ if (!isTruthy(printConfigData?.ShowPayQrCode)) {
757
+ return '';
758
+ }
759
+
760
+ return firstValue(
761
+ invoiceData?.Entity?.UPI,
762
+ invoiceData?.QRText,
763
+ invoiceData?.QrText,
764
+ invoiceData?.QRCode,
765
+ invoiceData?.QRData,
766
+ invoiceData?.UPIId,
767
+ invoiceData?.Bank?.UPI,
768
+ invoiceData?.BankDetails?.UPI
769
+ );
770
+ }
771
+
772
+ function resolveUpiPhone(invoiceData: any) {
773
+ return firstValue(
774
+ invoiceData?.UPIPhone,
775
+ invoiceData?.Entity?.UPIPhone,
776
+ invoiceData?.Bank?.UPIPhone,
777
+ invoiceData?.BankDetails?.UPIPhone,
778
+ invoiceData?.Entity?.Bank?.UPIPhone,
779
+ invoiceData?.Entity?.BankDetails?.UPIPhone
780
+ );
781
+ }
782
+
783
+ function formatAmountFixed2(value: number) {
784
+ if (!Number.isFinite(value)) {
785
+ return '0.00';
786
+ }
787
+ return value.toFixed(2);
788
+ }
789
+
790
+ function parseNumber(value: any) {
791
+ if (value === undefined || value === null) {
792
+ return 0;
793
+ }
794
+ if (typeof value === 'number') {
795
+ return Number.isFinite(value) ? value : 0;
796
+ }
797
+
798
+ const raw = String(value).trim();
799
+ if (!raw) {
800
+ return 0;
801
+ }
802
+
803
+ const cleaned = raw.replace(/\s/g, '').replace(/[^0-9,.-]/g, '');
804
+ if (!cleaned) {
805
+ return 0;
806
+ }
807
+
808
+ const commaCount = (cleaned.match(/,/g) || []).length;
809
+ const dotCount = (cleaned.match(/\./g) || []).length;
810
+
811
+ let normalized = cleaned;
812
+ if (commaCount > 0 && dotCount > 0) {
813
+ const lastCommaIndex = cleaned.lastIndexOf(',');
814
+ const lastDotIndex = cleaned.lastIndexOf('.');
815
+ const decimalSeparator = lastCommaIndex > lastDotIndex ? ',' : '.';
816
+ if (decimalSeparator === ',') {
817
+ normalized = cleaned.replace(/\./g, '').replace(',', '.');
818
+ } else {
819
+ normalized = cleaned.replace(/,/g, '');
820
+ }
821
+ } else if (commaCount > 0) {
822
+ const isCommaDecimal = /^-?\d+,\d{1,2}$/.test(cleaned);
823
+ normalized = isCommaDecimal ? cleaned.replace(',', '.') : cleaned.replace(/,/g, '');
824
+ }
825
+
826
+ const numeric = Number(normalized);
827
+ return Number.isFinite(numeric) ? numeric : 0;
828
+ }
829
+
830
+ function formatTaxRate(value: string) {
831
+ const normalized = firstValue(value);
832
+ if (!normalized) {
833
+ return '-';
834
+ }
835
+ if (normalized.includes('%')) {
836
+ return normalized;
837
+ }
838
+ const numericValue = Number(normalized);
839
+ return Number.isFinite(numericValue) ? `${normalized}%` : normalized;
840
+ }
841
+
842
+ function resolveTotalInWords(invoiceData: any) {
843
+ const roundedTotal = parseNumber(firstValue(invoiceData?.CustRoundedTotal || invoiceData?.RoundedTotal));
844
+ if (roundedTotal > 0) {
845
+ return convertAmountToWordsINR(roundedTotal);
846
+ }
847
+ return firstValue(
848
+ invoiceData?.TotalInWords,
849
+ invoiceData?.AmtInWords,
850
+ invoiceData?.AmountInWords
851
+ );
852
+ }
853
+
854
+ function convertAmountToWordsINR(amount: number) {
855
+ if (!Number.isFinite(amount)) {
856
+ return '';
857
+ }
858
+ const absoluteAmount = Math.abs(amount);
859
+ const integerPart = Math.floor(absoluteAmount);
860
+ const decimalPart = Math.round((absoluteAmount - integerPart) * 100);
861
+
862
+ const rupeesInWords = numberToWordsIndian(integerPart);
863
+ const paiseInWords = decimalPart > 0 ? ` And ${numberToWordsIndian(decimalPart)} Paise` : '';
864
+ const signText = amount < 0 ? 'Minus ' : '';
865
+
866
+ return `${signText}${rupeesInWords} Rupee(s)${paiseInWords} Only`;
867
+ }
868
+
869
+ function numberToWordsIndian(num: number): string {
870
+ if (num === 0) {
871
+ return 'Zero';
872
+ }
873
+
874
+ const ones = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine',
875
+ 'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen',
876
+ 'Seventeen', 'Eighteen', 'Nineteen'];
877
+ const tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
878
+
879
+ const belowThousand = (n: number): string => {
880
+ let words = '';
881
+ if (n >= 100) {
882
+ words += `${ones[Math.floor(n / 100)]} Hundred`;
883
+ n %= 100;
884
+ if (n > 0) {
885
+ words += ' And ';
886
+ }
887
+ }
888
+ if (n >= 20) {
889
+ words += tens[Math.floor(n / 10)];
890
+ if (n % 10 > 0) {
891
+ words += ` ${ones[n % 10]}`;
892
+ }
893
+ } else if (n > 0) {
894
+ words += ones[n];
895
+ }
896
+ return words.trim();
897
+ };
898
+
899
+ const units = [
900
+ { value: 10000000, label: 'Crore' },
901
+ { value: 100000, label: 'Lakh' },
902
+ { value: 1000, label: 'Thousand' }
903
+ ];
904
+
905
+ let n = Math.floor(num);
906
+ const parts: string[] = [];
907
+
908
+ for (const unit of units) {
909
+ if (n >= unit.value) {
910
+ const unitCount = Math.floor(n / unit.value);
911
+ parts.push(`${belowThousand(unitCount)} ${unit.label}`.trim());
912
+ n %= unit.value;
913
+ }
914
+ }
915
+
916
+ if (n > 0) {
917
+ parts.push(belowThousand(n));
918
+ }
919
+
920
+ return parts.join(' ').replace(/\s+/g, ' ').trim();
921
+ }