@endora-commerce/mod-invoices 0.0.0-stage → 0.100.0

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -2
  3. package/dist/admin/components/InvoiceSectionTabs.d.ts +22 -0
  4. package/dist/admin/components/InvoiceSectionTabs.d.ts.map +1 -0
  5. package/dist/admin/components/InvoiceSectionTabs.js +34 -0
  6. package/dist/admin/components/InvoiceSectionTabs.js.map +1 -0
  7. package/dist/admin/index.d.ts +34 -0
  8. package/dist/admin/index.d.ts.map +1 -0
  9. package/dist/admin/index.js +69 -0
  10. package/dist/admin/index.js.map +1 -0
  11. package/dist/admin/pages/InvoiceDetail.d.ts +10 -0
  12. package/dist/admin/pages/InvoiceDetail.d.ts.map +1 -0
  13. package/dist/admin/pages/InvoiceDetail.js +111 -0
  14. package/dist/admin/pages/InvoiceDetail.js.map +1 -0
  15. package/dist/admin/pages/InvoiceTemplateEditor.d.ts +11 -0
  16. package/dist/admin/pages/InvoiceTemplateEditor.d.ts.map +1 -0
  17. package/dist/admin/pages/InvoiceTemplateEditor.js +188 -0
  18. package/dist/admin/pages/InvoiceTemplateEditor.js.map +1 -0
  19. package/dist/admin/pages/InvoiceTemplatesPage.d.ts +10 -0
  20. package/dist/admin/pages/InvoiceTemplatesPage.d.ts.map +1 -0
  21. package/dist/admin/pages/InvoiceTemplatesPage.js +60 -0
  22. package/dist/admin/pages/InvoiceTemplatesPage.js.map +1 -0
  23. package/dist/admin/pages/InvoicesList.d.ts +9 -0
  24. package/dist/admin/pages/InvoicesList.d.ts.map +1 -0
  25. package/dist/admin/pages/InvoicesList.js +116 -0
  26. package/dist/admin/pages/InvoicesList.js.map +1 -0
  27. package/dist/admin/templates/described-blocks.d.ts +67 -0
  28. package/dist/admin/templates/described-blocks.d.ts.map +1 -0
  29. package/dist/admin/templates/described-blocks.js +83 -0
  30. package/dist/admin/templates/described-blocks.js.map +1 -0
  31. package/dist/admin/templates/invoice-builder-plugin.d.ts +4 -0
  32. package/dist/admin/templates/invoice-builder-plugin.d.ts.map +1 -0
  33. package/dist/admin/templates/invoice-builder-plugin.js +12 -0
  34. package/dist/admin/templates/invoice-builder-plugin.js.map +1 -0
  35. package/dist/admin/templates/invoice-puck-config.d.ts +37 -0
  36. package/dist/admin/templates/invoice-puck-config.d.ts.map +1 -0
  37. package/dist/admin/templates/invoice-puck-config.js +733 -0
  38. package/dist/admin/templates/invoice-puck-config.js.map +1 -0
  39. package/dist/backend/email-templates/invoice-issued.default.d.ts +10 -0
  40. package/dist/backend/email-templates/invoice-issued.default.d.ts.map +1 -0
  41. package/dist/backend/email-templates/invoice-issued.default.js +45 -0
  42. package/dist/backend/email-templates/invoice-issued.default.js.map +1 -0
  43. package/dist/backend/entities/invoice-external-attachment.entity.d.ts +20 -0
  44. package/dist/backend/entities/invoice-external-attachment.entity.d.ts.map +1 -0
  45. package/dist/backend/entities/invoice-external-attachment.entity.js +77 -0
  46. package/dist/backend/entities/invoice-external-attachment.entity.js.map +1 -0
  47. package/dist/backend/entities/invoice-line.entity.d.ts +20 -0
  48. package/dist/backend/entities/invoice-line.entity.d.ts.map +1 -0
  49. package/dist/backend/entities/invoice-line.entity.js +82 -0
  50. package/dist/backend/entities/invoice-line.entity.js.map +1 -0
  51. package/dist/backend/entities/invoice-number-counter.entity.d.ts +18 -0
  52. package/dist/backend/entities/invoice-number-counter.entity.d.ts.map +1 -0
  53. package/dist/backend/entities/invoice-number-counter.entity.js +63 -0
  54. package/dist/backend/entities/invoice-number-counter.entity.js.map +1 -0
  55. package/dist/backend/entities/invoice-template.entity.d.ts +22 -0
  56. package/dist/backend/entities/invoice-template.entity.d.ts.map +1 -0
  57. package/dist/backend/entities/invoice-template.entity.js +84 -0
  58. package/dist/backend/entities/invoice-template.entity.js.map +1 -0
  59. package/dist/backend/entities/invoice.entity.d.ts +64 -0
  60. package/dist/backend/entities/invoice.entity.d.ts.map +1 -0
  61. package/dist/backend/entities/invoice.entity.js +202 -0
  62. package/dist/backend/entities/invoice.entity.js.map +1 -0
  63. package/dist/backend/index.d.ts +111 -0
  64. package/dist/backend/index.d.ts.map +1 -0
  65. package/dist/backend/index.js +291 -0
  66. package/dist/backend/index.js.map +1 -0
  67. package/dist/backend/pdf-components/descriptor.d.ts +29 -0
  68. package/dist/backend/pdf-components/descriptor.d.ts.map +1 -0
  69. package/dist/backend/pdf-components/descriptor.js +227 -0
  70. package/dist/backend/pdf-components/descriptor.js.map +1 -0
  71. package/dist/backend/pdf-components/embed-logo-images.d.ts +35 -0
  72. package/dist/backend/pdf-components/embed-logo-images.d.ts.map +1 -0
  73. package/dist/backend/pdf-components/embed-logo-images.js +101 -0
  74. package/dist/backend/pdf-components/embed-logo-images.js.map +1 -0
  75. package/dist/backend/pdf-components/sample.d.ts +4 -0
  76. package/dist/backend/pdf-components/sample.d.ts.map +1 -0
  77. package/dist/backend/pdf-components/sample.js +75 -0
  78. package/dist/backend/pdf-components/sample.js.map +1 -0
  79. package/dist/backend/pdf-components/sections.d.ts +34 -0
  80. package/dist/backend/pdf-components/sections.d.ts.map +1 -0
  81. package/dist/backend/pdf-components/sections.js +445 -0
  82. package/dist/backend/pdf-components/sections.js.map +1 -0
  83. package/dist/backend/pdf-components/tree-mapper.d.ts +37 -0
  84. package/dist/backend/pdf-components/tree-mapper.d.ts.map +1 -0
  85. package/dist/backend/pdf-components/tree-mapper.js +76 -0
  86. package/dist/backend/pdf-components/tree-mapper.js.map +1 -0
  87. package/dist/backend/plugin.d.ts +124 -0
  88. package/dist/backend/plugin.d.ts.map +1 -0
  89. package/dist/backend/plugin.js +87 -0
  90. package/dist/backend/plugin.js.map +1 -0
  91. package/dist/backend/routes.admin.d.ts +41 -0
  92. package/dist/backend/routes.admin.d.ts.map +1 -0
  93. package/dist/backend/routes.admin.js +219 -0
  94. package/dist/backend/routes.admin.js.map +1 -0
  95. package/dist/backend/routes.customer.d.ts +33 -0
  96. package/dist/backend/routes.customer.d.ts.map +1 -0
  97. package/dist/backend/routes.customer.js +124 -0
  98. package/dist/backend/routes.customer.js.map +1 -0
  99. package/dist/backend/seeds/generic-invoice-template.d.ts +18 -0
  100. package/dist/backend/seeds/generic-invoice-template.d.ts.map +1 -0
  101. package/dist/backend/seeds/generic-invoice-template.js +174 -0
  102. package/dist/backend/seeds/generic-invoice-template.js.map +1 -0
  103. package/dist/backend/services/amount-to-words.d.ts +20 -0
  104. package/dist/backend/services/amount-to-words.d.ts.map +1 -0
  105. package/dist/backend/services/amount-to-words.js +232 -0
  106. package/dist/backend/services/amount-to-words.js.map +1 -0
  107. package/dist/backend/services/auto-issue-reactor.d.ts +53 -0
  108. package/dist/backend/services/auto-issue-reactor.d.ts.map +1 -0
  109. package/dist/backend/services/auto-issue-reactor.js +122 -0
  110. package/dist/backend/services/auto-issue-reactor.js.map +1 -0
  111. package/dist/backend/services/corrective-invoice.d.ts +38 -0
  112. package/dist/backend/services/corrective-invoice.d.ts.map +1 -0
  113. package/dist/backend/services/corrective-invoice.js +257 -0
  114. package/dist/backend/services/corrective-invoice.js.map +1 -0
  115. package/dist/backend/services/cross-module-context.d.ts +82 -0
  116. package/dist/backend/services/cross-module-context.d.ts.map +1 -0
  117. package/dist/backend/services/cross-module-context.js +93 -0
  118. package/dist/backend/services/cross-module-context.js.map +1 -0
  119. package/dist/backend/services/duplicate-number-refusal.d.ts +33 -0
  120. package/dist/backend/services/duplicate-number-refusal.d.ts.map +1 -0
  121. package/dist/backend/services/duplicate-number-refusal.js +92 -0
  122. package/dist/backend/services/duplicate-number-refusal.js.map +1 -0
  123. package/dist/backend/services/erp-sale-document-write-port.d.ts +37 -0
  124. package/dist/backend/services/erp-sale-document-write-port.d.ts.map +1 -0
  125. package/dist/backend/services/erp-sale-document-write-port.js +192 -0
  126. package/dist/backend/services/erp-sale-document-write-port.js.map +1 -0
  127. package/dist/backend/services/invoice-attachment-fetch-registry.d.ts +75 -0
  128. package/dist/backend/services/invoice-attachment-fetch-registry.d.ts.map +1 -0
  129. package/dist/backend/services/invoice-attachment-fetch-registry.js +81 -0
  130. package/dist/backend/services/invoice-attachment-fetch-registry.js.map +1 -0
  131. package/dist/backend/services/invoice-copy-host.service.d.ts +9 -0
  132. package/dist/backend/services/invoice-copy-host.service.d.ts.map +1 -0
  133. package/dist/backend/services/invoice-copy-host.service.js +52 -0
  134. package/dist/backend/services/invoice-copy-host.service.js.map +1 -0
  135. package/dist/backend/services/invoice-email-dispatch.d.ts +89 -0
  136. package/dist/backend/services/invoice-email-dispatch.d.ts.map +1 -0
  137. package/dist/backend/services/invoice-email-dispatch.js +138 -0
  138. package/dist/backend/services/invoice-email-dispatch.js.map +1 -0
  139. package/dist/backend/services/invoice-line-builder.d.ts +29 -0
  140. package/dist/backend/services/invoice-line-builder.d.ts.map +1 -0
  141. package/dist/backend/services/invoice-line-builder.js +46 -0
  142. package/dist/backend/services/invoice-line-builder.js.map +1 -0
  143. package/dist/backend/services/invoice-number-collisions.d.ts +17 -0
  144. package/dist/backend/services/invoice-number-collisions.d.ts.map +1 -0
  145. package/dist/backend/services/invoice-number-collisions.js +154 -0
  146. package/dist/backend/services/invoice-number-collisions.js.map +1 -0
  147. package/dist/backend/services/invoice-number-generator.d.ts +96 -0
  148. package/dist/backend/services/invoice-number-generator.d.ts.map +1 -0
  149. package/dist/backend/services/invoice-number-generator.js +157 -0
  150. package/dist/backend/services/invoice-number-generator.js.map +1 -0
  151. package/dist/backend/services/invoice-pdf-block-registry.d.ts +65 -0
  152. package/dist/backend/services/invoice-pdf-block-registry.d.ts.map +1 -0
  153. package/dist/backend/services/invoice-pdf-block-registry.js +94 -0
  154. package/dist/backend/services/invoice-pdf-block-registry.js.map +1 -0
  155. package/dist/backend/services/invoice-pdf-renderer.d.ts +57 -0
  156. package/dist/backend/services/invoice-pdf-renderer.d.ts.map +1 -0
  157. package/dist/backend/services/invoice-pdf-renderer.js +158 -0
  158. package/dist/backend/services/invoice-pdf-renderer.js.map +1 -0
  159. package/dist/backend/services/invoice-pdf.d.ts +24 -0
  160. package/dist/backend/services/invoice-pdf.d.ts.map +1 -0
  161. package/dist/backend/services/invoice-pdf.js +52 -0
  162. package/dist/backend/services/invoice-pdf.js.map +1 -0
  163. package/dist/backend/services/invoice-placement-apply-port.d.ts +29 -0
  164. package/dist/backend/services/invoice-placement-apply-port.d.ts.map +1 -0
  165. package/dist/backend/services/invoice-placement-apply-port.js +40 -0
  166. package/dist/backend/services/invoice-placement-apply-port.js.map +1 -0
  167. package/dist/backend/services/invoice-read-port.d.ts +44 -0
  168. package/dist/backend/services/invoice-read-port.d.ts.map +1 -0
  169. package/dist/backend/services/invoice-read-port.js +95 -0
  170. package/dist/backend/services/invoice-read-port.js.map +1 -0
  171. package/dist/backend/services/invoice-service.d.ts +94 -0
  172. package/dist/backend/services/invoice-service.d.ts.map +1 -0
  173. package/dist/backend/services/invoice-service.js +374 -0
  174. package/dist/backend/services/invoice-service.js.map +1 -0
  175. package/dist/backend/services/invoice-template-service.d.ts +43 -0
  176. package/dist/backend/services/invoice-template-service.d.ts.map +1 -0
  177. package/dist/backend/services/invoice-template-service.js +147 -0
  178. package/dist/backend/services/invoice-template-service.js.map +1 -0
  179. package/dist/backend/services/numbering-configuration.d.ts +76 -0
  180. package/dist/backend/services/numbering-configuration.d.ts.map +1 -0
  181. package/dist/backend/services/numbering-configuration.js +176 -0
  182. package/dist/backend/services/numbering-configuration.js.map +1 -0
  183. package/dist/backend/services/numbering-write-validator.d.ts +22 -0
  184. package/dist/backend/services/numbering-write-validator.d.ts.map +1 -0
  185. package/dist/backend/services/numbering-write-validator.js +82 -0
  186. package/dist/backend/services/numbering-write-validator.js.map +1 -0
  187. package/dist/backend/services/seller-settings.d.ts +24 -0
  188. package/dist/backend/services/seller-settings.d.ts.map +1 -0
  189. package/dist/backend/services/seller-settings.js +38 -0
  190. package/dist/backend/services/seller-settings.js.map +1 -0
  191. package/dist/backend/services/vendor-number-hold.d.ts +10 -0
  192. package/dist/backend/services/vendor-number-hold.d.ts.map +1 -0
  193. package/dist/backend/services/vendor-number-hold.js +14 -0
  194. package/dist/backend/services/vendor-number-hold.js.map +1 -0
  195. package/dist/manifest.d.ts +203 -0
  196. package/dist/manifest.d.ts.map +1 -0
  197. package/dist/manifest.js +390 -0
  198. package/dist/manifest.js.map +1 -0
  199. package/dist/migrations/20260629T125121_invoices_module.d.ts +17 -0
  200. package/dist/migrations/20260629T125121_invoices_module.d.ts.map +1 -0
  201. package/dist/migrations/20260629T125121_invoices_module.js +117 -0
  202. package/dist/migrations/20260629T125121_invoices_module.js.map +1 -0
  203. package/dist/migrations/20260801T111000_invoices_generic_template_reseed.d.ts +6 -0
  204. package/dist/migrations/20260801T111000_invoices_generic_template_reseed.d.ts.map +1 -0
  205. package/dist/migrations/20260801T111000_invoices_generic_template_reseed.js +25 -0
  206. package/dist/migrations/20260801T111000_invoices_generic_template_reseed.js.map +1 -0
  207. package/dist/migrations/20260817T201110_invoices_correction_idempotency_key.d.ts +20 -0
  208. package/dist/migrations/20260817T201110_invoices_correction_idempotency_key.d.ts.map +1 -0
  209. package/dist/migrations/20260817T201110_invoices_correction_idempotency_key.js +33 -0
  210. package/dist/migrations/20260817T201110_invoices_correction_idempotency_key.js.map +1 -0
  211. package/dist/migrations/20260903T101756_invoices_namespace_block_names.d.ts +6 -0
  212. package/dist/migrations/20260903T101756_invoices_namespace_block_names.d.ts.map +1 -0
  213. package/dist/migrations/20260903T101756_invoices_namespace_block_names.js +56 -0
  214. package/dist/migrations/20260903T101756_invoices_namespace_block_names.js.map +1 -0
  215. package/dist/migrations/20260914T133603_invoices_erp_imported_sale_documents.d.ts +12 -0
  216. package/dist/migrations/20260914T133603_invoices_erp_imported_sale_documents.d.ts.map +1 -0
  217. package/dist/migrations/20260914T133603_invoices_erp_imported_sale_documents.js +87 -0
  218. package/dist/migrations/20260914T133603_invoices_erp_imported_sale_documents.js.map +1 -0
  219. package/dist/migrations/20260926T230239_invoices_import_identity.d.ts +33 -0
  220. package/dist/migrations/20260926T230239_invoices_import_identity.d.ts.map +1 -0
  221. package/dist/migrations/20260926T230239_invoices_import_identity.js +83 -0
  222. package/dist/migrations/20260926T230239_invoices_import_identity.js.map +1 -0
  223. package/dist/migrations/index.d.ts +32 -0
  224. package/dist/migrations/index.d.ts.map +1 -0
  225. package/dist/migrations/index.js +39 -0
  226. package/dist/migrations/index.js.map +1 -0
  227. package/dist/ports/index.d.ts +93 -0
  228. package/dist/ports/index.d.ts.map +1 -0
  229. package/dist/ports/index.js +2 -0
  230. package/dist/ports/index.js.map +1 -0
  231. package/docs/invoices.md +113 -0
  232. package/i18n/en.json +45 -0
  233. package/i18n/pl.json +45 -0
  234. package/package.json +119 -3
  235. package/tailwind.css +14 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The port interfaces `invoices` publishes whose signature carries a MikroORM
