@dainamite/billing 0.19.0 → 0.21.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 (614) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +14 -0
  3. package/dist/modules/billing/acl.js +13 -1
  4. package/dist/modules/billing/acl.js.map +2 -2
  5. package/dist/modules/billing/api/accounts/[id]/summary/route.js +52 -0
  6. package/dist/modules/billing/api/accounts/[id]/summary/route.js.map +7 -0
  7. package/dist/modules/billing/api/accounts/route.js +46 -4
  8. package/dist/modules/billing/api/accounts/route.js.map +2 -2
  9. package/dist/modules/billing/api/export/account/[id]/route.js +16 -12
  10. package/dist/modules/billing/api/export/account/[id]/route.js.map +2 -2
  11. package/dist/modules/billing/api/invoices/[id]/memos/route.js +54 -0
  12. package/dist/modules/billing/api/invoices/[id]/memos/route.js.map +7 -0
  13. package/dist/modules/billing/api/invoices/[id]/pdf/route.js +69 -0
  14. package/dist/modules/billing/api/invoices/[id]/pdf/route.js.map +7 -0
  15. package/dist/modules/billing/api/invoices/[id]/route.js +44 -24
  16. package/dist/modules/billing/api/invoices/[id]/route.js.map +2 -2
  17. package/dist/modules/billing/api/invoices/[id]/send/route.js +107 -0
  18. package/dist/modules/billing/api/invoices/[id]/send/route.js.map +7 -0
  19. package/dist/modules/billing/api/invoices/add-line/route.js +3 -3
  20. package/dist/modules/billing/api/invoices/add-line/route.js.map +2 -2
  21. package/dist/modules/billing/api/invoices/delete-draft/route.js +33 -0
  22. package/dist/modules/billing/api/invoices/delete-draft/route.js.map +7 -0
  23. package/dist/modules/billing/api/invoices/edit-line/route.js +3 -3
  24. package/dist/modules/billing/api/invoices/edit-line/route.js.map +2 -2
  25. package/dist/modules/billing/api/invoices/post/route.js +2 -2
  26. package/dist/modules/billing/api/invoices/post/route.js.map +2 -2
  27. package/dist/modules/billing/api/invoices/remove-line/route.js +3 -3
  28. package/dist/modules/billing/api/invoices/remove-line/route.js.map +2 -2
  29. package/dist/modules/billing/api/invoices/route.js +45 -46
  30. package/dist/modules/billing/api/invoices/route.js.map +2 -2
  31. package/dist/modules/billing/api/items/bulk/route.js +1 -1
  32. package/dist/modules/billing/api/items/bulk/route.js.map +2 -2
  33. package/dist/modules/billing/api/items/change-price/route.js +44 -0
  34. package/dist/modules/billing/api/items/change-price/route.js.map +7 -0
  35. package/dist/modules/billing/api/items/route.js +19 -7
  36. package/dist/modules/billing/api/items/route.js.map +2 -2
  37. package/dist/modules/billing/api/payment-imports/[id]/route.js +49 -0
  38. package/dist/modules/billing/api/payment-imports/[id]/route.js.map +7 -0
  39. package/dist/modules/billing/api/payment-imports/route.js +57 -0
  40. package/dist/modules/billing/api/payment-imports/route.js.map +7 -0
  41. package/dist/modules/billing/api/payments/[id]/route.js +60 -0
  42. package/dist/modules/billing/api/payments/[id]/route.js.map +7 -0
  43. package/dist/modules/billing/api/payments/allocate/route.js +35 -0
  44. package/dist/modules/billing/api/payments/allocate/route.js.map +7 -0
  45. package/dist/modules/billing/api/payments/assign/route.js +36 -0
  46. package/dist/modules/billing/api/payments/assign/route.js.map +7 -0
  47. package/dist/modules/billing/api/payments/convert-to-topup/route.js +35 -0
  48. package/dist/modules/billing/api/payments/convert-to-topup/route.js.map +7 -0
  49. package/dist/modules/billing/api/payments/ignore/route.js +35 -0
  50. package/dist/modules/billing/api/payments/ignore/route.js.map +7 -0
  51. package/dist/modules/billing/api/payments/import/route.js +63 -0
  52. package/dist/modules/billing/api/payments/import/route.js.map +7 -0
  53. package/dist/modules/billing/api/payments/restore/route.js +35 -0
  54. package/dist/modules/billing/api/payments/restore/route.js.map +7 -0
  55. package/dist/modules/billing/api/payments/route.js +114 -0
  56. package/dist/modules/billing/api/payments/route.js.map +7 -0
  57. package/dist/modules/billing/api/payments/unallocate/route.js +35 -0
  58. package/dist/modules/billing/api/payments/unallocate/route.js.map +7 -0
  59. package/dist/modules/billing/api/payments/unassign/route.js +35 -0
  60. package/dist/modules/billing/api/payments/unassign/route.js.map +7 -0
  61. package/dist/modules/billing/api/run-outcomes/route.js +44 -7
  62. package/dist/modules/billing/api/run-outcomes/route.js.map +2 -2
  63. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js +61 -0
  64. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js.map +7 -0
  65. package/dist/modules/billing/api/runs/[id]/route.js +53 -0
  66. package/dist/modules/billing/api/runs/[id]/route.js.map +7 -0
  67. package/dist/modules/billing/api/runs/retry-failed/route.js +3 -3
  68. package/dist/modules/billing/api/runs/retry-failed/route.js.map +2 -2
  69. package/dist/modules/billing/api/runs/route.js +11 -5
  70. package/dist/modules/billing/api/runs/route.js.map +2 -2
  71. package/dist/modules/billing/api/settings/number-preview/route.js +42 -0
  72. package/dist/modules/billing/api/settings/number-preview/route.js.map +7 -0
  73. package/dist/modules/billing/api/settings/route.js +92 -0
  74. package/dist/modules/billing/api/settings/route.js.map +7 -0
  75. package/dist/modules/billing/api/statements/route.js +3 -0
  76. package/dist/modules/billing/api/statements/route.js.map +2 -2
  77. package/dist/modules/billing/api/test-invoices/wipe/route.js +2 -2
  78. package/dist/modules/billing/api/test-invoices/wipe/route.js.map +2 -2
  79. package/dist/modules/billing/backend/billing/accounts/[id]/page.js +121 -232
  80. package/dist/modules/billing/backend/billing/accounts/[id]/page.js.map +2 -2
  81. package/dist/modules/billing/backend/billing/accounts/create/page.js +6 -0
  82. package/dist/modules/billing/backend/billing/accounts/create/page.js.map +2 -2
  83. package/dist/modules/billing/backend/billing/accounts/page.js +63 -4
  84. package/dist/modules/billing/backend/billing/accounts/page.js.map +2 -2
  85. package/dist/modules/billing/backend/billing/invoices/[id]/page.js +297 -65
  86. package/dist/modules/billing/backend/billing/invoices/[id]/page.js.map +3 -3
  87. package/dist/modules/billing/backend/billing/invoices/page.js +6 -172
  88. package/dist/modules/billing/backend/billing/invoices/page.js.map +2 -2
  89. package/dist/modules/billing/backend/billing/items/[id]/page.js +51 -7
  90. package/dist/modules/billing/backend/billing/items/[id]/page.js.map +2 -2
  91. package/dist/modules/billing/backend/billing/items/create/page.js +9 -6
  92. package/dist/modules/billing/backend/billing/items/create/page.js.map +2 -2
  93. package/dist/modules/billing/backend/billing/items/page.js +8 -2
  94. package/dist/modules/billing/backend/billing/items/page.js.map +2 -2
  95. package/dist/modules/billing/backend/billing/payments/[id]/page.js +297 -0
  96. package/dist/modules/billing/backend/billing/payments/[id]/page.js.map +7 -0
  97. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js +21 -0
  98. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js.map +7 -0
  99. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js +74 -0
  100. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js.map +7 -0
  101. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js +21 -0
  102. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js.map +7 -0
  103. package/dist/modules/billing/backend/billing/payments/page.js +58 -0
  104. package/dist/modules/billing/backend/billing/payments/page.js.map +7 -0
  105. package/dist/modules/billing/backend/billing/payments/page.meta.js +18 -0
  106. package/dist/modules/billing/backend/billing/payments/page.meta.js.map +7 -0
  107. package/dist/modules/billing/backend/billing/runs/[id]/page.js +49 -14
  108. package/dist/modules/billing/backend/billing/runs/[id]/page.js.map +2 -2
  109. package/dist/modules/billing/backend/billing/runs/page.js +58 -7
  110. package/dist/modules/billing/backend/billing/runs/page.js.map +2 -2
  111. package/dist/modules/billing/backend/billing/statements/[id]/page.js +61 -6
  112. package/dist/modules/billing/backend/billing/statements/[id]/page.js.map +2 -2
  113. package/dist/modules/billing/backend/billing/statements/page.js +1 -1
  114. package/dist/modules/billing/backend/billing/statements/page.js.map +2 -2
  115. package/dist/modules/billing/backend/billing/topups/page.js +1 -1
  116. package/dist/modules/billing/backend/billing/topups/page.js.map +2 -2
  117. package/dist/modules/billing/backend/billing/transactions/page.js +1 -1
  118. package/dist/modules/billing/backend/billing/transactions/page.js.map +2 -2
  119. package/dist/modules/billing/backend/billing/usage/create/page.js +3 -2
  120. package/dist/modules/billing/backend/billing/usage/create/page.js.map +2 -2
  121. package/dist/modules/billing/backend/config/billing/page.js +472 -0
  122. package/dist/modules/billing/backend/config/billing/page.js.map +7 -0
  123. package/dist/modules/billing/backend/config/billing/page.meta.js +19 -0
  124. package/dist/modules/billing/backend/config/billing/page.meta.js.map +7 -0
  125. package/dist/modules/billing/ce.js.map +2 -2
  126. package/dist/modules/billing/cli.js +22 -1
  127. package/dist/modules/billing/cli.js.map +2 -2
  128. package/dist/modules/billing/commands/accounts.js +6 -0
  129. package/dist/modules/billing/commands/accounts.js.map +2 -2
  130. package/dist/modules/billing/commands/index.js +3 -0
  131. package/dist/modules/billing/commands/index.js.map +2 -2
  132. package/dist/modules/billing/commands/invoices.js +272 -170
  133. package/dist/modules/billing/commands/invoices.js.map +2 -2
  134. package/dist/modules/billing/commands/items.js +108 -0
  135. package/dist/modules/billing/commands/items.js.map +2 -2
  136. package/dist/modules/billing/commands/memos.js +179 -0
  137. package/dist/modules/billing/commands/memos.js.map +7 -0
  138. package/dist/modules/billing/commands/payments.js +379 -0
  139. package/dist/modules/billing/commands/payments.js.map +7 -0
  140. package/dist/modules/billing/commands/runs.js +154 -7
  141. package/dist/modules/billing/commands/runs.js.map +2 -2
  142. package/dist/modules/billing/commands/settings.js +59 -0
  143. package/dist/modules/billing/commands/settings.js.map +7 -0
  144. package/dist/modules/billing/commands/topups.js +9 -2
  145. package/dist/modules/billing/commands/topups.js.map +2 -2
  146. package/dist/modules/billing/commands/transactions.js +2 -2
  147. package/dist/modules/billing/commands/transactions.js.map +2 -2
  148. package/dist/modules/billing/components/AccountForm.js +149 -42
  149. package/dist/modules/billing/components/AccountForm.js.map +2 -2
  150. package/dist/modules/billing/components/AccountInvoicesSection.js +64 -0
  151. package/dist/modules/billing/components/AccountInvoicesSection.js.map +7 -0
  152. package/dist/modules/billing/components/AccountPaymentsSection.js +43 -0
  153. package/dist/modules/billing/components/AccountPaymentsSection.js.map +7 -0
  154. package/dist/modules/billing/components/AccountPicker.js +56 -0
  155. package/dist/modules/billing/components/AccountPicker.js.map +7 -0
  156. package/dist/modules/billing/components/AllocatePaymentDialog.js +134 -0
  157. package/dist/modules/billing/components/AllocatePaymentDialog.js.map +7 -0
  158. package/dist/modules/billing/components/BillingDataTable.js +21 -0
  159. package/dist/modules/billing/components/BillingDataTable.js.map +7 -0
  160. package/dist/modules/billing/components/BillingSettingsLink.js +19 -0
  161. package/dist/modules/billing/components/BillingSettingsLink.js.map +7 -0
  162. package/dist/modules/billing/components/ChangeItemPriceDialog.js +158 -0
  163. package/dist/modules/billing/components/ChangeItemPriceDialog.js.map +7 -0
  164. package/dist/modules/billing/components/CreateMemoDialog.js +200 -0
  165. package/dist/modules/billing/components/CreateMemoDialog.js.map +7 -0
  166. package/dist/modules/billing/components/CustomerLabel.js +33 -0
  167. package/dist/modules/billing/components/CustomerLabel.js.map +7 -0
  168. package/dist/modules/billing/components/InvoicesTable.js +270 -0
  169. package/dist/modules/billing/components/InvoicesTable.js.map +7 -0
  170. package/dist/modules/billing/components/ItemForm.js +176 -44
  171. package/dist/modules/billing/components/ItemForm.js.map +2 -2
  172. package/dist/modules/billing/components/ItemPriceField.js +46 -0
  173. package/dist/modules/billing/components/ItemPriceField.js.map +7 -0
  174. package/dist/modules/billing/components/LineFormDialog.js +25 -2
  175. package/dist/modules/billing/components/LineFormDialog.js.map +2 -2
  176. package/dist/modules/billing/components/ManualPaymentDialog.js +122 -0
  177. package/dist/modules/billing/components/ManualPaymentDialog.js.map +7 -0
  178. package/dist/modules/billing/components/MoneyInput.js +14 -0
  179. package/dist/modules/billing/components/MoneyInput.js.map +7 -0
  180. package/dist/modules/billing/components/PaymentUploadDialog.js +115 -0
  181. package/dist/modules/billing/components/PaymentUploadDialog.js.map +7 -0
  182. package/dist/modules/billing/components/PaymentsTable.js +171 -0
  183. package/dist/modules/billing/components/PaymentsTable.js.map +7 -0
  184. package/dist/modules/billing/components/PostRunDraftsButton.js +105 -0
  185. package/dist/modules/billing/components/PostRunDraftsButton.js.map +7 -0
  186. package/dist/modules/billing/components/PrepaidPanel.js +14 -4
  187. package/dist/modules/billing/components/PrepaidPanel.js.map +2 -2
  188. package/dist/modules/billing/components/RunCyclesSection.js +209 -0
  189. package/dist/modules/billing/components/RunCyclesSection.js.map +7 -0
  190. package/dist/modules/billing/components/TestRunActions.js +127 -0
  191. package/dist/modules/billing/components/TestRunActions.js.map +7 -0
  192. package/dist/modules/billing/components/account/AccountItemsTab.js +157 -0
  193. package/dist/modules/billing/components/account/AccountItemsTab.js.map +7 -0
  194. package/dist/modules/billing/components/account/AccountRunBillingDialog.js +122 -0
  195. package/dist/modules/billing/components/account/AccountRunBillingDialog.js.map +7 -0
  196. package/dist/modules/billing/components/account/AccountRunsTab.js +152 -0
  197. package/dist/modules/billing/components/account/AccountRunsTab.js.map +7 -0
  198. package/dist/modules/billing/components/account/AccountStatementsTab.js +98 -0
  199. package/dist/modules/billing/components/account/AccountStatementsTab.js.map +7 -0
  200. package/dist/modules/billing/components/account/AccountSummaryCards.js +125 -0
  201. package/dist/modules/billing/components/account/AccountSummaryCards.js.map +7 -0
  202. package/dist/modules/billing/components/account/AccountUsageTab.js +91 -0
  203. package/dist/modules/billing/components/account/AccountUsageTab.js.map +7 -0
  204. package/dist/modules/billing/components/account/AccountView.js +73 -0
  205. package/dist/modules/billing/components/account/AccountView.js.map +7 -0
  206. package/dist/modules/billing/components/account/accountRow.js +39 -0
  207. package/dist/modules/billing/components/account/accountRow.js.map +7 -0
  208. package/dist/modules/billing/components/customerNames.js +42 -0
  209. package/dist/modules/billing/components/customerNames.js.map +7 -0
  210. package/dist/modules/billing/data/entities.js +615 -59
  211. package/dist/modules/billing/data/entities.js.map +2 -2
  212. package/dist/modules/billing/data/entityIds.js +10 -1
  213. package/dist/modules/billing/data/entityIds.js.map +2 -2
  214. package/dist/modules/billing/data/validators.js +269 -15
  215. package/dist/modules/billing/data/validators.js.map +2 -2
  216. package/dist/modules/billing/events.js +70 -0
  217. package/dist/modules/billing/events.js.map +2 -2
  218. package/dist/modules/billing/i18n/en.json +457 -21
  219. package/dist/modules/billing/i18n/pl.json +457 -21
  220. package/dist/modules/billing/index.js +6 -2
  221. package/dist/modules/billing/index.js.map +2 -2
  222. package/dist/modules/billing/lib/accountFinancials.js +58 -0
  223. package/dist/modules/billing/lib/accountFinancials.js.map +7 -0
  224. package/dist/modules/billing/lib/accountLock.js +14 -0
  225. package/dist/modules/billing/lib/accountLock.js.map +7 -0
  226. package/dist/modules/billing/lib/accountStatus.js +9 -7
  227. package/dist/modules/billing/lib/accountStatus.js.map +2 -2
  228. package/dist/modules/billing/lib/accountSummary.js +106 -0
  229. package/dist/modules/billing/lib/accountSummary.js.map +7 -0
  230. package/dist/modules/billing/lib/allocation.js +356 -0
  231. package/dist/modules/billing/lib/allocation.js.map +7 -0
  232. package/dist/modules/billing/lib/allocationEvents.js +22 -0
  233. package/dist/modules/billing/lib/allocationEvents.js.map +7 -0
  234. package/dist/modules/billing/lib/billPeriod.js +15 -1
  235. package/dist/modules/billing/lib/billPeriod.js.map +2 -2
  236. package/dist/modules/billing/lib/billRunEngine.js +241 -106
  237. package/dist/modules/billing/lib/billRunEngine.js.map +2 -2
  238. package/dist/modules/billing/lib/billRunLabel.js.map +1 -1
  239. package/dist/modules/billing/lib/billingSettings.js +116 -0
  240. package/dist/modules/billing/lib/billingSettings.js.map +7 -0
  241. package/dist/modules/billing/lib/commandRoute.js +81 -0
  242. package/dist/modules/billing/lib/commandRoute.js.map +7 -0
  243. package/dist/modules/billing/lib/customerLookup.js +97 -0
  244. package/dist/modules/billing/lib/customerLookup.js.map +7 -0
  245. package/dist/modules/billing/lib/dateOnly.js +13 -0
  246. package/dist/modules/billing/lib/dateOnly.js.map +7 -0
  247. package/dist/modules/billing/lib/documentParties.js +16 -0
  248. package/dist/modules/billing/lib/documentParties.js.map +7 -0
  249. package/dist/modules/billing/lib/documentTypes.js +27 -0
  250. package/dist/modules/billing/lib/documentTypes.js.map +7 -0
  251. package/dist/modules/billing/lib/dueDate.js +18 -0
  252. package/dist/modules/billing/lib/dueDate.js.map +7 -0
  253. package/dist/modules/billing/lib/iban.js +29 -0
  254. package/dist/modules/billing/lib/iban.js.map +7 -0
  255. package/dist/modules/billing/lib/invoiceDelivery.js +131 -0
  256. package/dist/modules/billing/lib/invoiceDelivery.js.map +7 -0
  257. package/dist/modules/billing/lib/invoiceLanguages.js +16 -0
  258. package/dist/modules/billing/lib/invoiceLanguages.js.map +7 -0
  259. package/dist/modules/billing/lib/invoiceWriter.js +107 -99
  260. package/dist/modules/billing/lib/invoiceWriter.js.map +2 -2
  261. package/dist/modules/billing/lib/itemBillingState.js +27 -0
  262. package/dist/modules/billing/lib/itemBillingState.js.map +7 -0
  263. package/dist/modules/billing/lib/itemPriceChange.js +18 -0
  264. package/dist/modules/billing/lib/itemPriceChange.js.map +7 -0
  265. package/dist/modules/billing/lib/itemSelector.js.map +2 -2
  266. package/dist/modules/billing/lib/lineAmounts.js +32 -0
  267. package/dist/modules/billing/lib/lineAmounts.js.map +7 -0
  268. package/dist/modules/billing/lib/memoGuards.js +25 -0
  269. package/dist/modules/billing/lib/memoGuards.js.map +7 -0
  270. package/dist/modules/billing/lib/navigation.js +48 -0
  271. package/dist/modules/billing/lib/navigation.js.map +7 -0
  272. package/dist/modules/billing/lib/numbering.js +120 -0
  273. package/dist/modules/billing/lib/numbering.js.map +7 -0
  274. package/dist/modules/billing/lib/overdue.js +36 -0
  275. package/dist/modules/billing/lib/overdue.js.map +7 -0
  276. package/dist/modules/billing/lib/paymentCsv.js +125 -0
  277. package/dist/modules/billing/lib/paymentCsv.js.map +7 -0
  278. package/dist/modules/billing/lib/paymentGateway.js +15 -0
  279. package/dist/modules/billing/lib/paymentGateway.js.map +7 -0
  280. package/dist/modules/billing/lib/paymentImport.js +164 -0
  281. package/dist/modules/billing/lib/paymentImport.js.map +7 -0
  282. package/dist/modules/billing/lib/paymentMatcher.js +36 -0
  283. package/dist/modules/billing/lib/paymentMatcher.js.map +7 -0
  284. package/dist/modules/billing/lib/pdf/attachmentStore.js +46 -0
  285. package/dist/modules/billing/lib/pdf/attachmentStore.js.map +7 -0
  286. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js +7 -0
  287. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js.map +7 -0
  288. package/dist/modules/billing/lib/pdf/invoiceModel.js +194 -0
  289. package/dist/modules/billing/lib/pdf/invoiceModel.js.map +7 -0
  290. package/dist/modules/billing/lib/pdf/invoicePdf.js +165 -0
  291. package/dist/modules/billing/lib/pdf/invoicePdf.js.map +7 -0
  292. package/dist/modules/billing/lib/pdf/invoiceTemplate.js +274 -0
  293. package/dist/modules/billing/lib/pdf/invoiceTemplate.js.map +7 -0
  294. package/dist/modules/billing/lib/prepaidConfig.js +17 -25
  295. package/dist/modules/billing/lib/prepaidConfig.js.map +2 -2
  296. package/dist/modules/billing/lib/prepaidConsume.js +26 -7
  297. package/dist/modules/billing/lib/prepaidConsume.js.map +2 -2
  298. package/dist/modules/billing/lib/prepaidPeriodClose.js +277 -158
  299. package/dist/modules/billing/lib/prepaidPeriodClose.js.map +2 -2
  300. package/dist/modules/billing/lib/prepaidTaxPoint.js +37 -0
  301. package/dist/modules/billing/lib/prepaidTaxPoint.js.map +7 -0
  302. package/dist/modules/billing/lib/seeds/demo.js +51 -3
  303. package/dist/modules/billing/lib/seeds/demo.js.map +2 -2
  304. package/dist/modules/billing/lib/seeds/paymentsSample.js +93 -0
  305. package/dist/modules/billing/lib/seeds/paymentsSample.js.map +7 -0
  306. package/dist/modules/billing/lib/seeds/sellerSettings.js +41 -0
  307. package/dist/modules/billing/lib/seeds/sellerSettings.js.map +7 -0
  308. package/dist/modules/billing/lib/servicePeriods.js +121 -0
  309. package/dist/modules/billing/lib/servicePeriods.js.map +7 -0
  310. package/dist/modules/billing/lib/tenantLock.js.map +1 -1
  311. package/dist/modules/billing/lib/testRunCleanup.js +24 -0
  312. package/dist/modules/billing/lib/testRunCleanup.js.map +7 -0
  313. package/dist/modules/billing/lib/topupCapture.js +2 -2
  314. package/dist/modules/billing/lib/topupCapture.js.map +2 -2
  315. package/dist/modules/billing/lib/topupReceipt.js +58 -79
  316. package/dist/modules/billing/lib/topupReceipt.js.map +2 -2
  317. package/dist/modules/billing/lib/usageRater.js.map +1 -1
  318. package/dist/modules/billing/lib/usageRunner.js +14 -6
  319. package/dist/modules/billing/lib/usageRunner.js.map +2 -2
  320. package/dist/modules/billing/lib/vat.js +39 -0
  321. package/dist/modules/billing/lib/vat.js.map +7 -0
  322. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js +15 -0
  323. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js.map +7 -0
  324. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js +25 -0
  325. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js.map +7 -0
  326. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js +115 -0
  327. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js.map +7 -0
  328. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js +47 -0
  329. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js.map +7 -0
  330. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js +89 -0
  331. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js.map +7 -0
  332. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js +17 -0
  333. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js.map +7 -0
  334. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js +27 -0
  335. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js.map +7 -0
  336. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js +29 -0
  337. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js.map +7 -0
  338. package/dist/modules/billing/setup.js +7 -184
  339. package/dist/modules/billing/setup.js.map +2 -2
  340. package/dist/modules/billing/subscribers/credit-memo-auto-send.js +16 -0
  341. package/dist/modules/billing/subscribers/credit-memo-auto-send.js.map +7 -0
  342. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js +16 -0
  343. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js.map +7 -0
  344. package/dist/modules/billing/subscribers/debit-memo-auto-send.js +16 -0
  345. package/dist/modules/billing/subscribers/debit-memo-auto-send.js.map +7 -0
  346. package/dist/modules/billing/subscribers/invoice-apply-credit.js +34 -0
  347. package/dist/modules/billing/subscribers/invoice-apply-credit.js.map +7 -0
  348. package/dist/modules/billing/subscribers/invoice-auto-send.js +30 -0
  349. package/dist/modules/billing/subscribers/invoice-auto-send.js.map +7 -0
  350. package/dist/modules/billing/subscribers/payment-captured-to-paid.js +69 -33
  351. package/dist/modules/billing/subscribers/payment-captured-to-paid.js.map +2 -2
  352. package/dist/modules/billing/subscribers/prepaid-topup-captured.js +4 -6
  353. package/dist/modules/billing/subscribers/prepaid-topup-captured.js.map +2 -2
  354. package/dist/modules/billing/workers/reap-stale-bill-runs.js +2 -2
  355. package/dist/modules/billing/workers/reap-stale-bill-runs.js.map +2 -2
  356. package/generated/entities/billing_account/index.ts +26 -0
  357. package/generated/entities/billing_account_balance/index.ts +13 -0
  358. package/generated/entities/billing_account_transaction/index.ts +21 -0
  359. package/generated/entities/billing_account_usage/index.ts +18 -0
  360. package/generated/entities/billing_allocation/index.ts +18 -0
  361. package/generated/entities/billing_document_sequence/index.ts +11 -0
  362. package/generated/entities/billing_draft_invoice_edit/index.ts +14 -0
  363. package/generated/entities/billing_invoice/index.ts +38 -0
  364. package/generated/entities/billing_invoice_line/index.ts +24 -0
  365. package/generated/entities/billing_item/index.ts +26 -0
  366. package/generated/entities/billing_payment/index.ts +25 -0
  367. package/generated/entities/billing_payment_import/index.ts +14 -0
  368. package/generated/entities/billing_run/index.ts +20 -0
  369. package/generated/entities/billing_run_outcome/index.ts +18 -0
  370. package/generated/entities/billing_settings/index.ts +26 -0
  371. package/generated/entities/billing_statement/index.ts +22 -0
  372. package/generated/entities/billing_topup/index.ts +20 -0
  373. package/generated/entities.ids.generated.ts +35 -0
  374. package/package.json +15 -10
  375. package/src/modules/billing/__integration__/TC-BILL-004.spec.ts +170 -0
  376. package/src/modules/billing/__integration__/TC-BILL-005.spec.ts +134 -0
  377. package/src/modules/billing/__integration__/TC-BILL-006.spec.ts +101 -0
  378. package/src/modules/billing/__integration__/TC-BILL-007.spec.ts +140 -0
  379. package/src/modules/billing/__integration__/TC-BILL-008.spec.ts +108 -0
  380. package/src/modules/billing/__integration__/TC-BILL-009.spec.ts +113 -0
  381. package/src/modules/billing/__integration__/TC-BILL-010.spec.ts +118 -0
  382. package/src/modules/billing/__integration__/TC-BILL-011.spec.ts +142 -0
  383. package/src/modules/billing/__integration__/TC-BILL-012.spec.ts +115 -0
  384. package/src/modules/billing/__integration__/TC-BILL-013.spec.ts +118 -0
  385. package/src/modules/billing/__integration__/sellerSettings.ts +24 -0
  386. package/src/modules/billing/__tests__/commands/invoices.test.ts +437 -355
  387. package/src/modules/billing/__tests__/commands/itemsBulk.test.ts +33 -0
  388. package/src/modules/billing/__tests__/commands/memos.test.ts +205 -0
  389. package/src/modules/billing/__tests__/commands/payments.test.ts +241 -0
  390. package/src/modules/billing/__tests__/commands/runsDelete.test.ts +146 -0
  391. package/src/modules/billing/__tests__/commands/runsPostDrafts.test.ts +106 -0
  392. package/src/modules/billing/__tests__/commands/topups.test.ts +11 -0
  393. package/src/modules/billing/__tests__/entityRegistry.test.ts +326 -0
  394. package/src/modules/billing/__tests__/events.test.ts +142 -0
  395. package/src/modules/billing/__tests__/helpers/prepaidMockEm.ts +28 -11
  396. package/src/modules/billing/__tests__/lib/accountFinancials.test.ts +53 -0
  397. package/src/modules/billing/__tests__/lib/accountSummary.test.ts +97 -0
  398. package/src/modules/billing/__tests__/lib/allocation.test.ts +319 -0
  399. package/src/modules/billing/__tests__/lib/billRunEngine.test.ts +231 -20
  400. package/src/modules/billing/__tests__/lib/billingSettings.test.ts +109 -0
  401. package/src/modules/billing/__tests__/lib/customerLookup.test.ts +156 -0
  402. package/src/modules/billing/__tests__/lib/dueDate.test.ts +35 -0
  403. package/src/modules/billing/__tests__/lib/iban.test.ts +38 -0
  404. package/src/modules/billing/__tests__/lib/invoiceDelivery.test.ts +189 -0
  405. package/src/modules/billing/__tests__/lib/invoiceWriter.test.ts +212 -10
  406. package/src/modules/billing/__tests__/lib/itemBillingState.test.ts +42 -0
  407. package/src/modules/billing/__tests__/lib/itemPriceChange.test.ts +165 -0
  408. package/src/modules/billing/__tests__/lib/lineAmounts.test.ts +86 -0
  409. package/src/modules/billing/__tests__/lib/navigation.test.ts +71 -0
  410. package/src/modules/billing/__tests__/lib/numbering.test.ts +91 -0
  411. package/src/modules/billing/__tests__/lib/overdue.test.ts +36 -0
  412. package/src/modules/billing/__tests__/lib/paymentCsv.test.ts +148 -0
  413. package/src/modules/billing/__tests__/lib/paymentImport.test.ts +113 -0
  414. package/src/modules/billing/__tests__/lib/paymentsSample.test.ts +73 -0
  415. package/src/modules/billing/__tests__/lib/pdf/invoicePdf.test.ts +199 -0
  416. package/src/modules/billing/__tests__/lib/pdf/invoicePdfService.test.ts +147 -0
  417. package/src/modules/billing/__tests__/lib/prepaidPeriodClose.test.ts +374 -98
  418. package/src/modules/billing/__tests__/lib/prepaidTaxPoint.test.ts +118 -0
  419. package/src/modules/billing/__tests__/lib/seedsDemo.test.ts +53 -2
  420. package/src/modules/billing/__tests__/lib/sellerSettings.test.ts +28 -0
  421. package/src/modules/billing/__tests__/lib/servicePeriods.test.ts +190 -0
  422. package/src/modules/billing/__tests__/lib/topupCapture.test.ts +6 -28
  423. package/src/modules/billing/__tests__/lib/topupReceipt.test.ts +21 -52
  424. package/src/modules/billing/__tests__/lib/vat.test.ts +51 -0
  425. package/src/modules/billing/__tests__/package-isolation.test.ts +22 -8
  426. package/src/modules/billing/__tests__/setup.test.ts +13 -4
  427. package/src/modules/billing/__tests__/validators.test.ts +193 -3
  428. package/src/modules/billing/acl.ts +12 -0
  429. package/src/modules/billing/api/accounts/[id]/summary/route.ts +62 -0
  430. package/src/modules/billing/api/accounts/route.ts +58 -4
  431. package/src/modules/billing/api/export/account/[id]/route.ts +20 -18
  432. package/src/modules/billing/api/invoices/[id]/memos/route.ts +63 -0
  433. package/src/modules/billing/api/invoices/[id]/pdf/route.ts +79 -0
  434. package/src/modules/billing/api/invoices/[id]/route.ts +57 -70
  435. package/src/modules/billing/api/invoices/[id]/send/route.ts +127 -0
  436. package/src/modules/billing/api/invoices/add-line/route.ts +3 -3
  437. package/src/modules/billing/api/invoices/delete-draft/route.ts +33 -0
  438. package/src/modules/billing/api/invoices/edit-line/route.ts +4 -4
  439. package/src/modules/billing/api/invoices/post/route.ts +7 -6
  440. package/src/modules/billing/api/invoices/remove-line/route.ts +3 -3
  441. package/src/modules/billing/api/invoices/route.ts +81 -86
  442. package/src/modules/billing/api/items/bulk/route.ts +2 -1
  443. package/src/modules/billing/api/items/change-price/route.ts +54 -0
  444. package/src/modules/billing/api/items/route.ts +23 -7
  445. package/src/modules/billing/api/payment-imports/[id]/route.ts +49 -0
  446. package/src/modules/billing/api/payment-imports/route.ts +57 -0
  447. package/src/modules/billing/api/payments/[id]/route.ts +63 -0
  448. package/src/modules/billing/api/payments/allocate/route.ts +35 -0
  449. package/src/modules/billing/api/payments/assign/route.ts +36 -0
  450. package/src/modules/billing/api/payments/convert-to-topup/route.ts +35 -0
  451. package/src/modules/billing/api/payments/ignore/route.ts +35 -0
  452. package/src/modules/billing/api/payments/import/route.ts +72 -0
  453. package/src/modules/billing/api/payments/restore/route.ts +35 -0
  454. package/src/modules/billing/api/payments/route.ts +147 -0
  455. package/src/modules/billing/api/payments/unallocate/route.ts +35 -0
  456. package/src/modules/billing/api/payments/unassign/route.ts +35 -0
  457. package/src/modules/billing/api/run-outcomes/route.ts +50 -7
  458. package/src/modules/billing/api/runs/[id]/post-drafts/route.ts +71 -0
  459. package/src/modules/billing/api/runs/[id]/route.ts +59 -0
  460. package/src/modules/billing/api/runs/retry-failed/route.ts +4 -3
  461. package/src/modules/billing/api/runs/route.ts +17 -9
  462. package/src/modules/billing/api/settings/number-preview/route.ts +46 -0
  463. package/src/modules/billing/api/settings/route.ts +116 -0
  464. package/src/modules/billing/api/statements/route.ts +5 -0
  465. package/src/modules/billing/api/test-invoices/wipe/route.ts +2 -2
  466. package/src/modules/billing/backend/billing/accounts/[id]/page.tsx +151 -372
  467. package/src/modules/billing/backend/billing/accounts/create/page.tsx +6 -0
  468. package/src/modules/billing/backend/billing/accounts/page.tsx +71 -5
  469. package/src/modules/billing/backend/billing/invoices/[id]/page.tsx +445 -96
  470. package/src/modules/billing/backend/billing/invoices/page.tsx +8 -227
  471. package/src/modules/billing/backend/billing/items/[id]/page.tsx +75 -6
  472. package/src/modules/billing/backend/billing/items/create/page.tsx +13 -8
  473. package/src/modules/billing/backend/billing/items/page.tsx +19 -3
  474. package/src/modules/billing/backend/billing/payments/[id]/page.meta.ts +19 -0
  475. package/src/modules/billing/backend/billing/payments/[id]/page.tsx +415 -0
  476. package/src/modules/billing/backend/billing/payments/imports/[id]/page.meta.ts +19 -0
  477. package/src/modules/billing/backend/billing/payments/imports/[id]/page.tsx +106 -0
  478. package/src/modules/billing/backend/billing/payments/page.meta.ts +16 -0
  479. package/src/modules/billing/backend/billing/payments/page.tsx +56 -0
  480. package/src/modules/billing/backend/billing/runs/[id]/page.tsx +50 -19
  481. package/src/modules/billing/backend/billing/runs/page.tsx +60 -9
  482. package/src/modules/billing/backend/billing/statements/[id]/page.tsx +87 -6
  483. package/src/modules/billing/backend/billing/statements/page.tsx +2 -2
  484. package/src/modules/billing/backend/billing/topups/page.tsx +2 -2
  485. package/src/modules/billing/backend/billing/transactions/page.tsx +2 -2
  486. package/src/modules/billing/backend/billing/usage/create/page.tsx +3 -2
  487. package/src/modules/billing/backend/config/billing/page.meta.ts +21 -0
  488. package/src/modules/billing/backend/config/billing/page.tsx +549 -0
  489. package/src/modules/billing/ce.ts +8 -7
  490. package/src/modules/billing/cli.ts +31 -1
  491. package/src/modules/billing/commands/accounts.ts +6 -0
  492. package/src/modules/billing/commands/index.ts +3 -0
  493. package/src/modules/billing/commands/invoices.ts +371 -238
  494. package/src/modules/billing/commands/items.ts +143 -0
  495. package/src/modules/billing/commands/memos.ts +218 -0
  496. package/src/modules/billing/commands/payments.ts +428 -0
  497. package/src/modules/billing/commands/runs.ts +208 -6
  498. package/src/modules/billing/commands/settings.ts +77 -0
  499. package/src/modules/billing/commands/topups.ts +12 -3
  500. package/src/modules/billing/commands/transactions.ts +2 -2
  501. package/src/modules/billing/components/AccountForm.tsx +199 -53
  502. package/src/modules/billing/components/AccountInvoicesSection.tsx +75 -0
  503. package/src/modules/billing/components/AccountPaymentsSection.tsx +42 -0
  504. package/src/modules/billing/components/AccountPicker.tsx +70 -0
  505. package/src/modules/billing/components/AllocatePaymentDialog.tsx +167 -0
  506. package/src/modules/billing/components/BillingDataTable.tsx +34 -0
  507. package/src/modules/billing/components/BillingSettingsLink.tsx +25 -0
  508. package/src/modules/billing/components/ChangeItemPriceDialog.tsx +180 -0
  509. package/src/modules/billing/components/CreateMemoDialog.tsx +232 -0
  510. package/src/modules/billing/components/CustomerLabel.tsx +53 -0
  511. package/src/modules/billing/components/InvoicesTable.tsx +344 -0
  512. package/src/modules/billing/components/ItemForm.tsx +233 -44
  513. package/src/modules/billing/components/ItemPriceField.tsx +81 -0
  514. package/src/modules/billing/components/LineFormDialog.tsx +25 -1
  515. package/src/modules/billing/components/ManualPaymentDialog.tsx +140 -0
  516. package/src/modules/billing/components/MoneyInput.tsx +26 -0
  517. package/src/modules/billing/components/PaymentUploadDialog.tsx +148 -0
  518. package/src/modules/billing/components/PaymentsTable.tsx +213 -0
  519. package/src/modules/billing/components/PostRunDraftsButton.tsx +129 -0
  520. package/src/modules/billing/components/PrepaidPanel.tsx +20 -7
  521. package/src/modules/billing/components/RunCyclesSection.tsx +298 -0
  522. package/src/modules/billing/components/TestRunActions.tsx +152 -0
  523. package/src/modules/billing/components/account/AccountItemsTab.tsx +192 -0
  524. package/src/modules/billing/components/account/AccountRunBillingDialog.tsx +147 -0
  525. package/src/modules/billing/components/account/AccountRunsTab.tsx +201 -0
  526. package/src/modules/billing/components/account/AccountStatementsTab.tsx +120 -0
  527. package/src/modules/billing/components/account/AccountSummaryCards.tsx +153 -0
  528. package/src/modules/billing/components/account/AccountUsageTab.tsx +122 -0
  529. package/src/modules/billing/components/account/AccountView.tsx +101 -0
  530. package/src/modules/billing/components/account/accountRow.ts +70 -0
  531. package/src/modules/billing/components/customerNames.ts +62 -0
  532. package/src/modules/billing/data/entities.ts +685 -15
  533. package/src/modules/billing/data/entityIds.ts +25 -11
  534. package/src/modules/billing/data/validators.ts +388 -8
  535. package/src/modules/billing/events.ts +82 -3
  536. package/src/modules/billing/i18n/en.json +457 -21
  537. package/src/modules/billing/i18n/pl.json +457 -21
  538. package/src/modules/billing/index.ts +6 -2
  539. package/src/modules/billing/lib/accountFinancials.ts +84 -0
  540. package/src/modules/billing/lib/accountLock.ts +32 -0
  541. package/src/modules/billing/lib/accountStatus.ts +11 -9
  542. package/src/modules/billing/lib/accountSummary.ts +172 -0
  543. package/src/modules/billing/lib/allocation.ts +515 -0
  544. package/src/modules/billing/lib/allocationEvents.ts +26 -0
  545. package/src/modules/billing/lib/billPeriod.ts +19 -0
  546. package/src/modules/billing/lib/billRunEngine.ts +362 -162
  547. package/src/modules/billing/lib/billRunLabel.ts +1 -1
  548. package/src/modules/billing/lib/billingSettings.ts +145 -0
  549. package/src/modules/billing/lib/commandRoute.ts +112 -0
  550. package/src/modules/billing/lib/customerLookup.ts +157 -0
  551. package/src/modules/billing/lib/dateOnly.ts +22 -0
  552. package/src/modules/billing/lib/documentParties.ts +23 -0
  553. package/src/modules/billing/lib/documentTypes.ts +37 -0
  554. package/src/modules/billing/lib/dueDate.ts +26 -0
  555. package/src/modules/billing/lib/iban.ts +36 -0
  556. package/src/modules/billing/lib/invoiceDelivery.ts +197 -0
  557. package/src/modules/billing/lib/invoiceLanguages.ts +34 -0
  558. package/src/modules/billing/lib/invoiceWriter.ts +162 -148
  559. package/src/modules/billing/lib/itemBillingState.ts +67 -0
  560. package/src/modules/billing/lib/itemPriceChange.ts +56 -0
  561. package/src/modules/billing/lib/itemSelector.ts +4 -1
  562. package/src/modules/billing/lib/lineAmounts.ts +61 -0
  563. package/src/modules/billing/lib/memoGuards.ts +41 -0
  564. package/src/modules/billing/lib/navigation.ts +64 -0
  565. package/src/modules/billing/lib/numbering.ts +174 -0
  566. package/src/modules/billing/lib/overdue.ts +60 -0
  567. package/src/modules/billing/lib/paymentCsv.ts +171 -0
  568. package/src/modules/billing/lib/paymentGateway.ts +52 -0
  569. package/src/modules/billing/lib/paymentImport.ts +228 -0
  570. package/src/modules/billing/lib/paymentMatcher.ts +88 -0
  571. package/src/modules/billing/lib/pdf/attachmentStore.ts +60 -0
  572. package/src/modules/billing/lib/pdf/fonts/NotoSans-Bold.ttf +0 -0
  573. package/src/modules/billing/lib/pdf/fonts/NotoSans-Regular.ttf +0 -0
  574. package/src/modules/billing/lib/pdf/fonts/OFL.txt +93 -0
  575. package/src/modules/billing/lib/pdf/fonts/embeddedFonts.ts +9 -0
  576. package/src/modules/billing/lib/pdf/invoiceModel.ts +328 -0
  577. package/src/modules/billing/lib/pdf/invoicePdf.ts +216 -0
  578. package/src/modules/billing/lib/pdf/invoiceTemplate.ts +338 -0
  579. package/src/modules/billing/lib/prepaidConfig.ts +27 -36
  580. package/src/modules/billing/lib/prepaidConsume.ts +29 -6
  581. package/src/modules/billing/lib/prepaidPeriodClose.ts +410 -242
  582. package/src/modules/billing/lib/prepaidTaxPoint.ts +76 -0
  583. package/src/modules/billing/lib/seeds/demo.ts +79 -6
  584. package/src/modules/billing/lib/seeds/paymentsSample.ts +136 -0
  585. package/src/modules/billing/lib/seeds/sellerSettings.ts +78 -0
  586. package/src/modules/billing/lib/servicePeriods.ts +226 -0
  587. package/src/modules/billing/lib/tenantLock.ts +1 -1
  588. package/src/modules/billing/lib/testRunCleanup.ts +42 -0
  589. package/src/modules/billing/lib/topupCapture.ts +3 -4
  590. package/src/modules/billing/lib/topupReceipt.ts +70 -103
  591. package/src/modules/billing/lib/usageRater.ts +1 -1
  592. package/src/modules/billing/lib/usageRunner.ts +17 -5
  593. package/src/modules/billing/lib/vat.ts +56 -0
  594. package/src/modules/billing/migrations/Migration20261114000000_billing_customer_kind.ts +25 -0
  595. package/src/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.ts +37 -0
  596. package/src/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.ts +132 -0
  597. package/src/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.ts +58 -0
  598. package/src/modules/billing/migrations/Migration20261117000000_billing_payments.ts +97 -0
  599. package/src/modules/billing/migrations/Migration20261118000000_billing_memos.ts +21 -0
  600. package/src/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.ts +39 -0
  601. package/src/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.ts +35 -0
  602. package/src/modules/billing/setup.ts +11 -237
  603. package/src/modules/billing/subscribers/credit-memo-auto-send.ts +15 -0
  604. package/src/modules/billing/subscribers/debit-memo-apply-credit.ts +15 -0
  605. package/src/modules/billing/subscribers/debit-memo-auto-send.ts +15 -0
  606. package/src/modules/billing/subscribers/invoice-apply-credit.ts +39 -0
  607. package/src/modules/billing/subscribers/invoice-auto-send.ts +46 -0
  608. package/src/modules/billing/subscribers/payment-captured-to-paid.ts +84 -62
  609. package/src/modules/billing/subscribers/prepaid-topup-captured.ts +4 -8
  610. package/src/modules/billing/workers/reap-stale-bill-runs.ts +4 -4
  611. package/dist/modules/billing/lib/invoiceStatus.js +0 -38
  612. package/dist/modules/billing/lib/invoiceStatus.js.map +0 -7
  613. package/src/modules/billing/__tests__/lib/invoiceStatus.test.ts +0 -97
  614. package/src/modules/billing/lib/invoiceStatus.ts +0 -61
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Human-readable label for a Bill Run.
3
3
  *
