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