@awadheshs109/billing 1.0.27 → 1.0.29

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/README.md CHANGED
@@ -1,18 +1,240 @@
1
+ # Zentris Billing
1
2
 
3
+ Framework-independent TypeScript billing and invoice generation library for Angular, React, Vue, Node.js and JavaScript applications.
4
+
5
+ Supports:
6
+
7
+ ✅ GST / Tax calculations
8
+ ✅ Discount calculations
9
+ ✅ Currency formatting
10
+ ✅ Invoice generation
11
+ ✅ PDF export
12
+ ✅ CSV export
13
+ ✅ JSON export
14
+ ✅ HTML invoice templates
15
+ ✅ Browser + Node support
16
+ ✅ CI/CD npm publishing
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @awadheshs109/billing
24
+ ```
25
+
26
+ ---
27
+
28
+ ## Quick Start
29
+
30
+ ```ts
31
+ import { Billing } from "@awadheshs109/billing";
32
+
33
+ const gst = Billing.calculateGST(1000, 18);
34
+
35
+ console.log(gst);
36
+
37
+ //180
38
+ ```
39
+
40
+ ---
41
+
42
+ # Invoice Example
43
+
44
+ ```ts
45
+ import { InvoiceGenerator } from "@awadheshs109/billing";
46
+
47
+ const invoice = {
48
+ invoiceNo: "INV-1001",
49
+
50
+ date: "21-05-2026",
51
+
52
+ company: {
53
+ name: "Zentris Pvt Ltd",
54
+
55
+ address: "Mumbai",
56
+
57
+ phone: "+91 999999999",
58
+ },
59
+
60
+ customer: {
61
+ name: "Awadhesh Sharma",
62
+
63
+ company: "Client Company",
64
+
65
+ address: "Bangalore",
66
+ },
67
+
68
+ items: [
69
+ {
70
+ description: "Angular Development",
71
+
72
+ quantity: 5,
73
+
74
+ rate: 75,
75
+ },
76
+
77
+ {
78
+ description: "Invoice Setup",
79
+
80
+ quantity: 2,
81
+
82
+ rate: 100,
83
+ },
84
+ ],
85
+
86
+ tax: 18,
87
+
88
+ discount: 5,
89
+ };
90
+ ```
91
+
92
+ ---
93
+
94
+ # Generate HTML Invoice
95
+
96
+ ```ts
97
+ const html = InvoiceGenerator.toHTML(invoice);
98
+ ```
99
+
100
+ ---
101
+
102
+ # Generate CSV
103
+
104
+ ```ts
105
+ const csv = InvoiceGenerator.toCSV(invoice);
106
+ ```
107
+
108
+ ---
109
+
110
+ # Generate JSON
111
+
112
+ ```ts
113
+ const json = InvoiceGenerator.toJSON(invoice);
114
+ ```
115
+
116
+ ---
117
+
118
+ # Generate PDF
119
+
120
+ ```ts
121
+ const pdf = InvoiceGenerator.toPDF(invoice);
122
+ ```
123
+
124
+ ---
125
+
126
+ # Save PDF in Node
127
+
128
+ ```ts
129
+ import fs from "fs";
130
+
131
+ const pdf = InvoiceGenerator.toPDF(invoice);
132
+
133
+ const buffer = Buffer.from(await pdf.arrayBuffer());
134
+
135
+ fs.writeFileSync("invoice.pdf", buffer);
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Available APIs
141
+
142
+ ### Billing
143
+
144
+ | Method | Description |
145
+ | ---------------------------------- | ------------------ |
146
+ | calculateGST(amount,tax) | Calculate GST |
147
+ | calculateDiscount(amount,discount) | Calculate discount |
148
+ | formatCurrency(amount,currency) | Currency formatter |
149
+
150
+ ---
151
+
152
+ ### InvoiceGenerator
153
+
154
+ | Method | Description |
155
+ | -------- | --------------------- |
156
+ | toHTML() | Generate invoice HTML |
157
+ | toCSV() | Export CSV |
158
+ | toJSON() | Export JSON |
159
+ | toPDF() | Export PDF |
160
+
161
+ ---
162
+
163
+ ## Development
164
+
165
+ Build:
166
+
167
+ ```bash
168
+ npm run build
169
+ ```
170
+
171
+ Run tests:
172
+
173
+ ```bash
174
+ npm run test:run
175
+ ```
176
+
177
+ Local invoice validation:
178
+
179
+ ```bash
180
+ npx tsx test-invoice.ts
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Release Process
186
+
187
+ Version update:
188
+
189
+ ```bash
190
+ npm version patch --no-git-tag-version
2
191
  ```
3
- zentris-billing
4
- ├─ examples
5
- │ ├─ angular
6
- │ ├─ javascript
7
- │ ├─ node
8
- │ └─ react
9
- ├─ package-lock.json
10
- ├─ package.json
11
- ├─ src
12
- │ ├─ constants
13
- │ ├─ core
14
- │ ├─ models
15
- │ └─ utils
16
- └─ tests
17
-
18
- ```
192
+
193
+ Commit:
194
+
195
+ ```bash
196
+ git add .
197
+ git commit -m "development: add feature"
198
+ ```
199
+
200
+ Tag:
201
+
202
+ ```bash
203
+ git tag v1.1.0
204
+ git push
205
+ git push --tags
206
+ ```
207
+
208
+ GitHub Actions automatically:
209
+
210
+ ```txt
211
+ build
212
+ → test
213
+ → publish npm
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Changelog
219
+
220
+ See:
221
+
222
+ ```txt
223
+ CHANGELOG.md
224
+ ```
225
+
226
+ ---
227
+
228
+ ## License
229
+
230
+ MIT
231
+
232
+ ---
233
+
234
+ ## Repository
235
+
236
+ :contentReference[oaicite:0]{index=0}
237
+
238
+ Package:
239
+
240
+ :contentReference[oaicite:1]{index=1}
package/dist/index.d.mts CHANGED
@@ -6,53 +6,21 @@ declare function calculateDiscount(amount: number, percent: number): number;
6
6
  type CurrencyType = 'INR' | 'USD' | 'EUR' | 'GBP';
7
7
  declare function formatCurrency(amount: number, currency?: CurrencyType): string;
8
8
 
9
- interface Customer {
10
- id?: string;
11
- name: string;
12
- email: string;
13
- phone?: string;
14
- gstNumber?: string;
15
- address?: string;
16
- }
17
-
18
- interface InvoiceItem {
19
- name: string;
20
- quantity: number;
21
- price: number;
22
- }
23
-
24
- interface Invoice {
25
- customer: Customer;
26
- items: InvoiceItem[];
27
- tax: number;
28
- discount: number;
29
- invoiceId?: string;
30
- subtotal?: number;
31
- taxAmount?: number;
32
- discountAmount?: number;
33
- total?: number;
34
- generatedDate?: string;
9
+ declare class InvoiceCalculator {
10
+ static summary(items: any[], tax?: number, discount?: number): {
11
+ subtotal: any;
12
+ discount: number;
13
+ tax: number;
14
+ total: number;
15
+ };
35
16
  }
36
17
 
37
- declare function createInvoice(invoice: Invoice): {
38
- invoiceId: string;
39
- subtotal: number;
40
- taxAmount: number;
41
- discountAmount: number;
42
- total: number;
43
- generatedDate: string;
44
- customer: Customer;
45
- items: InvoiceItem[];
46
- tax: number;
47
- discount: number;
48
- };
49
-
50
18
  declare class Billing {
51
19
  static calculateGST: typeof calculateGST;
52
20
  static calculateTax: typeof calculateTax;
53
21
  static calculateDiscount: typeof calculateDiscount;
54
22
  static formatCurrency: typeof formatCurrency;
55
- static createInvoice: typeof createInvoice;
23
+ static InvoiceCalculator: typeof InvoiceCalculator;
56
24
  static getVersion(): string;
57
25
  }
58
26
 
@@ -66,6 +34,42 @@ declare class InvoiceError extends Error {
66
34
  constructor(message: string);
67
35
  }
68
36
 
37
+ interface Customer {
38
+ id?: string;
39
+ name: string;
40
+ email: string;
41
+ phone?: string;
42
+ gstNumber?: string;
43
+ address?: string;
44
+ }
45
+
46
+ interface InvoiceItem {
47
+ description: string;
48
+ quantity: number;
49
+ rate: number;
50
+ }
51
+
52
+ interface Invoice {
53
+ invoiceNo: string;
54
+ date: string;
55
+ company: {
56
+ name: string;
57
+ address: string;
58
+ phone: string;
59
+ email?: string;
60
+ };
61
+ customer: {
62
+ name: string;
63
+ company?: string;
64
+ address: string;
65
+ email?: string;
66
+ };
67
+ items: InvoiceItem[];
68
+ discount?: number;
69
+ tax?: number;
70
+ notes?: string;
71
+ }
72
+
69
73
  interface Tax {
70
74
  name?: string;
71
75
  rate: number;
@@ -92,4 +96,11 @@ declare const TAX_RATES: {
92
96
  readonly GST_28: 28;
93
97
  };
94
98
 
95
- export { Billing, BillingError, type BillingSummary, type CurrencyType, type Customer, type Invoice, InvoiceError, type InvoiceItem, TAX_RATES, type Tax, ValidationError, calculateDiscount, calculateGST, calculateTax, createInvoice, formatCurrency, formatDate, getCurrentTimestamp, isValidEmail, isValidGST, isValidPhone };
99
+ declare class InvoiceGenerator {
100
+ static toPDF(invoice: any): Blob;
101
+ static toCSV(invoice: any): string;
102
+ static toJSON(invoice: any): string;
103
+ static toHTML(invoice: any): string;
104
+ }
105
+
106
+ export { Billing, BillingError, type BillingSummary, type CurrencyType, type Customer, type Invoice, InvoiceCalculator, InvoiceError, InvoiceGenerator, type InvoiceItem, TAX_RATES, type Tax, ValidationError, calculateDiscount, calculateGST, calculateTax, formatCurrency, formatDate, getCurrentTimestamp, isValidEmail, isValidGST, isValidPhone };
package/dist/index.d.ts CHANGED
@@ -6,53 +6,21 @@ declare function calculateDiscount(amount: number, percent: number): number;
6
6
  type CurrencyType = 'INR' | 'USD' | 'EUR' | 'GBP';
7
7
  declare function formatCurrency(amount: number, currency?: CurrencyType): string;
8
8
 
9
- interface Customer {
10
- id?: string;
11
- name: string;
12
- email: string;
13
- phone?: string;
14
- gstNumber?: string;
15
- address?: string;
16
- }
17
-
18
- interface InvoiceItem {
19
- name: string;
20
- quantity: number;
21
- price: number;
22
- }
23
-
24
- interface Invoice {
25
- customer: Customer;
26
- items: InvoiceItem[];
27
- tax: number;
28
- discount: number;
29
- invoiceId?: string;
30
- subtotal?: number;
31
- taxAmount?: number;
32
- discountAmount?: number;
33
- total?: number;
34
- generatedDate?: string;
9
+ declare class InvoiceCalculator {
10
+ static summary(items: any[], tax?: number, discount?: number): {
11
+ subtotal: any;
12
+ discount: number;
13
+ tax: number;
14
+ total: number;
15
+ };
35
16
  }
36
17
 
37
- declare function createInvoice(invoice: Invoice): {
38
- invoiceId: string;
39
- subtotal: number;
40
- taxAmount: number;
41
- discountAmount: number;
42
- total: number;
43
- generatedDate: string;
44
- customer: Customer;
45
- items: InvoiceItem[];
46
- tax: number;
47
- discount: number;
48
- };
49
-
50
18
  declare class Billing {
51
19
  static calculateGST: typeof calculateGST;
52
20
  static calculateTax: typeof calculateTax;
53
21
  static calculateDiscount: typeof calculateDiscount;
54
22
  static formatCurrency: typeof formatCurrency;
55
- static createInvoice: typeof createInvoice;
23
+ static InvoiceCalculator: typeof InvoiceCalculator;
56
24
  static getVersion(): string;
57
25
  }
58
26
 
@@ -66,6 +34,42 @@ declare class InvoiceError extends Error {
66
34
  constructor(message: string);
67
35
  }
68
36
 
37
+ interface Customer {
38
+ id?: string;
39
+ name: string;
40
+ email: string;
41
+ phone?: string;
42
+ gstNumber?: string;
43
+ address?: string;
44
+ }
45
+
46
+ interface InvoiceItem {
47
+ description: string;
48
+ quantity: number;
49
+ rate: number;
50
+ }
51
+
52
+ interface Invoice {
53
+ invoiceNo: string;
54
+ date: string;
55
+ company: {
56
+ name: string;
57
+ address: string;
58
+ phone: string;
59
+ email?: string;
60
+ };
61
+ customer: {
62
+ name: string;
63
+ company?: string;
64
+ address: string;
65
+ email?: string;
66
+ };
67
+ items: InvoiceItem[];
68
+ discount?: number;
69
+ tax?: number;
70
+ notes?: string;
71
+ }
72
+
69
73
  interface Tax {
70
74
  name?: string;
71
75
  rate: number;
@@ -92,4 +96,11 @@ declare const TAX_RATES: {
92
96
  readonly GST_28: 28;
93
97
  };
94
98
 
95
- export { Billing, BillingError, type BillingSummary, type CurrencyType, type Customer, type Invoice, InvoiceError, type InvoiceItem, TAX_RATES, type Tax, ValidationError, calculateDiscount, calculateGST, calculateTax, createInvoice, formatCurrency, formatDate, getCurrentTimestamp, isValidEmail, isValidGST, isValidPhone };
99
+ declare class InvoiceGenerator {
100
+ static toPDF(invoice: any): Blob;
101
+ static toCSV(invoice: any): string;
102
+ static toJSON(invoice: any): string;
103
+ static toHTML(invoice: any): string;
104
+ }
105
+
106
+ export { Billing, BillingError, type BillingSummary, type CurrencyType, type Customer, type Invoice, InvoiceCalculator, InvoiceError, InvoiceGenerator, type InvoiceItem, TAX_RATES, type Tax, ValidationError, calculateDiscount, calculateGST, calculateTax, formatCurrency, formatDate, getCurrentTimestamp, isValidEmail, isValidGST, isValidPhone };
package/dist/index.js CHANGED
@@ -22,13 +22,14 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  Billing: () => Billing,
24
24
  BillingError: () => BillingError,
25
+ InvoiceCalculator: () => InvoiceCalculator,
25
26
  InvoiceError: () => InvoiceError,
27
+ InvoiceGenerator: () => InvoiceGenerator,
26
28
  TAX_RATES: () => TAX_RATES,
27
29
  ValidationError: () => ValidationError,
28
30
  calculateDiscount: () => calculateDiscount,
29
31
  calculateGST: () => calculateGST,
30
32
  calculateTax: () => calculateTax,
31
- createInvoice: () => createInvoice,
32
33
  formatCurrency: () => formatCurrency,
33
34
  formatDate: () => formatDate,
34
35
  getCurrentTimestamp: () => getCurrentTimestamp,
@@ -109,95 +110,24 @@ function formatCurrency(amount, currency = "INR") {
109
110
  ).format(amount);
110
111
  }
111
112
 
112
- // src/utils/validators.ts
113
- function isValidEmail(email) {
114
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
115
- }
116
- function isValidPhone(phone) {
117
- return /^[0-9]{10}$/.test(phone);
118
- }
119
- function isValidGST(gst) {
120
- 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);
121
- }
122
-
123
113
  // src/core/invoice.ts
124
- var invoiceCounter = 1;
125
- function generateInvoiceId() {
126
- const date = /* @__PURE__ */ new Date();
127
- const yyyy = date.getFullYear();
128
- const mm = String(
129
- date.getMonth() + 1
130
- ).padStart(2, "0");
131
- const dd = String(
132
- date.getDate()
133
- ).padStart(2, "0");
134
- const count = String(
135
- invoiceCounter++
136
- ).padStart(6, "0");
137
- return `INV-${yyyy}${mm}${dd}-${count}`;
138
- }
139
- function validateItems(items) {
140
- for (const item of items) {
141
- if (item.quantity <= 0) {
142
- throw new ValidationError(
143
- `Invalid quantity for ${item.name}`
144
- );
145
- }
146
- if (item.price < 0) {
147
- throw new ValidationError(
148
- `Invalid price for ${item.name}`
149
- );
150
- }
151
- }
152
- }
153
- function createInvoice(invoice) {
154
- if (!invoice.customer.name) {
155
- throw new ValidationError(
156
- "Customer name required"
157
- );
158
- }
159
- if (!isValidEmail(
160
- invoice.customer.email
161
- )) {
162
- throw new ValidationError(
163
- "Invalid email"
114
+ var InvoiceCalculator = class {
115
+ static summary(items, tax = 0, discount = 0) {
116
+ const subtotal = items.reduce(
117
+ (sum, item) => sum + item.quantity * item.rate,
118
+ 0
164
119
  );
120
+ const discountAmount = subtotal * (discount / 100);
121
+ const taxable = subtotal - discountAmount;
122
+ const taxAmount = taxable * (tax / 100);
123
+ return {
124
+ subtotal,
125
+ discount: discountAmount,
126
+ tax: taxAmount,
127
+ total: taxable + taxAmount
128
+ };
165
129
  }
166
- if (!invoice.items || invoice.items.length === 0) {
167
- throw new InvoiceError(
168
- "Invoice cannot be empty"
169
- );
170
- }
171
- validateItems(
172
- invoice.items
173
- );
174
- const subtotal = invoice.items.reduce(
175
- (sum, item) => {
176
- return sum + item.price * item.quantity;
177
- },
178
- 0
179
- );
180
- const taxAmount = calculateTax(
181
- subtotal,
182
- invoice.tax
183
- );
184
- const discountAmount = calculateDiscount(
185
- subtotal,
186
- invoice.discount
187
- );
188
- const total = subtotal + taxAmount - discountAmount;
189
- return {
190
- ...invoice,
191
- invoiceId: generateInvoiceId(),
192
- subtotal,
193
- taxAmount,
194
- discountAmount,
195
- total: Number(
196
- total.toFixed(2)
197
- ),
198
- generatedDate: (/* @__PURE__ */ new Date()).toISOString()
199
- };
200
- }
130
+ };
201
131
 
202
132
  // src/core/billing.ts
203
133
  var Billing = class {
@@ -209,7 +139,7 @@ Billing.calculateGST = calculateGST;
209
139
  Billing.calculateTax = calculateTax;
210
140
  Billing.calculateDiscount = calculateDiscount;
211
141
  Billing.formatCurrency = formatCurrency;
212
- Billing.createInvoice = createInvoice;
142
+ Billing.InvoiceCalculator = InvoiceCalculator;
213
143
 
214
144
  // src/utils/date.ts
215
145
  function formatDate(date = /* @__PURE__ */ new Date(), locale = "en-IN") {
@@ -223,6 +153,17 @@ function getCurrentTimestamp() {
223
153
  return Date.now();
224
154
  }
225
155
 
156
+ // src/utils/validators.ts
157
+ function isValidEmail(email) {
158
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
159
+ }
160
+ function isValidPhone(phone) {
161
+ return /^[0-9]{10}$/.test(phone);
162
+ }
163
+ function isValidGST(gst) {
164
+ 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
+ }
166
+
226
167
  // src/constants/tax-rates.ts
227
168
  var TAX_RATES = {
228
169
  GST_5: 5,
@@ -230,17 +171,172 @@ var TAX_RATES = {
230
171
  GST_18: 18,
231
172
  GST_28: 28
232
173
  };
174
+
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");
207
+ }
208
+ };
209
+
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");
221
+ }
222
+ };
223
+
224
+ // src/exporters/json-exporter.ts
225
+ var JsonExporter = class {
226
+ static generate(invoice) {
227
+ return JSON.stringify(
228
+ invoice,
229
+ null,
230
+ 2
231
+ );
232
+ }
233
+ };
234
+
235
+ // src/templates/classic.template.ts
236
+ function classicInvoiceTemplate(invoice, summary) {
237
+ return `
238
+ <html>
239
+
240
+ <body>
241
+
242
+ <div class="invoice">
243
+
244
+ <h1>INVOICE</h1>
245
+
246
+ <div>
247
+ Invoice #: ${invoice.invoiceNo}
248
+ Date:${invoice.date}
249
+ </div>
250
+
251
+ <h3>BILL TO</h3>
252
+
253
+ <p>
254
+ ${invoice.customer.name}
255
+ <br/>
256
+ ${invoice.customer.address}
257
+ </p>
258
+
259
+ <table>
260
+
261
+ <tr>
262
+ <th>Description</th>
263
+ <th>Amount</th>
264
+ </tr>
265
+
266
+ ${invoice.items.map(
267
+ (item) => `
268
+ <tr>
269
+ <td>${item.description}</td>
270
+ <td>
271
+ \u20B9${item.quantity * item.rate}
272
+ </td>
273
+ </tr>
274
+ `
275
+ ).join("")}
276
+
277
+ </table>
278
+
279
+ <div>
280
+ Subtotal:
281
+ \u20B9${summary.subtotal}
282
+ </div>
283
+
284
+ <div>
285
+ Tax:
286
+ \u20B9${summary.tax}
287
+ </div>
288
+
289
+ <div>
290
+ Total:
291
+ \u20B9${summary.total}
292
+ </div>
293
+
294
+ </div>
295
+
296
+ </body>
297
+ </html>
298
+ `;
299
+ }
300
+
301
+ // src/exporters/html-exporter.ts
302
+ var HtmlExporter = class {
303
+ static generate(invoice) {
304
+ const summary = InvoiceCalculator.summary(
305
+ invoice.items,
306
+ invoice.tax,
307
+ invoice.discount
308
+ );
309
+ return classicInvoiceTemplate(invoice, summary);
310
+ }
311
+ };
312
+
313
+ // src/generators/invoice-generator.ts
314
+ var InvoiceGenerator = class {
315
+ static toPDF(invoice) {
316
+ return PdfExporter.generate(invoice);
317
+ }
318
+ static toCSV(invoice) {
319
+ return CsvExporter.generate(invoice);
320
+ }
321
+ static toJSON(invoice) {
322
+ return JsonExporter.generate(invoice);
323
+ }
324
+ static toHTML(invoice) {
325
+ return HtmlExporter.generate(invoice);
326
+ }
327
+ };
233
328
  // Annotate the CommonJS export names for ESM import in node:
234
329
  0 && (module.exports = {
235
330
  Billing,
236
331
  BillingError,
332
+ InvoiceCalculator,
237
333
  InvoiceError,
334
+ InvoiceGenerator,
238
335
  TAX_RATES,
239
336
  ValidationError,
240
337
  calculateDiscount,
241
338
  calculateGST,
242
339
  calculateTax,
243
- createInvoice,
244
340
  formatCurrency,
245
341
  formatDate,
246
342
  getCurrentTimestamp,
package/dist/index.mjs CHANGED
@@ -69,95 +69,24 @@ function formatCurrency(amount, currency = "INR") {
69
69
  ).format(amount);
70
70
  }
71
71
 
72
- // src/utils/validators.ts
73
- function isValidEmail(email) {
74
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
75
- }
76
- function isValidPhone(phone) {
77
- return /^[0-9]{10}$/.test(phone);
78
- }
79
- function isValidGST(gst) {
80
- 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);
81
- }
82
-
83
72
  // src/core/invoice.ts
84
- var invoiceCounter = 1;
85
- function generateInvoiceId() {
86
- const date = /* @__PURE__ */ new Date();
87
- const yyyy = date.getFullYear();
88
- const mm = String(
89
- date.getMonth() + 1
90
- ).padStart(2, "0");
91
- const dd = String(
92
- date.getDate()
93
- ).padStart(2, "0");
94
- const count = String(
95
- invoiceCounter++
96
- ).padStart(6, "0");
97
- return `INV-${yyyy}${mm}${dd}-${count}`;
98
- }
99
- function validateItems(items) {
100
- for (const item of items) {
101
- if (item.quantity <= 0) {
102
- throw new ValidationError(
103
- `Invalid quantity for ${item.name}`
104
- );
105
- }
106
- if (item.price < 0) {
107
- throw new ValidationError(
108
- `Invalid price for ${item.name}`
109
- );
110
- }
111
- }
112
- }
113
- function createInvoice(invoice) {
114
- if (!invoice.customer.name) {
115
- throw new ValidationError(
116
- "Customer name required"
117
- );
118
- }
119
- if (!isValidEmail(
120
- invoice.customer.email
121
- )) {
122
- throw new ValidationError(
123
- "Invalid email"
73
+ var InvoiceCalculator = class {
74
+ static summary(items, tax = 0, discount = 0) {
75
+ const subtotal = items.reduce(
76
+ (sum, item) => sum + item.quantity * item.rate,
77
+ 0
124
78
  );
79
+ const discountAmount = subtotal * (discount / 100);
80
+ const taxable = subtotal - discountAmount;
81
+ const taxAmount = taxable * (tax / 100);
82
+ return {
83
+ subtotal,
84
+ discount: discountAmount,
85
+ tax: taxAmount,
86
+ total: taxable + taxAmount
87
+ };
125
88
  }
126
- if (!invoice.items || invoice.items.length === 0) {
127
- throw new InvoiceError(
128
- "Invoice cannot be empty"
129
- );
130
- }
131
- validateItems(
132
- invoice.items
133
- );
134
- const subtotal = invoice.items.reduce(
135
- (sum, item) => {
136
- return sum + item.price * item.quantity;
137
- },
138
- 0
139
- );
140
- const taxAmount = calculateTax(
141
- subtotal,
142
- invoice.tax
143
- );
144
- const discountAmount = calculateDiscount(
145
- subtotal,
146
- invoice.discount
147
- );
148
- const total = subtotal + taxAmount - discountAmount;
149
- return {
150
- ...invoice,
151
- invoiceId: generateInvoiceId(),
152
- subtotal,
153
- taxAmount,
154
- discountAmount,
155
- total: Number(
156
- total.toFixed(2)
157
- ),
158
- generatedDate: (/* @__PURE__ */ new Date()).toISOString()
159
- };
160
- }
89
+ };
161
90
 
162
91
  // src/core/billing.ts
163
92
  var Billing = class {
@@ -169,7 +98,7 @@ Billing.calculateGST = calculateGST;
169
98
  Billing.calculateTax = calculateTax;
170
99
  Billing.calculateDiscount = calculateDiscount;
171
100
  Billing.formatCurrency = formatCurrency;
172
- Billing.createInvoice = createInvoice;
101
+ Billing.InvoiceCalculator = InvoiceCalculator;
173
102
 
174
103
  // src/utils/date.ts
175
104
  function formatDate(date = /* @__PURE__ */ new Date(), locale = "en-IN") {
@@ -183,6 +112,17 @@ function getCurrentTimestamp() {
183
112
  return Date.now();
184
113
  }
185
114
 
115
+ // src/utils/validators.ts
116
+ function isValidEmail(email) {
117
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
118
+ }
119
+ function isValidPhone(phone) {
120
+ return /^[0-9]{10}$/.test(phone);
121
+ }
122
+ function isValidGST(gst) {
123
+ 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
+ }
125
+
186
126
  // src/constants/tax-rates.ts
187
127
  var TAX_RATES = {
188
128
  GST_5: 5,
@@ -190,16 +130,171 @@ var TAX_RATES = {
190
130
  GST_18: 18,
191
131
  GST_28: 28
192
132
  };
133
+
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");
166
+ }
167
+ };
168
+
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");
180
+ }
181
+ };
182
+
183
+ // src/exporters/json-exporter.ts
184
+ var JsonExporter = class {
185
+ static generate(invoice) {
186
+ return JSON.stringify(
187
+ invoice,
188
+ null,
189
+ 2
190
+ );
191
+ }
192
+ };
193
+
194
+ // src/templates/classic.template.ts
195
+ function classicInvoiceTemplate(invoice, summary) {
196
+ return `
197
+ <html>
198
+
199
+ <body>
200
+
201
+ <div class="invoice">
202
+
203
+ <h1>INVOICE</h1>
204
+
205
+ <div>
206
+ Invoice #: ${invoice.invoiceNo}
207
+ Date:${invoice.date}
208
+ </div>
209
+
210
+ <h3>BILL TO</h3>
211
+
212
+ <p>
213
+ ${invoice.customer.name}
214
+ <br/>
215
+ ${invoice.customer.address}
216
+ </p>
217
+
218
+ <table>
219
+
220
+ <tr>
221
+ <th>Description</th>
222
+ <th>Amount</th>
223
+ </tr>
224
+
225
+ ${invoice.items.map(
226
+ (item) => `
227
+ <tr>
228
+ <td>${item.description}</td>
229
+ <td>
230
+ \u20B9${item.quantity * item.rate}
231
+ </td>
232
+ </tr>
233
+ `
234
+ ).join("")}
235
+
236
+ </table>
237
+
238
+ <div>
239
+ Subtotal:
240
+ \u20B9${summary.subtotal}
241
+ </div>
242
+
243
+ <div>
244
+ Tax:
245
+ \u20B9${summary.tax}
246
+ </div>
247
+
248
+ <div>
249
+ Total:
250
+ \u20B9${summary.total}
251
+ </div>
252
+
253
+ </div>
254
+
255
+ </body>
256
+ </html>
257
+ `;
258
+ }
259
+
260
+ // src/exporters/html-exporter.ts
261
+ var HtmlExporter = class {
262
+ static generate(invoice) {
263
+ const summary = InvoiceCalculator.summary(
264
+ invoice.items,
265
+ invoice.tax,
266
+ invoice.discount
267
+ );
268
+ return classicInvoiceTemplate(invoice, summary);
269
+ }
270
+ };
271
+
272
+ // src/generators/invoice-generator.ts
273
+ var InvoiceGenerator = class {
274
+ static toPDF(invoice) {
275
+ return PdfExporter.generate(invoice);
276
+ }
277
+ static toCSV(invoice) {
278
+ return CsvExporter.generate(invoice);
279
+ }
280
+ static toJSON(invoice) {
281
+ return JsonExporter.generate(invoice);
282
+ }
283
+ static toHTML(invoice) {
284
+ return HtmlExporter.generate(invoice);
285
+ }
286
+ };
193
287
  export {
194
288
  Billing,
195
289
  BillingError,
290
+ InvoiceCalculator,
196
291
  InvoiceError,
292
+ InvoiceGenerator,
197
293
  TAX_RATES,
198
294
  ValidationError,
199
295
  calculateDiscount,
200
296
  calculateGST,
201
297
  calculateTax,
202
- createInvoice,
203
298
  formatCurrency,
204
299
  formatDate,
205
300
  getCurrentTimestamp,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awadheshs109/billing",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "Framework-independent TypeScript billing library for Angular, React, Vue, Node.js and JavaScript projects",
5
5
  "author": "Awadhesh Sharma",
6
6
  "license": "MIT",
@@ -52,5 +52,9 @@
52
52
  "tsx": "^4.22.3",
53
53
  "typescript": "^6.0.3",
54
54
  "vitest": "^4.1.7"
55
+ },
56
+ "dependencies": {
57
+ "jspdf": "^4.2.1",
58
+ "papaparse": "^5.5.3"
55
59
  }
56
60
  }