4
- * The BillRun entity has no `name` column — the engine keys runs by id.
4
+ * The BillingRun entity has no `name` column — the engine keys runs by id.
5
5
  * The admin UI derives a stable, scannable label from the run's as-of
6
6
  * date so operators see `BILL_RUN_2026-05-20` instead of a raw UUID.
7
7
  */
@@ -0,0 +1,145 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql'
2
+ import { BillingSettings } from '../data/entities'
3
+ import { DEFAULT_NUMBER_MASKS, maskFor, type DocumentSeries } from './numbering'
4
+
5
+ /**
6
+ * Per-organization billing settings (Spec 0, E-D2 / E-D5).
7
+ *
8
+ * Replaces the tenant-wide core `configs` rows billing used to seed. One row
9
+ * per (tenant, organization), created lazily with today's defaults on first
10
+ * read so every caller can rely on it existing. Spec B adds the seller /
11
+ * payment / document fields (the INSERT below relies on their DB defaults:
12
+ * 14 days terms, 23 % VAT, seller fields empty).
13
+ */
14
+
15
+ export type SettingsScope = { tenantId: string; organizationId: string }
16
+
17
+ export const BILLING_SETTINGS_DEFAULTS = {
18
+ lowBalanceThresholdDefault: '0',
19
+ nearLimitBufferDefault: '0',
20
+ statementEnabled: true,
21
+ topupTaxRate: '0',
22
+ topupProvider: 'stripe',
23
+ numberMasks: { ...DEFAULT_NUMBER_MASKS } as Record<string, string>,
24
+ defaultPaymentTermsDays: 14,
25
+ defaultTaxRate: '23',
26
+ prepaidTaxPoint: 'topup',
27
+ } as const
28
+
29
+ /**
30
+ * VAT rate printed on top-up receipts (Spec F, P-D11): `topup_tax_rate` when
31
+ * the prepaid tax point is `topup`, 0 in `consumption` mode (VAT is charged
32
+ * on each debit instead — never twice).
33
+ */
34
+ export function receiptTaxRate(settings: Pick<BillingSettings, 'topupTaxRate' | 'prepaidTaxPoint'>): number {
35
+ if (settings.prepaidTaxPoint === 'consumption') return 0
36
+ const n = Number.parseFloat(String(settings.topupTaxRate ?? '0'))
37
+ return Number.isFinite(n) && n > 0 ? n : 0
38
+ }
39
+
40
+ /** numeric(7,4) column value for a VAT percentage. */
41
+ export function taxRateColumn(ratePercent: number): string {
42
+ return (Math.round(ratePercent * 10000) / 10000).toString()
43
+ }
44
+
45
+ /** Seller fields a posted (printable) invoice requires — Spec B, P-D4. */
46
+ export const REQUIRED_SELLER_FIELDS = ['legalName', 'sellerAddress', 'taxId', 'iban'] as const
47
+ export type RequiredSellerField = (typeof REQUIRED_SELLER_FIELDS)[number]
48
+
49
+ export function missingSellerFields(
50
+ settings: Pick<BillingSettings, RequiredSellerField>,
51
+ ): RequiredSellerField[] {
52
+ return REQUIRED_SELLER_FIELDS.filter((field) => {
53
+ const value = settings[field]
54
+ if (value === null || value === undefined) return true
55
+ if (typeof value === 'string') return value.trim() === ''
56
+ return Object.keys(value).length === 0
57
+ })
58
+ }
59
+
60
+ /**
61
+ * Seller block frozen onto an invoice at post, so later settings edits never
62
+ * change an issued document.
63
+ */
64
+ export function buildSellerSnapshot(settings: BillingSettings): Record<string, unknown> {
65
+ return {
66
+ organization_id: settings.organizationId,
67
+ legal_name: settings.legalName ?? null,
68
+ address: settings.sellerAddress ?? null,
69
+ tax_id: settings.taxId ?? null,
70
+ bank_name: settings.bankName ?? null,
71
+ iban: settings.iban ?? null,
72
+ bic: settings.bic ?? null,
73
+ invoice_footer: settings.invoiceFooter ?? null,
74
+ logo_attachment_id: settings.logoAttachmentId ?? null,
75
+ }
76
+ }
77
+
78
+ export async function getBillingSettings(em: EntityManager, scope: SettingsScope): Promise<BillingSettings> {
79
+ const where = { tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null }
80
+ const existing = await em.findOne(BillingSettings, where as never)
81
+ if (existing) return existing
82
+ // Race-safe create: a concurrent first read may insert the same row; the
83
+ // partial unique index makes ours a no-op and we re-read the winner.
84
+ const now = new Date()
85
+ await em.execute(
86
+ `INSERT INTO billing_settings
87
+ (tenant_id, organization_id, low_balance_threshold_default, near_limit_buffer_default,
88
+ statement_enabled, topup_tax_rate, topup_provider, number_masks, created_at, updated_at)
89
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?::jsonb, ?, ?)
90
+ ON CONFLICT (tenant_id, organization_id) WHERE deleted_at IS NULL DO NOTHING`,
91
+ [
92
+ scope.tenantId,
93
+ scope.organizationId,
94
+ BILLING_SETTINGS_DEFAULTS.lowBalanceThresholdDefault,
95
+ BILLING_SETTINGS_DEFAULTS.nearLimitBufferDefault,
96
+ BILLING_SETTINGS_DEFAULTS.statementEnabled,
97
+ BILLING_SETTINGS_DEFAULTS.topupTaxRate,
98
+ BILLING_SETTINGS_DEFAULTS.topupProvider,
99
+ JSON.stringify(BILLING_SETTINGS_DEFAULTS.numberMasks),
100
+ now,
101
+ now,
102
+ ],
103
+ )
104
+ const created = await em.findOne(BillingSettings, where as never)
105
+ if (!created) throw new Error('Billing settings could not be initialised')
106
+ return created
107
+ }
108
+
109
+ /** Mask for a series, falling back to the default when unset or invalid. */
110
+ export function numberMaskFor(settings: Pick<BillingSettings, 'numberMasks'>, series: DocumentSeries): string {
111
+ return maskFor(settings.numberMasks ?? null, series)
112
+ }
113
+
114
+ function numberOr(value: string | number | null | undefined, fallback: number): number {
115
+ const n = typeof value === 'number' ? value : Number.parseFloat(value ?? '')
116
+ return Number.isFinite(n) ? n : fallback
117
+ }
118
+
119
+ /** Plain view of the settings — what the API returns and the UI edits. */
120
+ export function serializeBillingSettings(settings: BillingSettings) {
121
+ return {
122
+ id: settings.id,
123
+ lowBalanceThresholdDefault: numberOr(settings.lowBalanceThresholdDefault, 0),
124
+ nearLimitBufferDefault: numberOr(settings.nearLimitBufferDefault, 0),
125
+ statementEnabled: settings.statementEnabled,
126
+ topupTaxRate: numberOr(settings.topupTaxRate, 0),
127
+ prepaidTaxPoint: settings.prepaidTaxPoint === 'consumption' ? ('consumption' as const) : ('topup' as const),
128
+ topupProvider: settings.topupProvider,
129
+ numberMasks: {
130
+ invoice: numberMaskFor(settings, 'invoice'),
131
+ credit_memo: numberMaskFor(settings, 'credit_memo'),
132
+ receipt: numberMaskFor(settings, 'receipt'),
133
+ },
134
+ legalName: settings.legalName ?? '',
135
+ sellerAddress: settings.sellerAddress ?? null,
136
+ taxId: settings.taxId ?? '',
137
+ bankName: settings.bankName ?? '',
138
+ iban: settings.iban ?? '',
139
+ bic: settings.bic ?? '',
140
+ invoiceFooter: settings.invoiceFooter ?? '',
141
+ logoAttachmentId: settings.logoAttachmentId ?? null,
142
+ defaultPaymentTermsDays: settings.defaultPaymentTermsDays ?? BILLING_SETTINGS_DEFAULTS.defaultPaymentTermsDays,
143
+ defaultTaxRate: numberOr(settings.defaultTaxRate, 23),
144
+ }
145
+ }
@@ -0,0 +1,112 @@
1
+ import { NextResponse } from 'next/server'
2
+ import type { ZodType } from 'zod'
3
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
+ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
+ import {
6
+ organizationScopeRequiredResponse,
7
+ resolveActiveOrganizationId,
8
+ } from '@open-mercato/shared/lib/auth/organizationScope'
9
+ import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
10
+ import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
11
+ import { bridgeLegacyGuard, runMutationGuards } from '@open-mercato/shared/lib/crud/mutation-guard-registry'
12
+
13
+ /**
14
+ * Shared handler for billing's custom POST action routes (Spec C payments,
15
+ * Spec D memos): authenticates, resolves the organization, validates the
16
+ * body, runs the shared mutation guards (record locks etc.) as `update` on
17
+ * the target resource, executes the command and maps `CrudHttpError`s.
18
+ *
19
+ * `requireFeatures` stays on each route's exported `metadata` (enforced by
20
+ * the API dispatcher).
21
+ */
22
+
23
+ export type CommandRouteOptions<TBody> = {
24
+ commandId: string
25
+ /** Body schema WITHOUT tenant / organization (they come from auth). */
26
+ bodySchema: ZodType<TBody>
27
+ resourceKind: string
28
+ resourceId: (body: TBody) => string | null
29
+ /** Mutation-guard operation (default `update`, the usual one for action routes). */
30
+ operation?: 'create' | 'update' | 'delete'
31
+ /** Optional input mapping (default: body + scope). */
32
+ toInput?: (body: TBody, scope: { tenantId: string; organizationId: string }) => Record<string, unknown>
33
+ logLabel: string
34
+ }
35
+
36
+ function userFeatures(auth: unknown): string[] {
37
+ const features = (auth as { features?: unknown })?.features
38
+ return Array.isArray(features) ? features.filter((value): value is string => typeof value === 'string') : []
39
+ }
40
+
41
+ export async function readRequestBody(req: Request): Promise<unknown> {
42
+ try {
43
+ return await req.json()
44
+ } catch {
45
+ return {}
46
+ }
47
+ }
48
+
49
+ export async function runCommandRoute<TBody>(
50
+ req: Request,
51
+ options: CommandRouteOptions<TBody>,
52
+ rawBody?: unknown,
53
+ ): Promise<Response> {
54
+ try {
55
+ const container = await createRequestContainer()
56
+ const auth = await getAuthFromRequest(req)
57
+ if (!auth || !auth.tenantId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
58
+ const organizationId = resolveActiveOrganizationId(auth)
59
+ if (!organizationId) return organizationScopeRequiredResponse()
60
+ const parsed = options.bodySchema.safeParse(rawBody === undefined ? await readRequestBody(req) : rawBody)
61
+ if (!parsed.success) {
62
+ return NextResponse.json(
63
+ { error: 'Invalid request', code: 'billing.request.invalid', issues: parsed.error.issues },
64
+ { status: 400 },
65
+ )
66
+ }
67
+ const scope = { tenantId: auth.tenantId, organizationId }
68
+ const guardInput = {
69
+ tenantId: auth.tenantId,
70
+ organizationId,
71
+ userId: auth.sub ?? '',
72
+ resourceKind: options.resourceKind,
73
+ resourceId: options.resourceId(parsed.data),
74
+ operation: options.operation ?? ('update' as const),
75
+ requestMethod: req.method,
76
+ requestHeaders: req.headers,
77
+ }
78
+ const legacyGuard = bridgeLegacyGuard(container)
79
+ const guard = legacyGuard
80
+ ? await runMutationGuards([legacyGuard], guardInput, { userFeatures: userFeatures(auth) })
81
+ : { ok: true as const, afterSuccessCallbacks: [] }
82
+ if (!guard.ok) {
83
+ return NextResponse.json(guard.errorBody ?? { error: 'Operation blocked by guard' }, { status: guard.errorStatus ?? 422 })
84
+ }
85
+ const ctx: CommandRuntimeContext = {
86
+ container,
87
+ auth,
88
+ organizationScope: null,
89
+ selectedOrganizationId: organizationId,
90
+ organizationIds: [organizationId],
91
+ request: req,
92
+ }
93
+ const commandBus = container.resolve('commandBus') as CommandBus
94
+ const input = options.toInput
95
+ ? options.toInput(parsed.data, scope)
96
+ : { ...(parsed.data as Record<string, unknown>), ...scope }
97
+ const response = await commandBus.execute(options.commandId, { input, ctx })
98
+ for (const callback of guard.afterSuccessCallbacks) {
99
+ if (!callback.guard.afterSuccess) continue
100
+ try {
101
+ await callback.guard.afterSuccess({ ...guardInput, resourceId: guardInput.resourceId ?? '', metadata: callback.metadata ?? null })
102
+ } catch (err) {
103
+ console.error(`[${options.logLabel}] guard afterSuccess failed`, err)
104
+ }
105
+ }
106
+ return NextResponse.json((response as { result?: unknown }).result ?? { ok: true })
107
+ } catch (err) {
108
+ if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })
109
+ console.error(`[${options.logLabel}]`, err)
110
+ return NextResponse.json({ error: 'Internal error' }, { status: 500 })
111
+ }
112
+ }
@@ -0,0 +1,157 @@
1
+ import type { CustomerKind } from '../data/validators'
2
+
3
+ /**
4
+ * Pure helpers for linking a Billing Account to a customer record (Spec E).
5
+ *
6
+ * Billing never imports the customers module: `customer_id` is a string FK
7
+ * and every read goes through the customers REST API from the UI (a soft
8
+ * dependency — if it is unavailable the form degrades to a raw id and no
9
+ * prefill). These helpers keep the response-shape knowledge in one tested
10
+ * place so the React components stay thin.
11
+ */
12
+
13
+ export type CustomerSummary = {
14
+ id: string
15
+ name: string
16
+ email: string | null
17
+ }
18
+
19
+ export type PrefillAddress = {
20
+ line1: string
21
+ line2: string
22
+ city: string
23
+ postal_code: string
24
+ country: string
25
+ }
26
+
27
+ export type PrefillTarget = {
28
+ name: string
29
+ invoiceEmail: string
30
+ invoiceAddress: PrefillAddress
31
+ }
32
+
33
+ type RawRecord = Record<string, unknown>
34
+
35
+ const CUSTOMER_ENDPOINTS: Record<CustomerKind, string> = {
36
+ company: '/api/customers/companies',
37
+ person: '/api/customers/people',
38
+ }
39
+
40
+ const CUSTOMER_DETAIL_PATHS: Record<CustomerKind, string> = {
41
+ company: '/backend/customers/companies',
42
+ person: '/backend/customers/people',
43
+ }
44
+
45
+ /** Max ids per batched lookup — the CRUD factory caps `pageSize` at 100. */
46
+ export const CUSTOMER_LOOKUP_CHUNK = 100
47
+
48
+ export function customerEndpoint(kind: CustomerKind): string {
49
+ return CUSTOMER_ENDPOINTS[kind]
50
+ }
51
+
52
+ export function customerDetailHref(kind: CustomerKind, customerId: string): string {
53
+ return `${CUSTOMER_DETAIL_PATHS[kind]}/${encodeURIComponent(customerId)}`
54
+ }
55
+
56
+ function str(value: unknown): string {
57
+ if (typeof value === 'string') return value.trim()
58
+ if (typeof value === 'number') return String(value)
59
+ return ''
60
+ }
61
+
62
+ /** Extracts the row array from a list response (`{ items }` or a bare array). */
63
+ export function extractItems(result: unknown): RawRecord[] {
64
+ const raw = Array.isArray(result)
65
+ ? result
66
+ : result && typeof result === 'object' && Array.isArray((result as { items?: unknown }).items)
67
+ ? (result as { items: unknown[] }).items
68
+ : []
69
+ return raw.filter((row): row is RawRecord => !!row && typeof row === 'object')
70
+ }
71
+
72
+ /** Maps a customers list row (snake_case or camelCase) to a summary. */
73
+ export function toCustomerSummary(row: RawRecord): CustomerSummary | null {
74
+ const id = str(row.id)
75
+ if (!id) return null
76
+ const name = str(row.display_name) || str(row.displayName) || str(row.name) || id
77
+ const email = str(row.primary_email) || str(row.primaryEmail) || str(row.email)
78
+ return { id, name, email: email || null }
79
+ }
80
+
81
+ /**
82
+ * Picks the customer's primary address (else the first usable one) and maps
83
+ * it onto the billing `invoice_address` shape. Returns null when no row has
84
+ * the parts billing requires (line 1, city, postal code, country).
85
+ */
86
+ export function mapPrimaryAddress(rows: RawRecord[]): PrefillAddress | null {
87
+ const ordered = [...rows].sort((a, b) => Number(b.is_primary === true) - Number(a.is_primary === true))
88
+ for (const row of ordered) {
89
+ const street = str(row.address_line1) || str(row.addressLine1)
90
+ const building = str(row.building_number) || str(row.buildingNumber)
91
+ const flat = str(row.flat_number) || str(row.flatNumber)
92
+ let line1 = street
93
+ if (line1 && building) line1 = `${line1} ${building}`
94
+ if (line1 && building && flat) line1 = `${line1}/${flat}`
95
+ const city = str(row.city)
96
+ const postalCode = str(row.postal_code) || str(row.postalCode)
97
+ const country = (str(row.country) || str(row.country_code) || str(row.countryCode)).toUpperCase()
98
+ if (!line1 || !city || !postalCode || country.length < 2 || country.length > 3) continue
99
+ return {
100
+ line1,
101
+ line2: str(row.address_line2) || str(row.addressLine2),
102
+ city,
103
+ postal_code: postalCode,
104
+ country,
105
+ }
106
+ }
107
+ return null
108
+ }
109
+
110
+ function isAddressEmpty(address: PrefillAddress): boolean {
111
+ return !address.line1.trim() && !address.line2.trim() && !address.city.trim() && !address.postal_code.trim()
112
+ }
113
+
114
+ /**
115
+ * Fills ONLY empty fields from the customer record (decision E2-D2) — never
116
+ * overwrites what the operator typed. The address is taken as a whole block
117
+ * (and only if the form's address is still blank) so we never mix a typed
118
+ * street with a prefilled city. Country alone does not count as "typed": the
119
+ * form ships a default country.
120
+ */
121
+ export function applyCustomerPrefill<T extends PrefillTarget>(
122
+ current: T,
123
+ customer: CustomerSummary | null,
124
+ address: PrefillAddress | null,
125
+ ): T {
126
+ let next = current
127
+ if (customer) {
128
+ if (!current.name.trim() && customer.name) next = { ...next, name: customer.name }
129
+ if (!current.invoiceEmail.trim() && customer.email) next = { ...next, invoiceEmail: customer.email }
130
+ }
131
+ if (address && isAddressEmpty(current.invoiceAddress)) {
132
+ next = { ...next, invoiceAddress: { ...address } }
133
+ }
134
+ return next
135
+ }
136
+
137
+ /** Groups ids by kind and chunks them for batched `?ids=` lookups. */
138
+ export function planCustomerLookups(
139
+ rows: Array<{ customerId: string | null | undefined; customerKind: CustomerKind | null | undefined }>,
140
+ ): Array<{ kind: CustomerKind; ids: string[] }> {
141
+ const byKind = new Map<CustomerKind, Set<string>>()
142
+ for (const row of rows) {
143
+ const id = (row.customerId ?? '').trim()
144
+ if (!id) continue
145
+ const kind: CustomerKind = row.customerKind === 'person' ? 'person' : 'company'
146
+ if (!byKind.has(kind)) byKind.set(kind, new Set())
147
+ byKind.get(kind)!.add(id)
148
+ }
149
+ const plan: Array<{ kind: CustomerKind; ids: string[] }> = []
150
+ for (const [kind, ids] of byKind) {
151
+ const all = Array.from(ids)
152
+ for (let i = 0; i < all.length; i += CUSTOMER_LOOKUP_CHUNK) {
153
+ plan.push({ kind, ids: all.slice(i, i + CUSTOMER_LOOKUP_CHUNK) })
154
+ }
155
+ }
156
+ return plan
157
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Date-only helpers (Spec F, P-D5).
3
+ *
4
+ * MikroORM v7 hydrates `date` columns as `YYYY-MM-DD` strings while the
5
+ * engine computes with `Date`s; and `pg` serialises a `Date` query
6
+ * parameter in the server's time zone, which can shift a `date` comparison
7
+ * by a day. Every date-only value the billing engine compares or sends to a
8
+ * `date` column goes through these helpers: compare as UTC midnight, query
9
+ * with the ISO day string.
10
+ */
11
+
12
+ /** UTC-midnight `Date` for a `Date`, ISO string or timestamp. */
13
+ export function toUtcMidnight(value: Date | string | number): Date {
14
+ const date = typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) ? new Date(`${value}T00:00:00Z`) : new Date(value)
15
+ date.setUTCHours(0, 0, 0, 0)
16
+ return date
17
+ }
18
+
19
+ /** `YYYY-MM-DD` (UTC) for a `Date`, ISO string or timestamp. */
20
+ export function toIsoDate(value: Date | string | number): string {
21
+ return toUtcMidnight(value).toISOString().slice(0, 10)
22
+ }
@@ -0,0 +1,23 @@
1
+ import type { BillingAccount } from '../data/entities'
2
+
3
+ /**
4
+ * Parties printed on a billing document. Posting freezes them as snapshots
5
+ * on the invoice (buyer from the account, seller from `billingSettings`), so
6
+ * later account / settings edits never change an issued document; drafts
7
+ * render from the live rows.
8
+ */
9
+
10
+ /** Frozen "issued to" block — later account edits never change a posted document. */
11
+ export function buildBuyerSnapshot(account: BillingAccount): Record<string, unknown> {
12
+ return {
13
+ bill_account_id: account.id,
14
+ name: account.name,
15
+ customer_id: account.customerId,
16
+ customer_kind: account.customerKind ?? 'company',
17
+ tax_id: account.taxId ?? null,
18
+ invoice_email: account.invoiceEmail,
19
+ invoice_language: account.invoiceLanguage,
20
+ invoice_address: account.invoiceAddress ?? null,
21
+ }
22
+ }
23
+
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Billing document type helpers (Spec 0 / Spec D). Pure.
3
+ *
4
+ * invoice — receivable, `invoice` series
5
+ * debit_memo — receivable (supplementary invoice), `invoice` series (D-D8)
6
+ * credit_memo — credit source, `credit_memo` series; amounts stored positive (D-D5)
7
+ * receipt — prepaid top-up receipt, `receipt` series, never corrected (D-D6)
8
+ */
9
+
10
+ export type DocumentType = 'invoice' | 'credit_memo' | 'debit_memo' | 'receipt'
11
+
12
+ export function isReceivable(type: string): boolean {
13
+ return type === 'invoice' || type === 'debit_memo'
14
+ }
15
+
16
+ export function isMemo(type: string): boolean {
17
+ return type === 'credit_memo' || type === 'debit_memo'
18
+ }
19
+
20
+ /** Numbering series of a document type. */
21
+ export function seriesFor(type: string): 'invoice' | 'credit_memo' | 'receipt' {
22
+ if (type === 'credit_memo') return 'credit_memo'
23
+ if (type === 'receipt') return 'receipt'
24
+ return 'invoice'
25
+ }
26
+
27
+ /** Sign used for DISPLAY only — credit memos read as negative amounts. */
28
+ export function displaySign(type: string): 1 | -1 {
29
+ return type === 'credit_memo' ? -1 : 1
30
+ }
31
+
32
+ /** Originals a memo may correct (D-D3): posted, partially paid, paid (credited → debit only). */
33
+ export function canCorrect(original: { documentType: string; status: string; testRun: boolean }, memoType: string): boolean {
34
+ if (original.testRun || original.documentType !== 'invoice') return false
35
+ if (['posted', 'partially_paid', 'paid'].includes(original.status)) return true
36
+ return original.status === 'credited' && memoType === 'debit_memo'
37
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Due-date math for posted invoices (Spec B). Pure, date-only, UTC.
3
+ *
4
+ * `due_date = issue_date + payment terms (days)`, where the terms come from
5
+ * the account (`payment_terms_days`) and fall back to the organization
6
+ * default (`billing_settings.default_payment_terms_days`).
7
+ */
8
+
9
+ export function resolvePaymentTermsDays(
10
+ accountTermsDays: number | null | undefined,
11
+ defaultTermsDays: number | null | undefined,
12
+ ): number {
13
+ if (typeof accountTermsDays === 'number' && Number.isInteger(accountTermsDays) && accountTermsDays >= 0) {
14
+ return accountTermsDays
15
+ }
16
+ if (typeof defaultTermsDays === 'number' && Number.isInteger(defaultTermsDays) && defaultTermsDays >= 0) {
17
+ return defaultTermsDays
18
+ }
19
+ return 14
20
+ }
21
+
22
+ /** Issue date (any time of day) + N calendar days, at UTC midnight. */
23
+ export function computeDueDate(issueDate: Date, termsDays: number): Date {
24
+ const base = new Date(issueDate)
25
+ return new Date(Date.UTC(base.getUTCFullYear(), base.getUTCMonth(), base.getUTCDate() + termsDays))
26
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * IBAN / BIC helpers for the seller's payment instructions (Spec B). Pure.
3
+ *
4
+ * `normalizeIban` strips spaces and upper-cases; `isValidIban` checks the
5
+ * structure (country code, check digits, 11–30 alphanumerics after) and the
6
+ * ISO 13616 mod-97 checksum. Country-specific lengths are not enforced — the
7
+ * checksum already rejects typos, and a missing country table never blocks a
8
+ * legitimate account.
9
+ */
10
+
11
+ export function normalizeIban(value: string): string {
12
+ return value.replace(/\s+/g, '').toUpperCase()
13
+ }
14
+
15
+ export function isValidIban(value: string): boolean {
16
+ const iban = normalizeIban(value)
17
+ if (!/^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/.test(iban)) return false
18
+ const rearranged = iban.slice(4) + iban.slice(0, 4)
19
+ let remainder = 0
20
+ for (const char of rearranged) {
21
+ const digits = /[A-Z]/.test(char) ? String(char.charCodeAt(0) - 55) : char
22
+ for (const digit of digits) {
23
+ remainder = (remainder * 10 + Number(digit)) % 97
24
+ }
25
+ }
26
+ return remainder === 1
27
+ }
28
+
29
+ /** Groups of 4 for display ("PL61 1090 1014 …"). */
30
+ export function formatIban(value: string): string {
31
+ return normalizeIban(value).replace(/(.{4})/g, '$1 ').trim()
32
+ }
33
+
34
+ export function isValidBic(value: string): boolean {
35
+ return /^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$/.test(value.trim().toUpperCase())
36
+ }