3
+ * `EntityManager`, and **nothing that exists at runtime** (feature 080, T048;
4
+ * D-169, D-171).
5
+ *
6
+ * `tsc` compiles this file to `export {};`. That is the property D-171 makes
7
+ * the boundary decision on — *a subpath is contract surface iff the module it
8
+ * resolves to exports no runtime binding* — and it is why this declaration has
9
+ * its own file rather than sitting on top of a service module, which exports
10
+ * the class beside it. A consumer naming that file names the owner's
11
+ * implementation, whatever `import type` erases; a consumer naming this one
12
+ * names a declaration and can name nothing else.
13
+ *
14
+ * **This is not yet a supported specifier and the ledger still counts it.**
15
+ * `invoices` is not a workspace package, so there is no `exports` map for this
16
+ * to be a subpath of, and `check:module-boundary` reads `orders`' relative
17
+ * import exactly as it read the entity import it replaces — D-171 says so in as
18
+ * many words: `resolveModulePackage` returns `null` for any specifier starting
19
+ * with `.`, so an unconverted reach has no subpath for the exemption to apply
20
+ * to, and reaching the exempt state takes three separable edits (package the
21
+ * owner, publish the interface, rewrite the specifier). This file is the second
22
+ * of those three, taken early because it is the one that does not need the
23
+ * module to move.
24
+ *
25
+ * The rest of this module's surface is in `@endora-commerce/contracts` and
26
+ * belongs there — `InvoiceReadPort`, `InvoicePdfPort`, `CorrectiveInvoicePort`
27
+ * are contract DTOs end to end. This one qualifies for `./ports` on D-171's own
28
+ * test — *"does this signature stop the interface living in
29
+ * `packages/contracts`"* — and the answer is its `EntityManager` parameter,
30
+ * which that package may not name because `admin` and `storefront` both compile
31
+ * it (FR-034).
32
+ *
33
+ * No entity class leaves by this door, type-only included (D-168).
34
+ */
35
+ import type { EntityManager } from '@mikro-orm/postgresql';
36
+ /**
37
+ * What {@link InvoicePlacementApplyPort.createProformaForOrder} answers — a
38
+ * published record and never the managed entity (D-77's first narrowing).
39
+ * `orders` reads nothing off it today; it is returned so that the caller can
40
+ * tell "opened" from "the owner is absent and opened nothing", which is a state
41
+ * this seam really has.
42
+ */
43
+ export interface ProformaInvoiceOpened {
44
+ readonly id: string;
45
+ readonly orderId: string;
46
+ readonly number: string;
47
+ }
48
+ /**
49
+ * Container name: `invoicePlacementApplyPort`. Owner: `invoices`.
50
+ *
51
+ * The proforma document order placement opens, written on the **caller's**
52
+ * `EntityManager` (D-169). `orders` is the one consumer, and it makes one call.
53
+ *
54
+ * **The seam is not a defect in the design, it *is* the design.**
55
+ * `invoices_order_fk` (`invoices.order_id` -> `orders.id`, `on delete restrict`,
56
+ * `db/migrations/20260425T050720_core_commerce_init.ts`) means the row cannot
57
+ * exist before its order does, and the order does not commit until placement
58
+ * returns — so a port that opened its own transaction could not satisfy a
59
+ * foreign key against a row it cannot see. A foreign key needs the **table**
60
+ * and never the class (D-169), so that constraint stands while this module
61
+ * publishes no entity class by name.
62
+ *
63
+ * **The read half is not here.** The customer download and the admin bulk print
64
+ * go through `InvoiceReadPort` / `InvoicePdfPort` in
65
+ * `@endora-commerce/contracts`, and a read handed an `EntityManager` would be a
66
+ * write seam re-opened to serve a read (D-169).
67
+ *
68
+ * **Owner off:** this module is switchable (`invoices.enabled`), and `orders`
69
+ * declares the edge `degrades-without` rather than binding it — an acknowledged
70
+ * edge would keep the bind and make that control unusable, because `orders` is
71
+ * non-deactivatable. So placement asks `effectiveState.isPresent('invoices')`
72
+ * and, when the answer is no, opens no proforma and changes nothing else about
73
+ * the order. That is what the setting's own description promises an operator —
74
+ * *"switches invoice issuance … on or off"* — and it is what the platform did
75
+ * **not** do before T048: the row was written straight into this module's table
76
+ * while the operator had switched it off, which is the shape issue #188 names.
77
+ */
78
+ export interface InvoicePlacementApplyPort {
79
+ /**
80
+ * Open the proforma an order is placed with.
81
+ *
82
+ * `em` is **required** (D-169). Its one caller is `placeOrder`, which always
83
+ * passes the `EntityManager` its own transaction runs on; an optional
84
+ * parameter is what lets the same method double as a standalone transaction,
85
+ * and that is a lie about a seam a foreign key holds together.
86
+ */
87
+ createProformaForOrder(em: EntityManager, input: {
88
+ orderId: string;
89
+ currency: string;
90
+ total: string;
91
+ }): Promise<ProformaInvoiceOpened>;
92
+ }
93
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,sBAAsB,CACpB,EAAE,EAAE,aAAa,EACjB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC1D,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACnC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,113 @@
1
+ ---
2
+ title: invoices
3
+ description: PDF invoice / proforma generation + asset linkage
4
+ ---
5
+
6
+ # `invoices`
7
+
8
+ Generates proforma and final invoice PDFs, registers them under the
9
+ `assets` module, and links them from the originating Order.
10
+
11
+ ## Public surface
12
+
13
+ Admin list is gated by `orders:read`.
14
+
15
+ | Verb + Path | Audience | Purpose |
16
+ | --- | --- | --- |
17
+ | `GET /api/v1/orders/:id/invoice` | customer | Download invoice PDF (404 `INVOICE_NOT_READY` until status='ready'; binary Content-Type once ready). Admin uses the same endpoint via the storefront origin to re-download. |
18
+ | `GET /api/v1/admin/invoices` | admin | List all invoices with `filter[status]` / `filter[orderId]`; default limit 50, capped at 200 |
19
+
20
+ ## Generation flow
21
+
22
+ `invoice-service.ts#generate()` runs after `order.confirmed`: pulls the
23
+ Order + items + buyer Address snapshot, renders a PDF via a small,
24
+ dependency-light renderer, persists the bytes through the `assets` module,
25
+ and writes the asset id back onto the Order. Failures emit
26
+ `invoice.generation_failed.v1` for an admin retry queue.
27
+
28
+ ## Entities
29
+
30
+ `Invoice` (number, issued/dated timestamps, asset reference,
31
+ `type ∈ {proforma, final}`).
32
+
33
+ ## Numbering
34
+
35
+ Two facts about an invoice number pull in opposite directions, and both are
36
+ deliberate:
37
+
38
+ - the **sequence** is drawn per `(sales channel, kind, year)`, gap-free, under a
39
+ row lock — `invoice_number_counters`;
40
+ - the **number** is unique across the whole platform — `invoices_number_unique`.
41
+
42
+ What turns the first into the second is a pattern, held in a Setting per
43
+ document kind and scopable per sales channel:
44
+
45
+ | Kind | Setting | Default |
46
+ | --- | --- | --- |
47
+ | VAT invoice | `invoices.numbering.invoice.pattern` | `FV {seq}/{channel}/{YYYY}` |
48
+ | Proforma | `invoices.numbering.proforma.pattern` | `PRO {seq}/{channel}/{YYYY}` |
49
+ | Correction | `invoices.numbering.correction.pattern` | `KOR {seq}/{channel}/{YYYY}` |
50
+
51
+ ### Tokens
52
+
53
+ | Token | Renders |
54
+ | --- | --- |
55
+ | `{seq}` | the drawn sequence number |
56
+ | `{seq:N}` | the same, zero-padded to width `N` |
57
+ | `{channel}` | the sales channel's `code`, uppercased |
58
+ | `{YYYY}` / `{YY}` | the issue year, 4 or 2 digits |
59
+ | `{MM}` | the issue month |
60
+
61
+ Everything else is literal text. The channel `code` is immutable and unique, so
62
+ a number already rendered through `{channel}` can never be invalidated by a
63
+ rename; keep a separator on both sides of it, because `FV {channel}{seq}` loses
64
+ the boundary between two variable-length fields and renders `FV A12` for both
65
+ (`a1`, 2) and (`a`, 12).
66
+
67
+ ### Three refusals, and which one is the guarantee
68
+
69
+ Because the sequence is per channel and the number is not, two channels whose
70
+ patterns can render one string are a duplicate waiting to happen. Three layers
71
+ stand between that and a customer's document:
72
+
73
+ 1. **The shipped default carries `{channel}`**, so creating a sales channel
74
+ does not arm a collision. The system-default channel is pinned once, at boot,
75
+ to the historical `FV {seq}/{YYYY}` — an existing deployment's series does not
76
+ change shape — and only while nobody has configured the setting.
77
+ 2. **`400 INVOICE_NUMBER_PATTERN_COLLIDES`** on the settings write, naming the
78
+ channel the pattern collides with. It refuses a *possible* collision: at a
79
+ configuration write nothing is at stake, so a conservative refusal costs one
80
+ edit.
81
+ 3. **`409 INVOICE_NUMBER_ALREADY_ISSUED`** at issuance, naming the channel that
82
+ already holds the number. This is the guarantee — it is the one chokepoint
83
+ every number passes through — and it refuses only an *actual* duplicate. The
84
+ transaction rolls back, so the counter draw is undone and no gap is left.
85
+
86
+ A deployment that is already configured into a collision is reported at boot,
87
+ once per colliding pair, and is **not** blocked: a fixable invoicing
88
+ misconfiguration must not become a storefront outage.
89
+
90
+ ## Extension points
91
+
92
+ - **Numbering scheme** — `services/invoice-number-generator.ts` renders the
93
+ pattern (`formatInvoiceNumber`) and draws the sequence;
94
+ `services/invoice-number-collisions.ts` decides whether two channels can
95
+ render one string. Add a token in the first and the probe grid in the second
96
+ will compare it.
97
+ - **e-invoicing** — for KSeF / Peppol / similar, plug a sender adapter
98
+ that consumes `invoice.issued.v1` events.
99
+
100
+ ## PDF templates (page builder)
101
+
102
+ Admin route `/invoices/templates` edits a Puck tree of invoice sections
103
+ (`InvoiceHeader`, `InvoiceParties`, line/VAT tables, totals, notes, KSeF,
104
+ plus layout blocks: spacer, divider, logo, footer). Section props
105
+ personalize typography, column visibility, and labels; missing props keep
106
+ the historical default layout.
107
+
108
+ - `GET /api/v1/admin/invoice-templates/:id/preview` — PDF of the **saved**
109
+ template content for that id (sample invoice fixture).
110
+ - `POST /api/v1/admin/invoice-templates/:id/preview` — same, with a draft
111
+ `{ data }` body so authors can preview unsaved canvas state.
112
+ - Runtime issue path still uses `resolveTree(salesChannelId)` (active
113
+ channel/global template).
package/i18n/en.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "settings.sellerTaxId.label": "Seller VAT / NIP",
3
+ "settings.sellerCompanyData.label": "Seller company data",
4
+ "settings.autoIssueTriggerStatus.label": "Auto-issue on order status",
5
+ "settings.emailSendOnIssue.label": "Email invoice on issue",
6
+ "settings.emailDeliveryMode.label": "Invoice email delivery mode",
7
+ "settings.numberingInvoicePattern.label": "Invoice numbering pattern",
8
+ "settings.numberingProformaPattern.label": "Proforma numbering pattern",
9
+ "settings.numberingCorrectionPattern.label": "Correction numbering pattern",
10
+ "settings.storefrontBaseUrl.label": "Storefront base URL (invoice email links)",
11
+ "actions.openInvoices.label": "Open invoices",
12
+ "actions.openInvoices.description": "View and manage issued invoices and corrections",
13
+ "actions.invoiceTemplates.label": "Invoice templates",
14
+ "actions.invoiceTemplates.description": "Customize the invoice PDF layout (WYSIWYG)",
15
+ "list.title": "Invoices",
16
+ "errors.INVOICE_NOT_READY": "The invoice for this order is not ready yet. It becomes available once it has been issued.",
17
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES": "This numbering pattern can produce the same document number as another sales channel. Invoice numbers must be unique across the whole platform.",
18
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES.other_channel": "This numbering pattern can produce the same document number as sales channel \"{channel}\". Invoice numbers are unique across the whole platform, so give this channel a pattern the other one cannot repeat — adding the channel token is the usual way.",
19
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES.no_sequence_token": "This numbering pattern has no sequence token, so every document in this channel would be given the same number. The field description lists the tokens you can use.",
20
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED": "This document number is already in use. Invoice numbers are unique across the whole platform.",
21
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED.other_channel": "Invoice number {number} is already used by sales channel \"{channel}\". Give this channel its own numbering pattern before issuing again — nothing was issued.",
22
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED.same_channel": "Invoice number {number} has already been issued in this sales channel, so its numbering pattern is producing repeats — nothing was issued.",
23
+ "nav.invoices.label": "Invoices",
24
+ "blocks.invoiceHeader.label": "Header (number + dates)",
25
+ "blocks.invoiceHeader.description": "The invoice number, issue date, sale date and payment due date.",
26
+ "blocks.invoiceParties.label": "Seller & buyer",
27
+ "blocks.invoiceParties.description": "The seller and buyer details, side by side.",
28
+ "blocks.invoiceLineItems.label": "Line items table",
29
+ "blocks.invoiceLineItems.description": "The invoiced positions, as a table.",
30
+ "blocks.invoiceVatSummary.label": "VAT summary",
31
+ "blocks.invoiceVatSummary.description": "Net, VAT and gross amounts per tax rate.",
32
+ "blocks.invoiceTotals.label": "Totals & amount in words",
33
+ "blocks.invoiceTotals.description": "The invoice totals, the amount due and the amount in words.",
34
+ "blocks.invoiceNotes.label": "Notes (free text)",
35
+ "blocks.invoiceNotes.description": "Free-text notes printed on the invoice.",
36
+ "blocks.invoiceSpacer.label": "Spacer",
37
+ "blocks.invoiceSpacer.description": "Vertical whitespace between sections.",
38
+ "blocks.invoiceDivider.label": "Divider",
39
+ "blocks.invoiceDivider.description": "A horizontal rule between sections.",
40
+ "blocks.invoiceLogo.label": "Logo",
41
+ "blocks.invoiceLogo.description": "The seller logo.",
42
+ "blocks.invoiceFooter.label": "Footer / legal",
43
+ "blocks.invoiceFooter.description": "The legal footer printed at the bottom of the invoice.",
44
+ "blocks.category.invoice": "Invoice sections"
45
+ }
package/i18n/pl.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "settings.sellerTaxId.label": "NIP / VAT sprzedawcy",
3
+ "settings.sellerCompanyData.label": "Dane firmy sprzedawcy",
4
+ "settings.autoIssueTriggerStatus.label": "Automatyczne wystawianie wg statusu zamówienia",
5
+ "settings.emailSendOnIssue.label": "Wyślij fakturę mailem po wystawieniu",
6
+ "settings.emailDeliveryMode.label": "Tryb wysyłki faktury mailem",
7
+ "settings.numberingInvoicePattern.label": "Format numeracji faktur",
8
+ "settings.numberingProformaPattern.label": "Format numeracji proform",
9
+ "settings.numberingCorrectionPattern.label": "Format numeracji korekt",
10
+ "settings.storefrontBaseUrl.label": "Bazowy URL Storefront (linki w mailach z fakturą)",
11
+ "actions.openInvoices.label": "Otwórz faktury",
12
+ "actions.openInvoices.description": "Przeglądaj i zarządzaj wystawionymi fakturami i korektami",
13
+ "actions.invoiceTemplates.label": "Szablony faktur",
14
+ "actions.invoiceTemplates.description": "Dostosuj wygląd PDF faktury (WYSIWYG)",
15
+ "list.title": "Faktury",
16
+ "errors.INVOICE_NOT_READY": "Faktura do tego zamówienia nie jest jeszcze gotowa. Będzie dostępna po jej wystawieniu.",
17
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES": "Ten wzorzec numeracji może wygenerować taki sam numer dokumentu jak inny kanał sprzedaży. Numery faktur muszą być unikalne w całej platformie.",
18
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES.other_channel": "Ten wzorzec numeracji może wygenerować taki sam numer dokumentu jak kanał sprzedaży \"{channel}\". Numery faktur są unikalne w całej platformie, więc nadaj temu kanałowi wzorzec, którego tamten nie może powtórzyć — zwykle wystarczy dodać token kanału.",
19
+ "errors.INVOICE_NUMBER_PATTERN_COLLIDES.no_sequence_token": "Ten wzorzec numeracji nie zawiera tokenu sekwencji, więc każdy dokument w tym kanale otrzymałby ten sam numer. Dostępne tokeny są wymienione w opisie pola.",
20
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED": "Ten numer dokumentu jest już zajęty. Numery faktur są unikalne w całej platformie.",
21
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED.other_channel": "Numer faktury {number} jest już używany przez kanał sprzedaży \"{channel}\". Nadaj temu kanałowi własny wzorzec numeracji przed ponowną próbą — nic nie zostało wystawione.",
22
+ "errors.INVOICE_NUMBER_ALREADY_ISSUED.same_channel": "Numer faktury {number} został już wystawiony w tym kanale sprzedaży, więc jego wzorzec numeracji generuje powtórzenia — nic nie zostało wystawione.",
23
+ "nav.invoices.label": "Faktury",
24
+ "blocks.invoiceHeader.label": "Nagłówek (numer i daty)",
25
+ "blocks.invoiceHeader.description": "Numer faktury, data wystawienia, data sprzedaży i termin płatności.",
26
+ "blocks.invoiceParties.label": "Sprzedawca i nabywca",
27
+ "blocks.invoiceParties.description": "Dane sprzedawcy i nabywcy obok siebie.",
28
+ "blocks.invoiceLineItems.label": "Tabela pozycji",
29
+ "blocks.invoiceLineItems.description": "Pozycje faktury w postaci tabeli.",
30
+ "blocks.invoiceVatSummary.label": "Podsumowanie VAT",
31
+ "blocks.invoiceVatSummary.description": "Kwoty netto, VAT i brutto w podziale na stawki podatku.",
32
+ "blocks.invoiceTotals.label": "Sumy i kwota słownie",
33
+ "blocks.invoiceTotals.description": "Sumy faktury, kwota do zapłaty i kwota słownie.",
34
+ "blocks.invoiceNotes.label": "Uwagi (tekst dowolny)",
35
+ "blocks.invoiceNotes.description": "Uwagi w postaci dowolnego tekstu drukowane na fakturze.",
36
+ "blocks.invoiceSpacer.label": "Odstęp",
37
+ "blocks.invoiceSpacer.description": "Pionowy odstęp pomiędzy sekcjami.",
38
+ "blocks.invoiceDivider.label": "Separator",
39
+ "blocks.invoiceDivider.description": "Linia pozioma pomiędzy sekcjami.",
40
+ "blocks.invoiceLogo.label": "Logo",
41
+ "blocks.invoiceLogo.description": "Logo sprzedawcy.",
42
+ "blocks.invoiceFooter.label": "Stopka / informacje prawne",
43
+ "blocks.invoiceFooter.description": "Stopka prawna drukowana na dole faktury.",
44
+ "blocks.category.invoice": "Sekcje faktury"
45
+ }
package/package.json CHANGED
@@ -1,6 +1,122 @@
1
1
  {
2
2
  "name": "@endora-commerce/mod-invoices",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.100.0",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "Invoice generation, numbering, PDF templates, corrections, and email delivery.",
7
+ "license": "MIT",
8
+ "endora": {
9
+ "type": "module",
10
+ "id": "invoices"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/endora-commerce/endora-commerce.git",
15
+ "directory": "packages/modules/invoices"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/manifest.d.ts",
23
+ "default": "./dist/manifest.js"
24
+ },
25
+ "./backend": {
26
+ "types": "./dist/backend/index.d.ts",
27
+ "default": "./dist/backend/index.js"
28
+ },
29
+ "./migrations": {
30
+ "types": "./dist/migrations/index.d.ts",
31
+ "default": "./dist/migrations/index.js"
32
+ },
33
+ "./ports": {
34
+ "types": "./dist/ports/index.d.ts",
35
+ "default": "./dist/ports/index.js"
36
+ },
37
+ "./admin": {
38
+ "types": "./dist/admin/index.d.ts",
39
+ "default": "./dist/admin/index.js"
40
+ },
41
+ "./tailwind.css": "./tailwind.css",
42
+ "./package.json": "./package.json"
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "i18n",
47
+ "docs",
48
+ "tailwind.css"
49
+ ],
50
+ "engines": {
51
+ "node": ">=22.18.0"
52
+ },
53
+ "peerDependencies": {
54
+ "@measured/puck": "^0",
55
+ "@mikro-orm/core": "^6",
56
+ "@mikro-orm/migrations": "^6",
57
+ "@mikro-orm/postgresql": "^6",
58
+ "@types/pdfmake": "^0",
59
+ "fastify": "^5",
60
+ "lucide-react": "^1",
61
+ "pdfmake": "^0",
62
+ "react": "^19",
63
+ "react-router-dom": "^7",
64
+ "zod": "^4",
65
+ "@endora-commerce/admin-kit": "0.100.0",
66
+ "@endora-commerce/contracts": "0.100.0",
67
+ "@endora-commerce/email-components": "0.100.0",
68
+ "@endora-commerce/page-builder-admin": "0.100.0",
69
+ "@endora-commerce/page-builder-core": "0.100.0",
70
+ "@endora-commerce/platform": "0.100.0"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "@endora-commerce/admin-kit": {
74
+ "optional": true
75
+ },
76
+ "@endora-commerce/page-builder-admin": {
77
+ "optional": true
78
+ },
79
+ "@measured/puck": {
80
+ "optional": true
81
+ },
82
+ "lucide-react": {
83
+ "optional": true
84
+ },
85
+ "react": {
86
+ "optional": true
87
+ },
88
+ "react-router-dom": {
89
+ "optional": true
90
+ }
91
+ },
92
+ "devDependencies": {
93
+ "@fastify/type-provider-zod": "^1.0.0",
94
+ "@measured/puck": "^0.20.2",
95
+ "@mikro-orm/core": "^6.6.13",
96
+ "@mikro-orm/migrations": "^6.6.13",
97
+ "@mikro-orm/postgresql": "^6.6.13",
98
+ "@types/node": "^22.9.0",
99
+ "@types/pdfmake": "^0.3.2",
100
+ "@types/react": "^19.2.14",
101
+ "fastify": "^5.12.5",
102
+ "lucide-react": "^1.11.0",
103
+ "pdfmake": "^0.3.7",
104
+ "react": "^19.2.5",
105
+ "react-router-dom": "^7.18.2",
106
+ "typescript": "^5.9.3",
107
+ "vitest": "^4.1.11",
108
+ "zod": "^4.2.0",
109
+ "@endora-commerce/admin-kit": "0.100.0",
110
+ "@endora-commerce/contracts": "0.100.0",
111
+ "@endora-commerce/email-components": "0.100.0",
112
+ "@endora-commerce/page-builder-admin": "0.100.0",
113
+ "@endora-commerce/page-builder-core": "0.100.0",
114
+ "@endora-commerce/platform": "0.100.0"
115
+ },
116
+ "scripts": {
117
+ "build": "tsc -p tsconfig.build.json && tsc -p tsconfig.ui.json",
118
+ "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.ui.json --noEmit",
119
+ "lint": "eslint src",
120
+ "test": "vitest run"
121
+ }
6
122
  }
package/tailwind.css ADDED
@@ -0,0 +1,14 @@
1
+ /* @endora-commerce/mod-invoices — AUTO-GENERATED by `pnpm --filter backend run manifests:generate`.
2
+ *
3
+ * The `@source` directives this package asks its host to scan
4
+ * (`specs/110-instance-repository/contracts/admin-stylesheet-composition.md` R1).
5
+ * They resolve relative to **this file**, so they hold wherever the package is
6
+ * installed — a workspace link here, `node_modules` in a client's instance.
7
+ *
8
+ * The `dist` line is what a published tarball ships and is what an instance
9
+ * scans; the `src` line is inert there and is what keeps `pnpm --filter admin
10
+ * run dev` reading source in this repository. Do not edit: run
11
+ * `pnpm --filter backend run manifests:generate`.
12
+ */
13
+ @source "./dist/admin";
14
+ @source "./src/admin";