@ic-labs/invoice-kit 0.1.1

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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +552 -0
  3. package/dist/core/document.d.ts +8 -0
  4. package/dist/core/document.d.ts.map +1 -0
  5. package/dist/core/document.js +22 -0
  6. package/dist/core/document.js.map +1 -0
  7. package/dist/core/factories.d.ts +7 -0
  8. package/dist/core/factories.d.ts.map +1 -0
  9. package/dist/core/factories.js +44 -0
  10. package/dist/core/factories.js.map +1 -0
  11. package/dist/core/types.d.ts +141 -0
  12. package/dist/core/types.d.ts.map +1 -0
  13. package/dist/core/types.js +2 -0
  14. package/dist/core/types.js.map +1 -0
  15. package/dist/core/validation.d.ts +3 -0
  16. package/dist/core/validation.d.ts.map +1 -0
  17. package/dist/core/validation.js +95 -0
  18. package/dist/core/validation.js.map +1 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/locales/ar.d.ts +3 -0
  24. package/dist/locales/ar.d.ts.map +1 -0
  25. package/dist/locales/ar.js +31 -0
  26. package/dist/locales/ar.js.map +1 -0
  27. package/dist/locales/fr.d.ts +3 -0
  28. package/dist/locales/fr.d.ts.map +1 -0
  29. package/dist/locales/fr.js +31 -0
  30. package/dist/locales/fr.js.map +1 -0
  31. package/dist/locales/index.d.ts +3 -0
  32. package/dist/locales/index.d.ts.map +1 -0
  33. package/dist/locales/index.js +8 -0
  34. package/dist/locales/index.js.map +1 -0
  35. package/dist/renderers/pdf.d.ts +3 -0
  36. package/dist/renderers/pdf.d.ts.map +1 -0
  37. package/dist/renderers/pdf.js +337 -0
  38. package/dist/renderers/pdf.js.map +1 -0
  39. package/dist/templates/definitions.d.ts +3 -0
  40. package/dist/templates/definitions.d.ts.map +1 -0
  41. package/dist/templates/definitions.js +12 -0
  42. package/dist/templates/definitions.js.map +1 -0
  43. package/dist/templates/delivery-note.d.ts +3 -0
  44. package/dist/templates/delivery-note.d.ts.map +1 -0
  45. package/dist/templates/delivery-note.js +11 -0
  46. package/dist/templates/delivery-note.js.map +1 -0
  47. package/dist/templates/invoice.d.ts +3 -0
  48. package/dist/templates/invoice.d.ts.map +1 -0
  49. package/dist/templates/invoice.js +11 -0
  50. package/dist/templates/invoice.js.map +1 -0
  51. package/dist/templates/purchase-order.d.ts +3 -0
  52. package/dist/templates/purchase-order.d.ts.map +1 -0
  53. package/dist/templates/purchase-order.js +11 -0
  54. package/dist/templates/purchase-order.js.map +1 -0
  55. package/dist/templates/quote.d.ts +3 -0
  56. package/dist/templates/quote.d.ts.map +1 -0
  57. package/dist/templates/quote.js +11 -0
  58. package/dist/templates/quote.js.map +1 -0
  59. package/dist/utils/formatting.d.ts +4 -0
  60. package/dist/utils/formatting.d.ts.map +1 -0
  61. package/dist/utils/formatting.js +18 -0
  62. package/dist/utils/formatting.js.map +1 -0
  63. package/dist/utils/math.d.ts +3 -0
  64. package/dist/utils/math.d.ts.map +1 -0
  65. package/dist/utils/math.js +14 -0
  66. package/dist/utils/math.js.map +1 -0
  67. package/dist/utils/taxes.d.ts +5 -0
  68. package/dist/utils/taxes.d.ts.map +1 -0
  69. package/dist/utils/taxes.js +44 -0
  70. package/dist/utils/taxes.js.map +1 -0
  71. package/package.json +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Itri Cloud Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,552 @@
