@awadheshs109/billing 1.0.29 → 2.0.12

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.
package/dist/index.mjs CHANGED
@@ -77,13 +77,22 @@ var InvoiceCalculator = class {
77
77
  0
78
78
  );
79
79
  const discountAmount = subtotal * (discount / 100);
80
- const taxable = subtotal - discountAmount;
81
- const taxAmount = taxable * (tax / 100);
80
+ const taxableAmount = subtotal - discountAmount;
81
+ const taxAmount = taxableAmount * (tax / 100);
82
+ const total = taxableAmount + taxAmount;
82
83
  return {
83
- subtotal,
84
- discount: discountAmount,
85
- tax: taxAmount,
86
- total: taxable + taxAmount
84
+ subtotal: Number(
85
+ subtotal.toFixed(2)
86
+ ),
87
+ taxAmount: Number(
88
+ taxAmount.toFixed(2)
89
+ ),
90
+ discountAmount: Number(
91
+ discountAmount.toFixed(2)
92
+ ),
93
+ total: Number(
94
+ total.toFixed(2)
95
+ )
87
96
  };
88
97
  }
89
98
  };
@@ -91,7 +100,7 @@ var InvoiceCalculator = class {
91
100
  // src/core/billing.ts
92
101
  var Billing = class {
93
102
  static getVersion() {
94
- return "1.0.16";
103
+ return "2.0.1";
95
104
  }
96
105
  };
97
106
  Billing.calculateGST = calculateGST;
@@ -100,6 +109,14 @@ Billing.calculateDiscount = calculateDiscount;
100
109
  Billing.formatCurrency = formatCurrency;
101
110
  Billing.InvoiceCalculator = InvoiceCalculator;
102
111
 
112
+ // src/constants/tax-rates.ts
113
+ var TAX_RATES = {
114
+ GST_5: 5,
115
+ GST_12: 12,
116
+ GST_18: 18,
117
+ GST_28: 28
118
+ };
119
+
103
120
  // src/utils/date.ts
104
121
  function formatDate(date = /* @__PURE__ */ new Date(), locale = "en-IN") {
105
122
  return new Intl.DateTimeFormat(locale, {
@@ -123,135 +140,891 @@ function isValidGST(gst) {
123
140
  return /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/i.test(gst);
124
141
  }
125
142
 
126
- // src/constants/tax-rates.ts
127
- var TAX_RATES = {
128
- GST_5: 5,
129
- GST_12: 12,
130
- GST_18: 18,
131
- GST_28: 28
143
+ // src/config/default-invoice-config.ts
144
+ var defaultInvoiceConfig = {
145
+ currency: "INR",
146
+ tax: 0,
147
+ discount: 0,
148
+ company: {
149
+ name: "",
150
+ address: "",
151
+ phone: ""
152
+ },
153
+ customer: {
154
+ name: "",
155
+ email: ""
156
+ },
157
+ features: {
158
+ showSellerGST: true,
159
+ showBuyerGST: true,
160
+ showPAN: true,
161
+ showTransport: true,
162
+ showEWay: true,
163
+ showBankDetails: true,
164
+ showTerms: true,
165
+ showSignature: true,
166
+ showSoftwareCredit: true,
167
+ showBranchDetails: true,
168
+ showPaymentDetails: true,
169
+ showPaymentTransactions: true,
170
+ showAmountWords: true
171
+ },
172
+ branding: {
173
+ showSoftwareCredit: true,
174
+ softwareCreditText: "Generated using Zentris Billing",
175
+ logoText: "ZENTRIS",
176
+ logoSubText: "Billing Engine"
177
+ },
178
+ theme: {
179
+ primaryColor: "#221b67",
180
+ accentColor: "#009688"
181
+ }
132
182
  };
133
183
 
134
- // src/exporters/pdf-exporter.ts
135
- import { jsPDF } from "jspdf";
136
- var PdfExporter = class {
137
- static generate(invoice) {
138
- const pdf = new jsPDF();
139
- pdf.setFontSize(20);
140
- pdf.text(
141
- "INVOICE",
142
- 20,
143
- 20
144
- );
145
- pdf.text(
146
- `Invoice: ${invoice.invoiceNo}`,
147
- 20,
148
- 40
149
- );
150
- pdf.text(
151
- `Customer: ${invoice.customer.name}`,
152
- 20,
153
- 50
154
- );
155
- let y = 70;
156
- invoice.items.forEach((item) => {
157
- pdf.text(
158
- `${item.description}
159
- \u20B9${item.rate}`,
160
- 20,
161
- y
162
- );
163
- y += 10;
164
- });
165
- return pdf.output("blob");
184
+ // src/normalizers/invoice-normalizer.ts
185
+ var InvoiceNormalizer = class {
186
+ static normalize(invoice) {
187
+ return {
188
+ ...defaultInvoiceConfig,
189
+ ...invoice,
190
+ items: invoice.items || [],
191
+ company: {
192
+ name: invoice.company?.name || defaultInvoiceConfig.company?.name || "",
193
+ address: invoice.company?.address || defaultInvoiceConfig.company?.address || "",
194
+ phone: invoice.company?.phone || defaultInvoiceConfig.company?.phone || "",
195
+ email: invoice.company?.email,
196
+ gstNumber: invoice.company?.gstNumber,
197
+ panNumber: invoice.company?.panNumber,
198
+ website: invoice.company?.website,
199
+ bankDetails: invoice.company?.bankDetails,
200
+ branches: invoice.company?.branches || []
201
+ },
202
+ customer: {
203
+ name: invoice.customer?.name || defaultInvoiceConfig.customer?.name || "",
204
+ email: invoice.customer?.email || defaultInvoiceConfig.customer?.email || "",
205
+ phone: invoice.customer?.phone,
206
+ gstNumber: invoice.customer?.gstNumber,
207
+ address: invoice.customer?.address
208
+ },
209
+ features: {
210
+ ...defaultInvoiceConfig.features,
211
+ ...invoice.features
212
+ },
213
+ branding: {
214
+ ...defaultInvoiceConfig.branding,
215
+ ...invoice.branding
216
+ },
217
+ theme: {
218
+ ...defaultInvoiceConfig.theme,
219
+ ...invoice.theme
220
+ },
221
+ payment: invoice.payment ? {
222
+ ...invoice.payment,
223
+ transactions: invoice.payment.transactions || []
224
+ } : void 0,
225
+ terms: invoice.terms || []
226
+ };
166
227
  }
167
228
  };
168
229
 
169
- // src/exporters/csv-exporter.ts
170
- var CsvExporter = class {
171
- static generate(invoice) {
172
- return [
173
- "Description,Quantity,Rate",
174
- ...invoice.items.map(
175
- (item) => `${item.description},
176
- ${item.quantity},
177
- ${item.rate}`
178
- )
179
- ].join("\n");
230
+ // src/renderers/invoice-renderer.ts
231
+ var InvoiceRenderer = class {
232
+ static renderHTML(invoice, summary, template) {
233
+ return template(
234
+ invoice,
235
+ summary
236
+ );
180
237
  }
181
238
  };
182
239
 
183
- // src/exporters/json-exporter.ts
184
- var JsonExporter = class {
240
+ // src/exporters/csv-exporter.ts
241
+ var CsvExporter = class {
185
242
  static generate(invoice) {
186
- return JSON.stringify(
187
- invoice,
188
- null,
189
- 2
243
+ const summary = InvoiceCalculator.summary(
244
+ invoice.items,
245
+ invoice.tax || 0,
246
+ invoice.discount || 0
190
247
  );
248
+ const rows = [
249
+ `Invoice No,${invoice.invoiceNo}`,
250
+ `Date,${invoice.date}`,
251
+ `Customer,${invoice.customer.name}`,
252
+ `Payment Status,${invoice.payment?.status || "pending"}`,
253
+ "",
254
+ "Description,Quantity,Rate,Amount",
255
+ ...invoice.items.map(
256
+ (item) => `${item.description},${item.quantity},${item.rate},${item.quantity * item.rate}`
257
+ ),
258
+ "",
259
+ `Subtotal,,,${summary.subtotal}`,
260
+ `Tax Amount,,,${summary.taxAmount}`,
261
+ `Discount Amount,,,${summary.discountAmount}`,
262
+ `Grand Total,,,${summary.total}`
263
+ ];
264
+ return rows.join("\n");
191
265
  }
192
266
  };
193
267
 
194
268
  // src/templates/classic.template.ts
195
269
  function classicInvoiceTemplate(invoice, summary) {
270
+ const currency = invoice.currency || "INR";
271
+ const items = invoice.items.map(
272
+ (item, index) => `
273
+ <tr>
274
+ <td>
275
+ ${index + 1}
276
+ </td>
277
+ <td>
278
+ ${item.description}
279
+ </td>
280
+ <td>
281
+ ${item.quantity}
282
+ </td>
283
+ <td>
284
+ ${Billing.formatCurrency(item.rate, currency)}
285
+ </td>
286
+ <td>
287
+ ${Billing.formatCurrency(item.quantity * item.rate, currency)}
288
+ </td>
289
+ </tr>
290
+ `
291
+ ).join("");
196
292
  return `
197
- <html>
198
-
293
+ <!DOCTYPE html>
294
+ <html lang="en">
295
+ <head>
296
+ <meta charset="UTF-8" />
297
+ <meta
298
+ name="viewport"
299
+ content="width=device-width, initial-scale=1.0"
300
+ />
301
+ <title>
302
+ ${invoice.type || "INVOICE"}
303
+ </title>
304
+ <style>
305
+ * {
306
+ box-sizing: border-box;
307
+ }
308
+ body {
309
+ font-family: Arial, Helvetica, sans-serif;
310
+ background: #ffffff;
311
+ padding: 0;
312
+ margin: 0;
313
+ color: #222222;
314
+ -webkit-print-color-adjust: exact;
315
+ print-color-adjust: exact;
316
+ }
317
+ .receipt-container {
318
+ width: 100%;
319
+ max-width: 100%;
320
+ margin: auto;
321
+ background: #ffffff;
322
+ padding: 40px;
323
+ }
324
+ .top-header {
325
+ display: flex;
326
+ justify-content: space-between;
327
+ align-items: flex-start;
328
+ margin-bottom: 35px;
329
+ }
330
+ .company-name {
331
+ font-size: 28px;
332
+ font-weight: 700;
333
+ margin-bottom: 10px;
334
+ }
335
+ .company-address {
336
+ font-size: 13px;
337
+ line-height: 1.5;
338
+ }
339
+ .invoice-title {
340
+ font-size: 34px;
341
+ font-weight: 700;
342
+ letter-spacing: 1px;
343
+ }
344
+ .address-section {
345
+ display: grid;
346
+ grid-template-columns: 1fr 1fr 1fr;
347
+ gap: 25px;
348
+ margin-bottom: 30px;
349
+ }
350
+ .address-box h3 {
351
+ font-size: 16px;
352
+ margin-bottom: 8px;
353
+ }
354
+ .address-box p {
355
+ font-size: 13px;
356
+ line-height: 1.5;
357
+ }
358
+ .invoice-details td {
359
+ padding: 4px 0;
360
+ font-size: 13px;
361
+ }
362
+ .invoice-details td:first-child {
363
+ font-weight: 700;
364
+ padding-right: 10px;
365
+ }
366
+ .items-table {
367
+ width: 100%;
368
+ border-collapse: collapse;
369
+ margin-top: 15px;
370
+ }
371
+ .items-table th {
372
+ background: #f3f3f3;
373
+ padding: 10px;
374
+ border: 1px solid #cccccc;
375
+ font-size: 13px;
376
+ text-align: center;
377
+ }
378
+ .items-table td {
379
+ border: 1px solid #cccccc;
380
+ padding: 9px;
381
+ font-size: 12px;
382
+ line-height: 1.4;
383
+ word-break: break-word;
384
+ }
385
+ .items-table td:nth-child(1),
386
+ .items-table td:nth-child(3) {
387
+ text-align: center;
388
+ width: 60px;
389
+ }
390
+ .items-table td:nth-child(4),
391
+ .items-table td:nth-child(5) {
392
+ text-align: right;
393
+ width: 120px;
394
+ }
395
+ .total-wrapper {
396
+ display: flex;
397
+ justify-content: flex-end;
398
+ margin-top: 18px;
399
+ }
400
+ .total-box {
401
+ width: 320px;
402
+ }
403
+ .total-table td {
404
+ padding: 10px;
405
+ font-size: 14px;
406
+ }
407
+ .total-table td:last-child {
408
+ text-align: right;
409
+ }
410
+ .total-table tr:last-child td {
411
+ border: 1px solid #cccccc;
412
+ font-size: 24px;
413
+ font-weight: 700;
414
+ }
415
+ .notes {
416
+ margin-top: 35px;
417
+ }
418
+ .notes h3 {
419
+ margin-bottom: 10px;
420
+ font-size: 15px;
421
+ }
422
+ .notes p {
423
+ font-size: 12px;
424
+ line-height: 1.6;
425
+ }
426
+ .signature-section {
427
+ margin-top: 45px;
428
+ display: flex;
429
+ justify-content: flex-end;
430
+ }
431
+ .signature {
432
+ font-size: 34px;
433
+ font-family: cursive;
434
+ margin-bottom: 5px;
435
+ }
436
+ .signature-label {
437
+ border-top: 1px solid #222222;
438
+ padding-top: 5px;
439
+ font-size: 11px;
440
+ }
441
+ .footer {
442
+ margin-top: 40px;
443
+ text-align: center;
444
+ color: #777777;
445
+ font-size: 11px;
446
+ }
447
+ </style>
448
+ </head>
199
449
  <body>
200
-
201
- <div class="invoice">
202
-
203
- <h1>INVOICE</h1>
204
-
450
+ <div class="receipt-container">
451
+ <div class="top-header">
205
452
  <div>
206
- Invoice #: ${invoice.invoiceNo}
207
- Date:${invoice.date}
453
+ <div class="company-name">
454
+ ${invoice.company?.name || "Zentris Pvt Ltd"}
208
455
  </div>
209
-
210
- <h3>BILL TO</h3>
211
-
456
+ <div class="company-address">
212
457
  <p>
213
- ${invoice.customer.name}
214
- <br/>
215
- ${invoice.customer.address}
458
+ ${invoice.company?.address || "Mumbai, India"}
216
459
  </p>
217
-
460
+ <p>
461
+ ${invoice.company?.phone || "+91 9999999999"}
462
+ </p>
463
+ <p>
464
+ ${invoice.company?.email || "support@zentris.com"}
465
+ </p>
466
+ <p>
467
+ GSTIN:
468
+ ${invoice.company?.gstNumber || "27ABCDE1234F1Z5"}
469
+ </p>
470
+ </div>
471
+ </div>
472
+ <div class="invoice-title">
473
+ ${invoice.type || "INVOICE"}
474
+ </div>
475
+ </div>
476
+ <div class="address-section">
477
+ <div class="address-box">
478
+ <h3>Seller</h3>
479
+ <p>
480
+ ${invoice.company?.name || "Zentris Pvt Ltd"}
481
+ </p>
482
+ <p>
483
+ ${invoice.company?.address || "Mumbai"}
484
+ </p>
485
+ </div>
486
+ <div class="address-box">
487
+ <h3>Buyer</h3>
488
+ <p>
489
+ ${invoice.customer?.name || "Customer Name"}
490
+ </p>
491
+ <p>
492
+ ${invoice.customer?.company || ""}
493
+ </p>
494
+ <p>
495
+ ${invoice.customer?.address || "Customer Address"}
496
+ </p>
497
+ <p>
498
+ ${invoice.customer?.phone || ""}
499
+ </p>
500
+ </div>
501
+ <div class="invoice-details">
218
502
  <table>
219
-
220
503
  <tr>
504
+ <td>Invoice Number</td>
505
+ <td>${invoice.invoiceNo || "INV-001"}</td>
506
+ </tr>
507
+ <tr>
508
+ <td>Date</td>
509
+ <td>${invoice.date || (/* @__PURE__ */ new Date()).toLocaleDateString()}</td>
510
+ </tr>
511
+ <tr>
512
+ <td>Due Date</td>
513
+ <td>${invoice.dueDate || ""}</td>
514
+ </tr>
515
+ <tr>
516
+ <td>Payment Mode</td>
517
+ <td>${invoice.payment?.mode || "Bank Transfer"}</td>
518
+ </tr>
519
+ <tr>
520
+ <td>Status</td>
521
+ <td>${invoice.payment?.status || "Pending"}</td>
522
+ </tr>
523
+ </table>
524
+ </div>
525
+ </div>
526
+ <table class="items-table">
527
+ <thead>
528
+ <tr>
529
+ <th>Number</th>
221
530
  <th>Description</th>
531
+ <th>Qty</th>
532
+ <th>Rate</th>
222
533
  <th>Amount</th>
223
534
  </tr>
224
-
225
- ${invoice.items.map(
226
- (item) => `
535
+ </thead>
536
+ <tbody>
537
+ ${items}
538
+ </tbody>
539
+ </table>
540
+ <div class="total-wrapper">
541
+ <div class="total-box">
542
+ <table class="total-table">
227
543
  <tr>
228
- <td>${item.description}</td>
544
+ <td>Subtotal</td>
229
545
  <td>
230
- \u20B9${item.quantity * item.rate}
546
+ ${Billing.formatCurrency(summary.subtotal, currency)}
547
+ </td>
548
+ </tr>
549
+ <tr>
550
+ <td>Tax</td>
551
+ <td>
552
+ ${Billing.formatCurrency(summary.taxAmount, currency)}
553
+ </td>
554
+ </tr>
555
+ <tr>
556
+ <td>Discount</td>
557
+ <td>
558
+ ${Billing.formatCurrency(summary.discountAmount, currency)}
559
+ </td>
560
+ </tr>
561
+ <tr>
562
+ <td>Total</td>
563
+ <td>
564
+ ${Billing.formatCurrency(summary.total, currency)}
231
565
  </td>
232
566
  </tr>
233
- `
234
- ).join("")}
235
-
236
567
  </table>
237
-
238
- <div>
239
- Subtotal:
240
- \u20B9${summary.subtotal}
241
568
  </div>
242
-
243
- <div>
244
- Tax:
245
- \u20B9${summary.tax}
246
569
  </div>
570
+ <div class="notes">
571
+ <h3>Terms and Conditions</h3>
572
+ <p>
573
+ ${invoice.notes || "Payment due within 15 days. Thank you for your business."}
574
+ </p>
575
+ </div>
576
+ ${invoice.signature ? `
577
+ <div class="signature-section">
578
+ <div class="signature-box">
579
+ <div class="signature">
580
+ ${invoice.signature}
581
+ </div>
582
+ <div class="signature-label">
583
+ Authorized Signature
584
+ </div>
585
+ </div>
586
+ </div>
587
+ ` : ""}
588
+ <div class="footer">
589
+ Generated using Zentris Billing
590
+ </div>
591
+ </div>
592
+ </body>
593
+ </html>
594
+ `;
595
+ }
247
596
 
597
+ // src/templates/classic.template2.ts
598
+ function classicInvoiceTemplate2(invoice, summary) {
599
+ const currency = invoice.currency || "INR";
600
+ const items = invoice.items.map(
601
+ (item, index) => `
602
+ <tr>
603
+ <td class="center">
604
+ ${index + 1}
605
+ </td>
606
+ <td>
607
+ <b>${item.description}</b>
608
+ </td>
609
+ <td class="center">
610
+ ${item.hsn || "8302"}
611
+ </td>
612
+ <td class="center">
613
+ ${item.quantity}
614
+ </td>
615
+ <td class="right">
616
+ ${Billing.formatCurrency(item.rate, currency)}
617
+ </td>
618
+ <td class="right">
619
+ ${Billing.formatCurrency(item.quantity * item.rate, currency)}
620
+ </td>
621
+ </tr>
622
+ `
623
+ ).join("");
624
+ return `
625
+ <!DOCTYPE html>
626
+ <html lang="en">
627
+ <head>
628
+ <meta charset="UTF-8"/>
629
+ <meta
630
+ name="viewport"
631
+ content="width=device-width, initial-scale=1.0"
632
+ />
633
+ <title>
634
+ ${invoice.type || "TAX INVOICE"}
635
+ </title>
636
+ <style>
637
+ *{
638
+ margin:0;
639
+ padding:0;
640
+ box-sizing:border-box;
641
+ font-family:Arial, Helvetica, sans-serif;
642
+ }
643
+ body{
644
+ background:#efefef;
645
+ padding:10px;
646
+ }
647
+ .invoice{
648
+ width:100%;
649
+ max-width:1000px;
650
+ margin:auto;
651
+ background:#fff;
652
+ border:2px solid #333;
653
+ color:#111;
654
+ }
655
+ table{
656
+ width:100%;
657
+ border-collapse:collapse;
658
+ }
659
+ td,th{
660
+ border:1px solid #333;
661
+ padding:4px 6px;
662
+ vertical-align:top;
663
+ font-size:12px;
664
+ }
665
+ .header{
666
+ padding:15px;
667
+ border-bottom:2px solid #333;
668
+ }
669
+ .top-flex{
670
+ display:flex;
671
+ justify-content:space-between;
672
+ align-items:flex-start;
673
+ }
674
+ .company-name{
675
+ font-size:32px;
676
+ font-weight:900;
677
+ color:#221b67;
678
+ line-height:1;
679
+ }
680
+ .green-strip{
681
+ background:#009688;
682
+ color:#fff;
683
+ font-size:13px;
684
+ font-weight:bold;
685
+ padding:6px 10px;
686
+ margin-top:8px;
687
+ display:inline-block;
688
+ }
689
+ .address{
690
+ margin-top:10px;
691
+ font-size:13px;
692
+ line-height:1.5;
693
+ }
694
+ .right-top{
695
+ text-align:right;
696
+ font-size:12px;
697
+ line-height:1.5;
698
+ }
699
+ .logo{
700
+ margin-top:10px;
701
+ font-size:28px;
702
+ font-weight:900;
703
+ color:#2a2a75;
704
+ }
705
+ .logo-sub{
706
+ font-size:10px;
707
+ letter-spacing:2px;
708
+ color:#999;
709
+ }
710
+ .invoice-title{
711
+ text-align:center;
712
+ font-size:18px;
713
+ font-weight:900;
714
+ }
715
+ .bold{
716
+ font-weight:bold;
717
+ }
718
+ .center{
719
+ text-align:center;
720
+ }
721
+ .right{
722
+ text-align:right;
723
+ }
724
+ .product-table th{
725
+ background:#f5f5f5;
726
+ font-size:11px;
727
+ }
728
+ .product-table td{
729
+ height:28px;
730
+ font-size:11px;
731
+ }
732
+ .total-row td{
733
+ font-size:15px;
734
+ font-weight:bold;
735
+ }
736
+ .amount-words{
737
+ padding:8px 12px;
738
+ font-size:12px;
739
+ line-height:1.6;
740
+ border-top:1px solid #333;
741
+ border-bottom:1px solid #333;
742
+ }
743
+ .tax-table th{
744
+ background:#f5f5f5;
745
+ }
746
+ .bank-details{
747
+ padding:8px;
748
+ line-height:1.7;
749
+ font-size:12px;
750
+ }
751
+ .qr{
752
+ width:100px;
753
+ height:100px;
754
+ border:3px solid #000;
755
+ margin:auto;
756
+ display:flex;
757
+ justify-content:center;
758
+ align-items:center;
759
+ font-size:12px;
760
+ font-weight:bold;
761
+ }
762
+ .certified{
763
+ text-align:center;
764
+ padding-top:10px;
765
+ font-size:11px;
766
+ font-weight:bold;
767
+ }
768
+ .company-sign{
769
+ text-align:center;
770
+ font-size:16px;
771
+ font-weight:bold;
772
+ padding:15px 0;
773
+ }
774
+ .computer-note{
775
+ text-align:center;
776
+ margin-top:60px;
777
+ transform:rotate(-10deg);
778
+ font-size:11px;
779
+ color:#333;
780
+ }
781
+ .terms{
782
+ padding:10px;
783
+ line-height:1.5;
784
+ font-size:11px;
785
+ }
786
+ .signature{
787
+ height:70px;
788
+ padding:10px;
789
+ font-weight:bold;
790
+ }
791
+ .footer{
792
+ padding:10px 0;
793
+ font-size:14px;
794
+ text-align:center;
795
+ }
796
+ @media print{
797
+ body{
798
+ background:#fff;
799
+ padding:0;
800
+ }
801
+ .invoice{
802
+ border:none;
803
+ max-width:100%;
804
+ }
805
+ }
806
+ </style>
807
+ </head>
808
+ <body>
809
+ <div class="invoice">
810
+ <div class="header">
811
+ <div class="top-flex">
248
812
  <div>
249
- Total:
250
- \u20B9${summary.total}
813
+ <div class="company-name">
814
+ ${invoice.company?.name || "Zentris Pvt Ltd"}
251
815
  </div>
252
-
816
+ <div class="green-strip">
817
+ Manufacturing & Software Billing Solutions
818
+ </div>
819
+ <div class="address">
820
+ ${invoice.company?.address || "Mumbai, India"}
821
+ <br>
822
+ Phone:
823
+ ${invoice.company?.phone || "+91 9999999999"}
824
+ <br>
825
+ Email:
826
+ ${invoice.company?.email || "support@zentris.com"}
827
+ <br>
828
+ GSTIN:
829
+ ${invoice.company?.gstNumber || "27ABCDE1234F1Z5"}
830
+ </div>
831
+ </div>
832
+ <div class="right-top">
833
+ Invoice:
834
+ ${invoice.invoiceNo}
835
+ <br>
836
+ Date:
837
+ ${invoice.date}
838
+ <br>
839
+ Due:
840
+ ${invoice.dueDate || ""}
841
+ <div class="logo">
842
+ ZENTRIS
843
+ <div class="logo-sub">
844
+ BILLING ENGINE
845
+ </div>
846
+ </div>
847
+ </div>
848
+ </div>
849
+ </div>
850
+ <table>
851
+ <tr>
852
+ <td width="35%">
853
+ <span class="bold">
854
+ PAN :
855
+ </span>
856
+ ${invoice.company?.panNumber || "ABCDE1234F"}
857
+ </td>
858
+ <td width="40%" class="invoice-title">
859
+ ${invoice.type || "TAX INVOICE"}
860
+ </td>
861
+ <td width="25%" class="right bold">
862
+ ORIGINAL FOR RECIPIENT
863
+ </td>
864
+ </tr>
865
+ </table>
866
+ <table>
867
+ <tr>
868
+ <td width="40%" class="center bold">
869
+ Customer Detail
870
+ </td>
871
+ <td colspan="2"></td>
872
+ </tr>
873
+ <tr>
874
+ <td>
875
+ <b>M/S:</b>
876
+ ${invoice.customer?.name}
877
+ <br><br>
878
+ <b>Company:</b>
879
+ ${invoice.customer?.company || ""}
880
+ <br><br>
881
+ <b>Address:</b>
882
+ ${invoice.customer?.address}
883
+ <br><br>
884
+ <b>Phone:</b>
885
+ ${invoice.customer?.phone || ""}
886
+ <br><br>
887
+ <b>GSTIN:</b>
888
+ ${invoice.customer?.gstNumber || ""}
889
+ </td>
890
+ <td width="30%">
891
+ <b>Payment Mode:</b>
892
+ ${invoice.payment?.mode || "UPI"}
893
+ <br><br>
894
+ <b>Transport:</b>
895
+ ${invoice.transport || "Blue Dart"}
896
+ <br><br>
897
+ <b>E-Way Bill:</b>
898
+ ${invoice.eway || "78456378"}
899
+ </td>
900
+ <td width="30%">
901
+ <b>Status:</b>
902
+ ${invoice.payment?.status || "Pending"}
903
+ </td>
904
+ </tr>
905
+ </table>
906
+ <table class="product-table">
907
+ <tr>
908
+ <th width="5%">
909
+ Sr
910
+ </th>
911
+ <th width="40%">
912
+ Description
913
+ </th>
914
+ <th width="13%">
915
+ HSN
916
+ </th>
917
+ <th width="13%">
918
+ Qty
919
+ </th>
920
+ <th width="14%">
921
+ Rate
922
+ </th>
923
+ <th width="15%">
924
+ Amount
925
+ </th>
926
+ </tr>
927
+ ${items}
928
+ <tr class="total-row">
929
+ <td colspan="2" class="right">
930
+ TOTAL
931
+ </td>
932
+ <td></td>
933
+ <td class="center">
934
+ ${invoice.items.length}
935
+ </td>
936
+ <td></td>
937
+ <td class="right">
938
+ ${Billing.formatCurrency(summary.total, currency)}
939
+ </td>
940
+ </tr>
941
+ </table>
942
+ <div class="amount-words">
943
+ <b>Total in words:</b>
944
+ ${invoice.amountWords || "Amount payable as per invoice"}
945
+ </div>
946
+ <table class="tax-table">
947
+ <tr>
948
+ <th>
949
+ Taxable
950
+ </th>
951
+ <th>
952
+ Tax %
953
+ </th>
954
+ <th>
955
+ Tax Amount
956
+ </th>
957
+ <th>
958
+ Discount
959
+ </th>
960
+ <th>
961
+ Grand Total
962
+ </th>
963
+ </tr>
964
+ <tr>
965
+ <td class="right">
966
+ ${summary.subtotal.toFixed(2)}
967
+ </td>
968
+ <td class="center">
969
+ ${invoice.tax || 0}%
970
+ </td>
971
+ <td class="right">
972
+ ${summary.taxAmount.toFixed(2)}
973
+ </td>
974
+ <td class="right">
975
+ ${summary.discountAmount.toFixed(2)}
976
+ </td>
977
+ <td class="right bold">
978
+ ${summary.total.toFixed(2)}
979
+ </td>
980
+ </tr>
981
+ </table>
982
+ <table>
983
+ <tr>
984
+ <td width="60%">
985
+ <div class="bank-details">
986
+ <b>Bank:</b>
987
+ ICICI BANK
988
+ <br>
989
+ <b>Account:</b>
990
+ 2715500356
991
+ <br>
992
+ <b>IFSC:</b>
993
+ ICIC000045
994
+ <br>
995
+ <b>UPI:</b>
996
+ zentris@icici
997
+ </div>
998
+ </td>
999
+ <td width="40%" class="center">
1000
+ <div class="qr">
1001
+ QR CODE
1002
+ </div>
1003
+ <div style="margin-top:8px;">
1004
+ Pay using UPI
1005
+ </div>
1006
+ </td>
1007
+ </tr>
1008
+ </table>
1009
+ <div class="terms">
1010
+ <b>Terms & Conditions</b>
1011
+ <br><br>
1012
+ Payment due within 15 days.
1013
+ <br>
1014
+ Goods once sold will not be taken back.
1015
+ <br>
1016
+ Subject to Mumbai jurisdiction.
1017
+ </div>
1018
+ <div class="company-sign">
1019
+ For
1020
+ ${invoice.company?.name || "Zentris Pvt Ltd"}
1021
+ <br><br>
1022
+ ${invoice.signature || "Authorised Signatory"}
1023
+ </div>
1024
+ </div>
1025
+ <div class="footer">
1026
+ Generated using Zentris Billing
253
1027
  </div>
254
-
255
1028
  </body>
256
1029
  </html>
257
1030
  `;
@@ -259,20 +1032,62 @@ Total:
259
1032
 
260
1033
  // src/exporters/html-exporter.ts
261
1034
  var HtmlExporter = class {
1035
+ static generate(invoice, options) {
1036
+ const normalizedInvoice = InvoiceNormalizer.normalize(invoice);
1037
+ const summary = InvoiceCalculator.summary(
1038
+ normalizedInvoice.items,
1039
+ normalizedInvoice.tax || 0,
1040
+ normalizedInvoice.discount || 0
1041
+ );
1042
+ const template = options?.template === "gst" ? classicInvoiceTemplate2 : classicInvoiceTemplate;
1043
+ return InvoiceRenderer.renderHTML(
1044
+ normalizedInvoice,
1045
+ summary,
1046
+ template
1047
+ );
1048
+ }
1049
+ };
1050
+
1051
+ // src/exporters/json-exporter.ts
1052
+ var JsonExporter = class {
262
1053
  static generate(invoice) {
263
1054
  const summary = InvoiceCalculator.summary(
264
1055
  invoice.items,
265
- invoice.tax,
266
- invoice.discount
1056
+ invoice.tax || 0,
1057
+ invoice.discount || 0
1058
+ );
1059
+ return JSON.stringify(
1060
+ {
1061
+ invoice,
1062
+ summary,
1063
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
1064
+ },
1065
+ null,
1066
+ 2
267
1067
  );
268
- return classicInvoiceTemplate(invoice, summary);
1068
+ }
1069
+ };
1070
+
1071
+ // src/exporters/pdf-exporter.ts
1072
+ import puppeteer from "puppeteer";
1073
+ var PdfExporter = class {
1074
+ static async generate(html) {
1075
+ const browser = await puppeteer.launch({ headless: true });
1076
+ const page = await browser.newPage();
1077
+ await page.setContent(html, { waitUntil: "networkidle0" });
1078
+ const pdfBuffer = await page.pdf({
1079
+ format: "A4",
1080
+ printBackground: true
1081
+ });
1082
+ await browser.close();
1083
+ return Buffer.from(pdfBuffer);
269
1084
  }
270
1085
  };
271
1086
 
272
1087
  // src/generators/invoice-generator.ts
273
1088
  var InvoiceGenerator = class {
274
- static toPDF(invoice) {
275
- return PdfExporter.generate(invoice);
1089
+ static toHTML(invoice, options) {
1090
+ return HtmlExporter.generate(invoice, options);
276
1091
  }
277
1092
  static toCSV(invoice) {
278
1093
  return CsvExporter.generate(invoice);
@@ -280,17 +1095,24 @@ var InvoiceGenerator = class {
280
1095
  static toJSON(invoice) {
281
1096
  return JsonExporter.generate(invoice);
282
1097
  }
283
- static toHTML(invoice) {
284
- return HtmlExporter.generate(invoice);
1098
+ static async toPDF(invoice, options) {
1099
+ const html = this.toHTML(invoice, options);
1100
+ return PdfExporter.generate(html);
285
1101
  }
286
1102
  };
1103
+
1104
+ // src/version.ts
1105
+ var VERSION = "2.0.1";
287
1106
  export {
288
1107
  Billing,
289
1108
  BillingError,
290
1109
  InvoiceCalculator,
291
1110
  InvoiceError,
292
1111
  InvoiceGenerator,
1112
+ InvoiceNormalizer,
1113
+ InvoiceRenderer,
293
1114
  TAX_RATES,
1115
+ VERSION,
294
1116
  ValidationError,
295
1117
  calculateDiscount,
296
1118
  calculateGST,