1
+ # @ic-labs/invoice-kit
2
+
3
+ TypeScript library for generating Moroccan business documents as PDFs.
4
+
5
+ It is designed for real business usage, not a demo. The package provides typed document factories, business calculations, French and Arabic labels, Moroccan invoice defaults, and PDF generation for:
6
+
7
+ - `Facture` / invoice
8
+ - `Devis` / quote
9
+ - `Bon de commande` / purchase order
10
+ - `Bon de livraison` / delivery note
11
+
12
+ ## Features
13
+
14
+ - Strict TypeScript API
15
+ - Node.js 18+
16
+ - Lightweight runtime based on `pdfkit`
17
+ - Clean factories for all document types
18
+ - Automatic subtotal, discount, VAT, taxable base, and total calculations
19
+ - Moroccan defaults:
20
+ - currency: `MAD`
21
+ - VAT label: `TVA`
22
+ - date format: `dd/MM/yyyy`
23
+ - company identifiers: `ICE`, `IF`, `RC`
24
+ - French labels by default
25
+ - Arabic labels with `locale: "ar-MA"`
26
+ - Bank details support:
27
+ - local transfer: bank name, holder name, RIB
28
+ - international transfer: bank name, holder name, SWIFT, IBAN
29
+ - Remote logo URL support in PDF headers
30
+ - Delivery notes rendered without pricing information
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ npm install @ic-labs/invoice-kit
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```ts
41
+ import { createInvoice } from "@ic-labs/invoice-kit";
42
+
43
+ const invoice = createInvoice({
44
+ number: "FAC-2026-0001",
45
+ logo: "https://example.com/assets/logo.png",
46
+ seller: {
47
+ name: "IC Labs SARL",
48
+ addressLines: ["Casablanca, Maroc"],
49
+ ice: "001234567890123",
50
+ if: "12345678",
51
+ rc: "56789"
52
+ },
53
+ client: {
54
+ name: "Client Demo",
55
+ addressLines: ["Rabat, Maroc"]
56
+ },
57
+ items: [
58
+ {
59
+ name: "Service de conseil",
60
+ quantity: 1,
61
+ price: 1000
62
+ }
63
+ ],
64
+ vatRate: 0.2,
65
+ paymentTerms: {
66
+ label: "Paiement sous 30 jours"
67
+ },
68
+ bankInfo: {
69
+ type: "local",
70
+ bankName: "Attijariwafa Bank",
71
+ holderName: "IC Labs SARL",
72
+ rib: "007 810 000123456789012345"
73
+ }
74
+ });
75
+
76
+ await invoice.toPDF("./invoice.pdf");
77
+ ```
78
+
79
+ ## Public API
80
+
81
+ ```ts
82
+ import {
83
+ createDeliveryNote,
84
+ createInvoice,
85
+ createPurchaseOrder,
86
+ createQuote
87
+ } from "@ic-labs/invoice-kit";
88
+ ```
89
+
90
+ Each factory returns a `BusinessDocument` instance.
91
+
92
+ ### `BusinessDocument`
93
+
94
+ - `toJSON(): BusinessDocumentData`
95
+ - `toPDF(outputPathOrOptions?): Promise<Uint8Array>`
96
+
97
+ Examples:
98
+
99
+ ```ts
100
+ const bytes = await invoice.toPDF();
101
+ ```
102
+
103
+ ```ts
104
+ await invoice.toPDF("./invoice.pdf");
105
+ ```
106
+
107
+ ```ts
108
+ await invoice.toPDF({
109
+ outputPath: "./invoice.pdf"
110
+ });
111
+ ```
112
+
113
+ ## Document Factories
114
+
115
+ ### `createInvoice(input)`
116
+
117
+ Creates a financial invoice with totals, discounts, VAT, bank details, and payment terms.
118
+
119
+ ### `createQuote(input)`
120
+
121
+ Creates a quote/devis with the same financial model as invoices.
122
+
123
+ ### `createPurchaseOrder(input)`
124
+
125
+ Creates a purchase order with pricing and totals.
126
+
127
+ ### `createDeliveryNote(input)`
128
+
129
+ Creates a delivery note without pricing display in the PDF.
130
+
131
+ Important behavior for delivery notes:
132
+
133
+ - item prices are not required
134
+ - pricing columns are hidden in the PDF
135
+ - totals are hidden in the PDF
136
+ - `discounts`, `vatRate`, `paymentTerms`, and `bankInfo` may exist in input but are not rendered as financial output
137
+ - internal totals are normalized to zero for delivery notes
138
+
139
+ ## Input Reference
140
+
141
+ All document factories accept a typed object shaped like `DocumentInput`.
142
+
143
+ ### Required fields
144
+
145
+ - `number: string`
146
+ - `seller: Party`
147
+ - `client: Party`
148
+ - `items: LineItemInput[]`
149
+
150
+ ### Common optional fields
151
+
152
+ - `logo?: string`
153
+ - `issueDate?: Date`
154
+ - `dueDate?: Date`
155
+ - `currency?: string`
156
+ - `vatRate?: number`
157
+ - `discounts?: DiscountInput[]`
158
+ - `notes?: string`
159
+ - `paymentTerms?: PaymentTerms`
160
+ - `bankInfo?: BankInfo`
161
+ - `locale?: "fr-MA" | "ar-MA"`
162
+ - `title?: string`
163
+
164
+ ### `Party`
165
+
166
+ ```ts
167
+ interface Party {
168
+ name: string;
169
+ addressLines: string[];
170
+ email?: string;
171
+ phone?: string;
172
+ city?: string;
173
+ country?: string;
174
+ taxId?: string;
175
+ ice?: string;
176
+ if?: string;
177
+ rc?: string;
178
+ }
179
+ ```
180
+
181
+ Notes:
182
+
183
+ - `addressLines` must contain at least one line
184
+ - seller identifiers `ICE`, `IF`, and `RC` are rendered directly inside seller details
185
+
186
+ ### `LineItemInput`
187
+
188
+ ```ts
189
+ interface LineItemInput {
190
+ name: string;
191
+ description?: string;
192
+ quantity: number;
193
+ unitPrice?: number;
194
+ price?: number;
195
+ unit?: string;
196
+ discountRate?: number;
197
+ }
198
+ ```
199
+
200
+ Notes:
201
+
202
+ - financial documents require either `unitPrice` or `price`
203
+ - delivery notes do not require pricing
204
+ - `discountRate` is a decimal ratio, for example:
205
+ - `0.1` for 10%
206
+ - `0.05` for 5%
207
+
208
+ ### `DiscountInput`
209
+
210
+ ```ts
211
+ interface DiscountInput {
212
+ type: "percentage" | "fixed";
213
+ value: number;
214
+ label?: string;
215
+ }
216
+ ```
217
+
218
+ Examples:
219
+
220
+ ```ts
221
+ { type: "fixed", value: 150, label: "Remise commerciale" }
222
+ ```
223
+
224
+ ```ts
225
+ { type: "percentage", value: 0.02, label: "Escompte" }
226
+ ```
227
+
228
+ ### `PaymentTerms`
229
+
230
+ ```ts
231
+ interface PaymentTerms {
232
+ label: string;
233
+ dueDate?: Date;
234
+ notes?: string;
235
+ }
236
+ ```
237
+
238
+ ### `BankInfo`
239
+
240
+ #### Local transfer
241
+
242
+ ```ts
243
+ {
244
+ type: "local",
245
+ bankName: "Attijariwafa Bank",
246
+ holderName: "IC Labs SARL",
247
+ rib: "007 810 000123456789012345"
248
+ }
249
+ ```
250
+
251
+ #### International transfer
252
+
253
+ ```ts
254
+ {
255
+ type: "international",
256
+ bankName: "BMCI Corporate",
257
+ holderName: "IC Labs SARL",
258
+ swiftCode: "BMCIMAMC",
259
+ iban: "MA64001122000001234567890123"
260
+ }
261
+ ```
262
+
263
+ ## Financial Model
264
+
265
+ For invoices, quotes, and purchase orders, the package calculates:
266
+
267
+ - line subtotal
268
+ - line discount amount
269
+ - line total
270
+ - subtotal
271
+ - document discount total
272
+ - taxable base
273
+ - VAT amount
274
+ - grand total
275
+
276
+ ### VAT
277
+
278
+ - default VAT rate is `0.2`
279
+ - VAT is displayed as `TVA`
280
+ - rate input uses decimal form:
281
+ - `0.2` = 20%
282
+ - `0.1` = 10%
283
+ - `0` = 0%
284
+
285
+ ### Currency
286
+
287
+ - default currency is `MAD`
288
+ - amounts are formatted with two decimals
289
+
290
+ ## Moroccan Business Context
291
+
292
+ The package is tailored for Morocco:
293
+
294
+ - `MAD` default currency
295
+ - `TVA` terminology
296
+ - seller company fields:
297
+ - `ICE`
298
+ - `IF`
299
+ - `RC`
300
+ - French-first labels
301
+ - Arabic labels available via locale
302
+ - date formatting in `dd/MM/yyyy`
303
+
304
+ ## Localization
305
+
306
+ Supported locales:
307
+
308
+ - `fr-MA`
309
+ - `ar-MA`
310
+
311
+ Example:
312
+
313
+ ```ts
314
+ const quote = createQuote({
315
+ number: "DEV-2026-0012",
316
+ locale: "ar-MA",
317
+ seller: {
318
+ name: "IC Labs SARL",
319
+ addressLines: ["Casablanca"]
320
+ },
321
+ client: {
322
+ name: "Client",
323
+ addressLines: ["Rabat"]
324
+ },
325
+ items: [{ name: "Audit", quantity: 1, price: 1200 }]
326
+ });
327
+ ```
328
+
329
+ ### Arabic PDF rendering
330
+
331
+ Arabic labels are supported, but Arabic PDFs require Arabic-capable font files when calling `toPDF()`.
332
+
333
+ ```ts
334
+ await quote.toPDF({
335
+ outputPath: "./devis-ar.pdf",
336
+ fonts: {
337
+ regular: "./fonts/NotoSansArabic-Regular.ttf",
338
+ bold: "./fonts/NotoSansArabic-Bold.ttf"
339
+ }
340
+ });
341
+ ```
342
+
343
+ Without custom fonts, Arabic glyph rendering is not reliable in PDF output.
344
+
345
+ ## Remote Logo Support
346
+
347
+ You can pass a remote image URL through `logo`.
348
+
349
+ ```ts
350
+ logo: "https://example.com/assets/logo.png"
351
+ ```
352
+
353
+ Behavior:
354
+
355
+ - the library fetches the image itself during `toPDF()`
356
+ - the user only provides the URL
357
+ - the logo is rendered in the document header
358
+
359
+ Currently supported remote image formats:
360
+
361
+ - `PNG`
362
+ - `JPEG` / `JPG`
363
+
364
+ Currently rejected remote image formats:
365
+
366
+ - `SVG`
367
+ - `WEBP`
368
+
369
+ Why:
370
+
371
+ - `pdfkit` does not natively embed `SVG` or `WEBP`
372
+ - this package intentionally keeps dependencies light and does not bundle image conversion tooling
373
+
374
+ ## Validation Rules
375
+
376
+ The library validates document input before building the document model.
377
+
378
+ Examples of enforced rules:
379
+
380
+ - `number` must be present
381
+ - seller and client names must be non-empty
382
+ - seller and client must have at least one address line
383
+ - `items` must contain at least one line item
384
+ - quantity must be greater than zero
385
+ - financial documents require `unitPrice` or `price`
386
+ - negative prices are rejected
387
+ - negative discounts are rejected
388
+ - `vatRate` must be between `0` and `1`
389
+ - `logo` must be a valid `http` or `https` URL
390
+ - bank fields must be present according to bank mode
391
+
392
+ ## Rendering Behavior
393
+
394
+ ### Financial documents
395
+
396
+ Invoices, quotes, and purchase orders render:
397
+
398
+ - seller block
399
+ - client block
400
+ - issue/due date
401
+ - currency
402
+ - item table with amount columns
403
+ - totals section
404
+ - payment terms
405
+ - bank details
406
+ - notes
407
+
408
+ ### Delivery notes
409
+
410
+ Delivery notes render:
411
+
412
+ - seller block
413
+ - client block
414
+ - issue/due date
415
+ - item table with designation and quantity only
416
+ - notes
417
+
418
+ Delivery notes do not render:
419
+
420
+ - unit price
421
+ - amount
422
+ - subtotal
423
+ - discount
424
+ - VAT
425
+ - total
426
+ - bank details
427
+ - payment terms block
428
+
429
+ ## Examples
430
+
431
+ ### Invoice with international transfer info
432
+
433
+ ```ts
434
+ import { createInvoice } from "@ic-labs/invoice-kit";
435
+
436
+ const invoice = createInvoice({
437
+ number: "FAC-2026-0020",
438
+ seller: {
439
+ name: "IC Labs SARL",
440
+ addressLines: ["Casablanca"],
441
+ ice: "001234567890123",
442
+ if: "12345678",
443
+ rc: "56789"
444
+ },
445
+ client: {
446
+ name: "Noxel SAS",
447
+ addressLines: ["Paris"]
448
+ },
449
+ items: [
450
+ {
451
+ name: "ERP Deployment",
452
+ quantity: 3,
453
+ price: 1800,
454
+ unit: "jour"
455
+ }
456
+ ],
457
+ vatRate: 0.2,
458
+ bankInfo: {
459
+ type: "international",
460
+ bankName: "BMCI Corporate",
461
+ holderName: "IC Labs SARL",
462
+ swiftCode: "BMCIMAMC",
463
+ iban: "MA64001122000001234567890123"
464
+ }
465
+ });
466
+ ```
467
+
468
+ ### Quote with local bank details
469
+
470
+ ```ts
471
+ import { createQuote } from "@ic-labs/invoice-kit";
472
+
473
+ const quote = createQuote({
474
+ number: "DEV-2026-0012",
475
+ seller: {
476
+ name: "IC Labs SARL",
477
+ addressLines: ["Casablanca"]
478
+ },
479
+ client: {
480
+ name: "Client",
481
+ addressLines: ["Rabat"]
482
+ },
483
+ items: [
484
+ {
485
+ name: "Audit",
486
+ quantity: 1,
487
+ price: 1200
488
+ }
489
+ ],
490
+ discounts: [{ type: "percentage", value: 0.05, label: "Remise devis" }],
491
+ bankInfo: {
492
+ type: "local",
493
+ bankName: "Attijariwafa Bank",
494
+ holderName: "IC Labs SARL",
495
+ rib: "007 810 000123456789012345"
496
+ }
497
+ });
498
+ ```
499
+
500
+ ### Delivery note without pricing
501
+
502
+ ```ts
503
+ import { createDeliveryNote } from "@ic-labs/invoice-kit";
504
+
505
+ const deliveryNote = createDeliveryNote({
506
+ number: "BL-2026-0015",
507
+ seller: {
508
+ name: "IC Labs SARL",
509
+ addressLines: ["Casablanca"]
510
+ },
511
+ client: {
512
+ name: "Client",
513
+ addressLines: ["Rabat"]
514
+ },
515
+ items: [
516
+ { name: "Laptop", quantity: 2, unit: "piece" },
517
+ { name: "Mouse", quantity: 3, unit: "piece" }
518
+ ],
519
+ notes: "Marchandise remise au responsable du site."
520
+ });
521
+ ```
522
+
523
+ ## Development
524
+
525
+ Available scripts:
526
+
527
+ - `npm run typecheck`
528
+ - `npm run build`
529
+ - `npm run smoke`
530
+
531
+ ## Publishing
532
+
533
+ The repository is configured for GitHub Actions based publishing.
534
+
535
+ Current release model:
536
+
537
+ - CI runs on pushes and pull requests
538
+ - publish workflow runs on pushes to `main`
539
+ - npm publish only happens if the current `package.json` version does not already exist on npm
540
+
541
+ That means a release requires a version bump before pushing to `main`.
542
+
543
+ ## Limitations
544
+
545
+ - multi-page table layout is not implemented yet
546
+ - remote logos currently support PNG/JPEG only
547
+ - Arabic PDF output requires custom fonts
548
+ - delivery notes intentionally do not display financial values
549
+
550
+ ## License
551
+
552
+ MIT
@@ -0,0 +1,8 @@
1
+ import type { BusinessDocumentData, PdfRenderOptions } from "./types.js";
2
+ export declare class BusinessDocument {
3
+ private readonly data;
4
+ constructor(data: BusinessDocumentData);
5
+ toJSON(): BusinessDocumentData;
6
+ toPDF(outputPathOrOptions?: string | PdfRenderOptions): Promise<Uint8Array>;
7
+ }
8
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/core/document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGzE,qBAAa,gBAAgB;IACR,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,oBAAoB;IAEvD,MAAM,IAAI,oBAAoB;IAIxB,KAAK,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;CAazF"}
@@ -0,0 +1,22 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { renderDocumentPdf } from "../renderers/pdf.js";
3
+ export class BusinessDocument {
4
+ data;
5
+ constructor(data) {
6
+ this.data = data;
7
+ }
8
+ toJSON() {
9
+ return this.data;
10
+ }
11
+ async toPDF(outputPathOrOptions) {
12
+ const options = typeof outputPathOrOptions === "string"
13
+ ? { outputPath: outputPathOrOptions }
14
+ : outputPathOrOptions;
15
+ const pdfBytes = await renderDocumentPdf(this.data, options);
16
+ if (options?.outputPath) {
17
+ await writeFile(options.outputPath, pdfBytes);
18
+ }
19
+ return pdfBytes;
20
+ }
21
+ }
22
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/core/document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,OAAO,gBAAgB;IACS;IAApC,YAAoC,IAA0B;QAA1B,SAAI,GAAJ,IAAI,CAAsB;IAAG,CAAC;IAE3D,MAAM;QACX,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,mBAA+C;QAChE,MAAM,OAAO,GAAG,OAAO,mBAAmB,KAAK,QAAQ;YACrD,CAAC,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE;YACrC,CAAC,CAAC,mBAAmB,CAAC;QAExB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE7D,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,MAAM,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import { BusinessDocument } from "./document.js";
2
+ import type { DocumentInput } from "./types.js";
3
+ export declare const createInvoice: (input: DocumentInput) => BusinessDocument;
4
+ export declare const createQuote: (input: DocumentInput) => BusinessDocument;
5
+ export declare const createPurchaseOrder: (input: DocumentInput) => BusinessDocument;
6
+ export declare const createDeliveryNote: (input: DocumentInput) => BusinessDocument;
7
+ //# sourceMappingURL=factories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../src/core/factories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAyB,aAAa,EAAgB,MAAM,YAAY,CAAC;AA6CrF,eAAO,MAAM,aAAa,UAHuB,aAAa,KAAG,gBAGjB,CAAC;AACjD,eAAO,MAAM,WAAW,UAJyB,aAAa,KAAG,gBAIrB,CAAC;AAC7C,eAAO,MAAM,mBAAmB,UALiB,aAAa,KAAG,gBAKL,CAAC;AAC7D,eAAO,MAAM,kBAAkB,UANkB,aAAa,KAAG,gBAMP,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { BusinessDocument } from "./document.js";
2
+ import { validateDocumentInput } from "./validation.js";
3
+ import { createTemplateDefinition } from "../templates/definitions.js";
4
+ import { getLabels } from "../locales/index.js";
5
+ import { computeLineItem, computeTotals, MOROCCO_DEFAULT_VAT_RATE } from "../utils/taxes.js";
6
+ const createBusinessDocument = (options) => {
7
+ validateDocumentInput(options);
8
+ const locale = options.locale ?? "fr-MA";
9
+ const template = createTemplateDefinition(options.type);
10
+ const isDeliveryNote = options.type === "deliveryNote";
11
+ const items = options.items.map(computeLineItem);
12
+ const discounts = isDeliveryNote ? [] : (options.discounts ?? []);
13
+ const vatRate = isDeliveryNote ? 0 : (options.vatRate ?? MOROCCO_DEFAULT_VAT_RATE);
14
+ const issueDate = options.issueDate ?? new Date();
15
+ const labels = getLabels(locale);
16
+ const data = {
17
+ type: options.type,
18
+ title: options.title ?? template.getTitle(locale) ?? labels.documentTitle,
19
+ number: options.number,
20
+ ...(options.logo ? { logo: options.logo } : {}),
21
+ issueDate,
22
+ seller: options.seller,
23
+ client: options.client,
24
+ items,
25
+ currency: options.currency ?? "MAD",
26
+ vatRate,
27
+ discounts,
28
+ locale,
29
+ totals: computeTotals(items, discounts, vatRate)
30
+ };
31
+ return new BusinessDocument({
32
+ ...data,
33
+ ...(options.dueDate ? { dueDate: options.dueDate } : {}),
34
+ ...(options.paymentTerms ? { paymentTerms: options.paymentTerms } : {}),
35
+ ...(options.bankInfo ? { bankInfo: options.bankInfo } : {}),
36
+ ...(options.notes ? { notes: options.notes } : {})
37
+ });
38
+ };
39
+ const withType = (type) => (input) => createBusinessDocument({ ...input, type });
40
+ export const createInvoice = withType("invoice");
41
+ export const createQuote = withType("quote");
42
+ export const createPurchaseOrder = withType("purchaseOrder");
43
+ export const createDeliveryNote = withType("deliveryNote");
44
+ //# sourceMappingURL=factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.js","sourceRoot":"","sources":["../../src/core/factories.ts"],"names":[],"mappings":"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"}