@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
@@ -0,0 +1,118 @@
1
+ import { buildVatSummary, resolvePrepaidDebit } from '../../lib/prepaidTaxPoint'
2
+ import { receiptTaxRate } from '../../lib/billingSettings'
3
+ import { consumePrepaidUsage } from '../../lib/prepaidConsume'
4
+ import { createPrepaidMockEm } from '../helpers/prepaidMockEm'
5
+
6
+ describe('resolvePrepaidDebit (Spec F, F-D3)', () => {
7
+ it('topup: debits the amount as entered — rate and basis ignored', () => {
8
+ expect(resolvePrepaidDebit({ lineAmount: 49, priceBasis: 'net', taxRate: 23, taxPoint: 'topup' })).toEqual({
9
+ debit: 49,
10
+ net: 49,
11
+ tax: 0,
12
+ taxRate: 0,
13
+ })
14
+ expect(resolvePrepaidDebit({ lineAmount: '12.30', priceBasis: 'gross', taxRate: 23, taxPoint: 'topup' }).debit).toBe(12.3)
15
+ })
16
+
17
+ it('consumption: debits the gross — 20 @ 0 % → 20, 10 net @ 23 % → 12.30', () => {
18
+ expect(resolvePrepaidDebit({ lineAmount: 20, priceBasis: 'net', taxRate: 0, taxPoint: 'consumption' }).debit).toBe(20)
19
+ expect(resolvePrepaidDebit({ lineAmount: 10, priceBasis: 'net', taxRate: 23, taxPoint: 'consumption' })).toEqual({
20
+ debit: 12.3,
21
+ net: 10,
22
+ tax: 2.3,
23
+ taxRate: 23,
24
+ })
25
+ })
26
+
27
+ it('consumption: a gross price is debited as typed; credits keep their sign', () => {
28
+ expect(resolvePrepaidDebit({ lineAmount: 12.3, priceBasis: 'gross', taxRate: 23, taxPoint: 'consumption' }).debit).toBe(12.3)
29
+ expect(resolvePrepaidDebit({ lineAmount: -10, priceBasis: 'net', taxRate: 23, taxPoint: 'consumption' }).debit).toBe(-12.3)
30
+ })
31
+ })
32
+
33
+ describe('buildVatSummary', () => {
34
+ it('groups consumption debits by rate (highest first) and is empty in topup mode', () => {
35
+ const debits = [
36
+ resolvePrepaidDebit({ lineAmount: 10, priceBasis: 'net', taxRate: 23, taxPoint: 'consumption' }),
37
+ resolvePrepaidDebit({ lineAmount: 5, priceBasis: 'net', taxRate: 23, taxPoint: 'consumption' }),
38
+ resolvePrepaidDebit({ lineAmount: 20, priceBasis: 'net', taxRate: 0, taxPoint: 'consumption' }),
39
+ ]
40
+ expect(buildVatSummary(debits, 'consumption')).toEqual([
41
+ { rate: '23', net: '15.0000', tax: '3.4500', gross: '18.4500' },
42
+ { rate: '0', net: '20.0000', tax: '0.0000', gross: '20.0000' },
43
+ ])
44
+ expect(buildVatSummary(debits, 'topup')).toEqual([])
45
+ })
46
+ })
47
+
48
+ describe('receiptTaxRate (Spec F, P-D11)', () => {
49
+ it('uses the top-up rate only when tax is charged at top-up — never twice', () => {
50
+ expect(receiptTaxRate({ topupTaxRate: '23', prepaidTaxPoint: 'topup' })).toBe(23)
51
+ expect(receiptTaxRate({ topupTaxRate: '23', prepaidTaxPoint: 'consumption' })).toBe(0)
52
+ expect(receiptTaxRate({ topupTaxRate: 'x', prepaidTaxPoint: 'topup' })).toBe(0)
53
+ })
54
+ })
55
+
56
+ describe('consumePrepaidUsage — tax point', () => {
57
+ const TENANT = 'ten-1'
58
+ const ORG = 'org-1'
59
+ const ACCT = 'acct-1'
60
+ const account = { id: ACCT, tenantId: TENANT, organizationId: ORG, currencyCode: 'EUR', billingMode: 'prepaid', creditLimit: '0' }
61
+ const usageItem = (overrides: Record<string, unknown> = {}) => ({
62
+ id: 'item-usage',
63
+ type: 'usage',
64
+ uomCode: 'gb',
65
+ isActive: true,
66
+ deletedAt: null,
67
+ taxRate: '23',
68
+ priceBasis: 'net',
69
+ rateJson: { unit_price: 1 },
70
+ description: 'Data',
71
+ ...overrides,
72
+ })
73
+ const input = {
74
+ organizationId: ORG,
75
+ tenantId: TENANT,
76
+ billAccountId: ACCT,
77
+ uomCode: 'gb',
78
+ quantity: 10,
79
+ periodStart: new Date('2026-11-01'),
80
+ periodEnd: new Date('2026-11-30'),
81
+ }
82
+
83
+ it('topup mode: debits the rated amount', async () => {
84
+ const em = createPrepaidMockEm({
85
+ account,
86
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '100.0000' },
87
+ usageItem: usageItem(),
88
+ })
89
+ const { result } = await consumePrepaidUsage(em as never, account as never, input)
90
+ expect(result.ratedAmount).toBe('10.0000')
91
+ expect(result.balance).toBe('90.0000')
92
+ })
93
+
94
+ it('consumption mode: debits the gross (10 × 1.00 net @ 23 % → 12.30) and records the split', async () => {
95
+ const em = createPrepaidMockEm({
96
+ account,
97
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '100.0000' },
98
+ usageItem: usageItem(),
99
+ configs: { 'prepaid.tax_point': 'consumption' },
100
+ })
101
+ const { result } = await consumePrepaidUsage(em as never, account as never, input)
102
+ expect(result.ratedAmount).toBe('12.3000')
103
+ expect(result.balance).toBe('87.7000')
104
+ const txn = em.transactions.find((t) => t.type === 'usage')!
105
+ expect(txn.metadata).toMatchObject({ rated_amount: '10.0000', net: '10.0000', tax: '2.3000', tax_rate: '23', tax_point: 'consumption' })
106
+ })
107
+
108
+ it('consumption mode at 0 %: net = gross', async () => {
109
+ const em = createPrepaidMockEm({
110
+ account,
111
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '100.0000' },
112
+ usageItem: usageItem({ taxRate: '0' }),
113
+ configs: { 'prepaid.tax_point': 'consumption' },
114
+ })
115
+ const { result } = await consumePrepaidUsage(em as never, account as never, input)
116
+ expect(result.ratedAmount).toBe('10.0000')
117
+ })
118
+ })
@@ -9,11 +9,15 @@ function makeMockEm() {
9
9
  const store: Array<Record<string, unknown>> = []
10
10
  let idSeq = 0
11
11
  const nativeDeleteCalls: unknown[] = []
12
+ // Spec B: the seed fills empty seller fields on the org's BillingSettings.
13
+ const settings: Record<string, unknown> = { defaultTaxRate: '23', legalName: null }
12
14
 
13
15
  const em = {
14
16
  store,
15
17
  nativeDeleteCalls,
16
- findOne: jest.fn(async (_entity: unknown, where: Record<string, unknown>) => {
18
+ settings,
19
+ findOne: jest.fn(async (entity: unknown, where: Record<string, unknown>) => {
20
+ if ((entity as { name?: string }).name === 'BillingSettings') return settings
17
21
  return (
18
22
  store.find((row) => {
19
23
  if (typeof where.name === 'string') return row.name === where.name
@@ -38,6 +42,7 @@ function makeMockEm() {
38
42
  return em as never as Parameters<typeof seedBillingDemo>[0] & {
39
43
  store: Array<Record<string, unknown>>
40
44
  nativeDeleteCalls: unknown[]
45
+ settings: Record<string, unknown>
41
46
  }
42
47
  }
43
48
 
@@ -49,7 +54,34 @@ describe('seedBillingDemo', () => {
49
54
  const em = makeMockEm()
50
55
  const res = await seedBillingDemo(em, SCOPE, { now: NOW })
51
56
 
52
- expect(res).toEqual({ accountsCreated: 2, itemsCreated: 3, usageCreated: 1 })
57
+ expect(res).toEqual({ accountsCreated: 3, itemsCreated: 6, usageCreated: 1 })
58
+ })
59
+
60
+ it('dates items to demo in-advance, in-arrears and mid-cycle proration (Spec A)', async () => {
61
+ const em = makeMockEm()
62
+ await seedBillingDemo(em, SCOPE, { now: NOW })
63
+ const byRef = (ref: string) =>
64
+ em.store.find((r) => r.sourceRef === ref) as { billStartDate: Date; chargeTiming: string } | undefined
65
+ const day = (d?: Date) => d?.toISOString().slice(0, 10)
66
+ expect(day(byRef('demo-billing-nw-rec')?.billStartDate)).toBe('2026-06-01')
67
+ expect(byRef('demo-billing-nw-rec')?.chargeTiming).toBe('in_advance')
68
+ expect(day(byRef('demo-billing-nw-addon')?.billStartDate)).toBe('2026-05-15')
69
+ expect(byRef('demo-billing-gx-arr')).toMatchObject({ chargeTiming: 'in_arrears' })
70
+ expect(day(byRef('demo-billing-gx-arr')?.billStartDate)).toBe('2026-05-01')
71
+ })
72
+
73
+ it('seeds a B2C person account invoiced in Polish next to the company accounts', async () => {
74
+ const em = makeMockEm()
75
+ await seedBillingDemo(em, SCOPE, { now: NOW })
76
+
77
+ const person = em.store.find((r) => r.name === 'Demo — Jan Kowalski') as
78
+ | { customerKind: string; invoiceLanguage: string }
79
+ | undefined
80
+ const company = em.store.find((r) => r.name === 'Demo — Northwind Telecom') as
81
+ | { customerKind: string }
82
+ | undefined
83
+ expect(person).toMatchObject({ customerKind: 'person', invoiceLanguage: 'pl' })
84
+ expect(company?.customerKind).toBe('company')
53
85
  })
54
86
 
55
87
  it('is idempotent — a second run creates nothing', async () => {
@@ -83,4 +115,23 @@ describe('seedBillingDemo', () => {
83
115
  await resetBillingDemo(em, SCOPE)
84
116
  expect(em.nativeDelete).toHaveBeenCalledTimes(3)
85
117
  })
118
+
119
+ it('seeds VAT rates on items, including a 0 % item (Spec B)', async () => {
120
+ const em = makeMockEm()
121
+ await seedBillingDemo(em, SCOPE, { now: NOW })
122
+ const rates = em.store.filter((r) => typeof r.sourceRef === 'string' && 'taxRate' in r).map((r) => r.taxRate)
123
+ expect(rates).toContain('23')
124
+ expect(rates).toContain('8')
125
+ expect(rates).toContain('0')
126
+ })
127
+
128
+ it('fills empty seller settings so demo invoices can be posted, never overwriting real values', async () => {
129
+ const em = makeMockEm()
130
+ em.settings.taxId = 'PL-REAL'
131
+ await seedBillingDemo(em, SCOPE, { now: NOW })
132
+ expect(em.settings.legalName).toBe('Dainamite Demo sp. z o.o.')
133
+ expect(em.settings.iban).toBe('PL61109010140000071219812874')
134
+ expect(em.settings.sellerAddress).toMatchObject({ city: 'Kraków' })
135
+ expect(em.settings.taxId).toBe('PL-REAL')
136
+ })
86
137
  })
@@ -0,0 +1,28 @@
1
+ import { DEFAULT_DEMO_SELLER, applySellerDefaults, sellerFieldsToFill } from '../../lib/seeds/sellerSettings'
2
+ import { billingSettingsUpdateSchema } from '../../data/validators'
3
+ import { missingSellerFields } from '../../lib/billingSettings'
4
+
5
+ const scope = { tenantId: '11111111-1111-4111-8111-111111111111', organizationId: '22222222-2222-4222-8222-222222222222' }
6
+
7
+ describe('seller defaults for seed tenants', () => {
8
+ it('fills only empty fields — real details are never overwritten', () => {
9
+ const fill = sellerFieldsToFill(
10
+ { legalName: 'Real Co', sellerAddress: null, taxId: '', bankName: null, iban: 'PL61109010140000071219812874', bic: null, invoiceFooter: null } as never,
11
+ DEFAULT_DEMO_SELLER,
12
+ )
13
+ expect(Object.keys(fill).sort()).toEqual(['bankName', 'bic', 'invoiceFooter', 'sellerAddress', 'taxId'])
14
+ })
15
+
16
+ it('applies and flushes once; a re-run is a no-op', async () => {
17
+ const settings: Record<string, unknown> = { legalName: null, sellerAddress: null, taxId: null, bankName: null, iban: null, bic: null, invoiceFooter: null }
18
+ const em = { findOne: jest.fn(async () => settings), flush: jest.fn(async () => undefined), execute: jest.fn() }
19
+ expect(await applySellerDefaults(em as never, scope, DEFAULT_DEMO_SELLER)).toHaveLength(7)
20
+ expect(missingSellerFields(settings as never)).toEqual([])
21
+ expect(await applySellerDefaults(em as never, scope, DEFAULT_DEMO_SELLER)).toEqual([])
22
+ expect(em.flush).toHaveBeenCalledTimes(1)
23
+ })
24
+
25
+ it('the default profile passes the settings validators (the page can save it unchanged)', () => {
26
+ expect(billingSettingsUpdateSchema.safeParse({ ...scope, ...DEFAULT_DEMO_SELLER }).success).toBe(true)
27
+ })
28
+ })
@@ -0,0 +1,190 @@
1
+ import {
2
+ MAX_PERIODS_PER_ITEM,
3
+ computeRecurringLines,
4
+ gridPeriodContaining,
5
+ inclusiveDays,
6
+ roundHalfUp2dp,
7
+ type RecurringItemState,
8
+ } from '../../lib/servicePeriods'
9
+ import type { BillCycle } from '../../data/validators'
10
+
11
+ const d = (iso: string) => new Date(`${iso}T00:00:00.000Z`)
12
+ const iso = (date: Date | null) => (date ? date.toISOString().slice(0, 10) : null)
13
+
14
+ function item(overrides: Partial<RecurringItemState> = {}): RecurringItemState {
15
+ return {
16
+ id: 'item-1',
17
+ chargeTiming: 'in_advance',
18
+ prorate: true,
19
+ billStartDate: d('2026-11-14'),
20
+ billEndDate: null,
21
+ billedToDate: null,
22
+ unitPrice: 100,
23
+ isActive: true,
24
+ deletedAt: null,
25
+ ...overrides,
26
+ }
27
+ }
28
+
29
+ function run(state: RecurringItemState, billDate: string, cycle: BillCycle = 'monthly') {
30
+ const res = computeRecurringLines(state, { billDate: d(billDate), cycle })
31
+ return {
32
+ ...res,
33
+ periods: res.lines.map((l) => [iso(l.servicePeriodStart), iso(l.servicePeriodEnd), l.amount]),
34
+ watermark: iso(res.newBilledToDate),
35
+ }
36
+ }
37
+
38
+ describe('helpers', () => {
39
+ it('counts inclusive days and rounds half-up symmetrically', () => {
40
+ expect(inclusiveDays(d('2026-11-14'), d('2026-11-30'))).toBe(17)
41
+ expect(roundHalfUp2dp(1.005)).toBe(1.01)
42
+ expect(roundHalfUp2dp(-1.005)).toBe(-1.01)
43
+ })
44
+
45
+ it('finds the grid period containing a date, without month-end drift', () => {
46
+ const p = gridPeriodContaining(d('2026-01-31'), 'monthly', d('2026-03-31'))
47
+ expect([iso(p.start), iso(p.end)]).toEqual(['2026-03-31', '2026-04-29'])
48
+ const back = gridPeriodContaining(d('2026-12-01'), 'monthly', d('2026-11-14'))
49
+ expect([iso(back.start), iso(back.end)]).toEqual(['2026-11-01', '2026-11-30'])
50
+ })
51
+ })
52
+
53
+ describe('computeRecurringLines — spec worked examples', () => {
54
+ it("operator's test: in advance from Nov 14 bills Nov 14–Dec 13 on Nov 14", () => {
55
+ const r = run(item(), '2026-11-14')
56
+ expect(r.periods).toEqual([['2026-11-14', '2026-12-13', 100]])
57
+ expect(r.watermark).toBe('2026-12-13')
58
+ expect(r.lines[0].proration).toBeNull()
59
+ })
60
+
61
+ it('catch-up chain: Dec 14 and Jan 14 continue from the watermark', () => {
62
+ const dec = run(item({ billedToDate: d('2026-12-13') }), '2026-12-14')
63
+ expect(dec.periods).toEqual([['2026-12-14', '2027-01-13', 100]])
64
+ const jan = run(item({ billedToDate: d('2027-01-13') }), '2027-01-14')
65
+ expect(jan.periods).toEqual([['2027-01-14', '2027-02-13', 100]])
66
+ })
67
+
68
+ it('mid-cycle add: prorated stub + full next period', () => {
69
+ const r = run(item(), '2026-12-01')
70
+ expect(r.periods).toEqual([
71
+ ['2026-11-14', '2026-11-30', 56.67],
72
+ ['2026-12-01', '2026-12-31', 100],
73
+ ])
74
+ expect(r.lines[0].proration).toEqual({ activeDays: 17, periodDays: 30 })
75
+ expect(r.watermark).toBe('2026-12-31')
76
+ })
77
+
78
+ it('in arrears bills the period just ended', () => {
79
+ const r = run(item({ chargeTiming: 'in_arrears', billStartDate: d('2026-11-01') }), '2026-12-01')
80
+ expect(r.periods).toEqual([['2026-11-01', '2026-11-30', 100]])
81
+ })
82
+
83
+ it('cancel after prepay: credit for unused days, watermark pulled back', () => {
84
+ const r = run(item({ billStartDate: d('2026-01-01'), billedToDate: d('2026-12-31'), billEndDate: d('2026-12-15') }), '2027-01-01')
85
+ expect(r.periods).toEqual([['2026-12-16', '2026-12-31', -51.61]])
86
+ expect(r.lines[0].kind).toBe('credit')
87
+ expect(r.watermark).toBe('2026-12-15')
88
+ })
89
+ })
90
+
91
+ describe('computeRecurringLines — edge cases', () => {
92
+ it('nothing to bill before the item starts (in arrears, start in the future)', () => {
93
+ const r = run(item({ chargeTiming: 'in_arrears', billStartDate: d('2026-12-05') }), '2026-12-01')
94
+ expect(r.lines).toHaveLength(0)
95
+ expect(r.watermark).toBeNull()
96
+ })
97
+
98
+ it('backdated item spanning 3 grid periods lands on one bill date', () => {
99
+ const r = run(item({ chargeTiming: 'in_arrears', billStartDate: d('2026-09-01') }), '2026-12-01')
100
+ expect(r.periods).toEqual([
101
+ ['2026-09-01', '2026-09-30', 100],
102
+ ['2026-10-01', '2026-10-31', 100],
103
+ ['2026-11-01', '2026-11-30', 100],
104
+ ])
105
+ })
106
+
107
+ it('prorates a mid-period end (in arrears)', () => {
108
+ const r = run(
109
+ item({ chargeTiming: 'in_arrears', billStartDate: d('2026-11-01'), billEndDate: d('2026-11-10') }),
110
+ '2026-12-01',
111
+ )
112
+ expect(r.periods).toEqual([['2026-11-01', '2026-11-10', 33.33]])
113
+ expect(r.watermark).toBe('2026-11-10')
114
+ })
115
+
116
+ it('an end exactly on a grid boundary is a full period (no proration)', () => {
117
+ const r = run(item({ billStartDate: d('2026-12-01'), billEndDate: d('2026-12-31') }), '2026-12-01')
118
+ expect(r.periods).toEqual([['2026-12-01', '2026-12-31', 100]])
119
+ })
120
+
121
+ it('prorate=false skips partial periods but still advances the watermark', () => {
122
+ const r = run(item({ prorate: false }), '2026-12-01')
123
+ expect(r.periods).toEqual([['2026-12-01', '2026-12-31', 100]])
124
+ expect(r.skipped).toEqual([
125
+ expect.objectContaining({ reason: 'partial-period-not-prorated' }),
126
+ ])
127
+ expect(r.watermark).toBe('2026-12-31')
128
+ })
129
+
130
+ it('prorate=false never credits an ended item and keeps the watermark', () => {
131
+ const r = run(item({ prorate: false, billedToDate: d('2026-12-31'), billEndDate: d('2026-12-15') }), '2027-01-01')
132
+ expect(r.lines).toHaveLength(0)
133
+ expect(r.skipped[0].reason).toBe('ended-after-billing-no-credit')
134
+ expect(r.watermark).toBe('2026-12-31')
135
+ })
136
+
137
+ it('re-running the same bill date with the new watermark yields nothing (idempotent)', () => {
138
+ const first = run(item(), '2026-12-01')
139
+ const again = run(item({ billedToDate: first.newBilledToDate }), '2026-12-01')
140
+ expect(again.lines).toHaveLength(0)
141
+ })
142
+
143
+ it('switching in arrears → in advance never overlaps or gaps', () => {
144
+ const arrears = run(item({ chargeTiming: 'in_arrears', billStartDate: d('2026-11-01') }), '2026-12-01')
145
+ expect(arrears.watermark).toBe('2026-11-30')
146
+ const advance = run(
147
+ item({ chargeTiming: 'in_advance', billStartDate: d('2026-11-01'), billedToDate: arrears.newBilledToDate }),
148
+ '2027-01-01',
149
+ )
150
+ expect(advance.periods).toEqual([
151
+ ['2026-12-01', '2026-12-31', 100],
152
+ ['2027-01-01', '2027-01-31', 100],
153
+ ])
154
+ })
155
+
156
+ it('switching in advance → in arrears waits until the prepaid period has passed', () => {
157
+ const r = run(item({ chargeTiming: 'in_arrears', billedToDate: d('2026-12-31') }), '2027-01-01')
158
+ expect(r.lines).toHaveLength(0)
159
+ expect(r.watermark).toBe('2026-12-31')
160
+ })
161
+
162
+ it('handles month-end anchors, leap years and other cycles', () => {
163
+ expect(run(item({ billStartDate: d('2027-01-31') }), '2027-01-31').periods).toEqual([
164
+ ['2027-01-31', '2027-02-27', 100],
165
+ ])
166
+ expect(run(item({ billStartDate: d('2028-02-01') }), '2028-02-01').periods).toEqual([
167
+ ['2028-02-01', '2028-02-29', 100],
168
+ ])
169
+ expect(run(item({ billStartDate: d('2026-11-16') }), '2026-11-16', 'weekly').periods).toEqual([
170
+ ['2026-11-16', '2026-11-22', 100],
171
+ ])
172
+ expect(run(item({ billStartDate: d('2026-10-01') }), '2026-10-01', 'quarterly').periods).toEqual([
173
+ ['2026-10-01', '2026-12-31', 100],
174
+ ])
175
+ expect(run(item({ billStartDate: d('2026-01-01') }), '2026-01-01', 'annually').periods).toEqual([
176
+ ['2026-01-01', '2026-12-31', 100],
177
+ ])
178
+ })
179
+
180
+ it('skips inactive and soft-deleted items', () => {
181
+ expect(run(item({ isActive: false }), '2026-12-01').skipped[0].reason).toBe('item-inactive')
182
+ expect(run(item({ deletedAt: d('2026-11-20') }), '2026-12-01').skipped[0].reason).toBe('item-soft-deleted')
183
+ })
184
+
185
+ it('caps runaway backdating', () => {
186
+ const r = run(item({ chargeTiming: 'in_arrears', billStartDate: d('2000-01-01') }), '2026-12-01')
187
+ expect(r.lines).toHaveLength(MAX_PERIODS_PER_ITEM)
188
+ expect(r.skipped.at(-1)?.reason).toBe('period-cap-reached')
189
+ })
190
+ })
@@ -1,5 +1,4 @@
1
1
  import { captureTopup } from '../../lib/topupCapture'
2
- import { __resetInvoiceStatusCacheForTests } from '../../lib/invoiceStatus'
3
2
  import { createPrepaidMockEm } from '../helpers/prepaidMockEm'
4
3
 
5
4
  const ACCOUNT = {
@@ -9,22 +8,6 @@ const ACCOUNT = {
9
8
  currencyCode: 'EUR',
10
9
  }
11
10
 
12
- function makeDeps() {
13
- return {
14
- numberGenerator: {
15
- generate: jest.fn(async () => ({ number: 'FV/2026/06/0042', format: 'x', sequence: 42 })),
16
- },
17
- taxService: {
18
- calculateUnitAmounts: jest.fn(async (input: { amount: number }) => ({
19
- netAmount: input.amount,
20
- grossAmount: input.amount,
21
- taxAmount: 0,
22
- taxRate: 0,
23
- })),
24
- },
25
- }
26
- }
27
-
28
11
  function makeTopup(overrides: Record<string, unknown> = {}) {
29
12
  return {
30
13
  id: 'topup-1',
@@ -39,10 +22,6 @@ function makeTopup(overrides: Record<string, unknown> = {}) {
39
22
  }
40
23
  }
41
24
 
42
- beforeEach(() => {
43
- __resetInvoiceStatusCacheForTests()
44
- })
45
-
46
25
  describe('captureTopup', () => {
47
26
  it('credits the balance, issues a receipt, and flips the top-up to captured', async () => {
48
27
  const topup = makeTopup()
@@ -50,7 +29,7 @@ describe('captureTopup', () => {
50
29
  topup,
51
30
  balance: { tenantId: 'ten-1', billAccountId: 'acct-1', balance: '0.0000' },
52
31
  })
53
- const result = await captureTopup(em as never, makeDeps(), {
32
+ const result = await captureTopup(em as never, {
54
33
  topup: topup as never,
55
34
  account: ACCOUNT,
56
35
  taxRate: 0,
@@ -61,7 +40,7 @@ describe('captureTopup', () => {
61
40
  expect(result.balanceAfter).toBe('100.0000')
62
41
  expect(result.transactionId).toBeTruthy()
63
42
  expect(result.receiptInvoiceId).toBeTruthy()
64
- expect(result.invoiceNumber).toBe('FV/2026/06/0042')
43
+ expect(result.invoiceNumber).toMatch(/^RC\/\d{4}\/\d{2}\/0042$/)
65
44
 
66
45
  // The credit transaction carries the deterministic source_ref.
67
46
  expect(em.transactions).toHaveLength(1)
@@ -81,7 +60,7 @@ describe('captureTopup', () => {
81
60
  topup,
82
61
  balance: { tenantId: 'ten-1', billAccountId: 'acct-1', balance: '100.0000' },
83
62
  })
84
- const result = await captureTopup(em as never, makeDeps(), {
63
+ const result = await captureTopup(em as never, {
85
64
  topup: topup as never,
86
65
  account: ACCOUNT,
87
66
  taxRate: 0,
@@ -107,8 +86,7 @@ describe('captureTopup', () => {
107
86
  billAccountId: 'acct-1',
108
87
  createdAt: new Date('2026-06-10'),
109
88
  })
110
- const deps = makeDeps()
111
- const result = await captureTopup(em as never, deps, {
89
+ const result = await captureTopup(em as never, {
112
90
  topup: topup as never,
113
91
  account: ACCOUNT,
114
92
  taxRate: 0,
@@ -117,7 +95,7 @@ describe('captureTopup', () => {
117
95
  expect(result.balanceAfter).toBe('100.0000') // unchanged — dedup hit
118
96
  expect(result.receiptInvoiceId).toBe('inv-prior') // returns the existing receipt
119
97
  expect(em.transactions).toHaveLength(1) // no new credit transaction
120
- // No second fiscal document: the number generator was never called.
121
- expect(deps.numberGenerator.generate).not.toHaveBeenCalled()
98
+ // No second fiscal document: no receipt number was claimed.
99
+ expect(em.sequenceClaims).toEqual([])
122
100
  })
123
101
  })
@@ -1,5 +1,4 @@
1
- import { createTopupReceipt, type TopupReceiptDeps } from '../../lib/topupReceipt'
2
- import { __resetInvoiceStatusCacheForTests } from '../../lib/invoiceStatus'
1
+ import { createTopupReceipt } from '../../lib/topupReceipt'
3
2
  import { createPrepaidMockEm } from '../helpers/prepaidMockEm'
4
3
 
5
4
  const ACCOUNT = {
@@ -9,40 +8,12 @@ const ACCOUNT = {
9
8
  currencyCode: 'EUR',
10
9
  }
11
10
 
12
- function makeDeps(taxRateOut: number | null): TopupReceiptDeps {
13
- return {
14
- numberGenerator: {
15
- generate: jest.fn(async () => ({
16
- number: 'FV/2026/06/0042',
17
- format: 'FV/{yyyy}/{mm}/{seq:4}',
18
- sequence: 42,
19
- })),
20
- },
21
- taxService: {
22
- calculateUnitAmounts: jest.fn(async (input: { amount: number; taxRate?: number | string | null }) => {
23
- const rate = typeof input.taxRate === 'number' ? input.taxRate : Number(input.taxRate ?? 0)
24
- const gross = input.amount
25
- const net = rate > 0 ? gross / (1 + rate / 100) : gross
26
- return {
27
- netAmount: Math.round(net * 10000) / 10000,
28
- grossAmount: Math.round(gross * 10000) / 10000,
29
- taxAmount: Math.round((gross - net) * 10000) / 10000,
30
- taxRate: taxRateOut,
31
- }
32
- }),
33
- },
34
- }
35
- }
36
-
37
- beforeEach(() => {
38
- __resetInvoiceStatusCacheForTests()
39
- })
11
+ const RECEIPT_NUMBER = /^RC\/\d{4}\/\d{2}\/0042$/
40
12
 
41
13
  describe('createTopupReceipt — VAT at top-up (amount is gross)', () => {
42
- it('splits 100 gross @ 23% into net + VAT and posts paid', async () => {
14
+ it('splits 100 gross @ 23% into net + VAT and issues a paid receipt document', async () => {
43
15
  const em = createPrepaidMockEm()
44
- const deps = makeDeps(23)
45
- const receipt = await createTopupReceipt(em as never, deps, {
16
+ const receipt = await createTopupReceipt(em as never, {
46
17
  account: ACCOUNT,
47
18
  topupId: 'topup-1',
48
19
  paymentId: 'pay-1',
@@ -50,35 +21,33 @@ describe('createTopupReceipt — VAT at top-up (amount is gross)', () => {
50
21
  taxRate: 23,
51
22
  })
52
23
 
53
- expect(receipt.invoiceNumber).toBe('FV/2026/06/0042')
54
- expect(receipt.grossAmount).toBe('100.0000')
55
- expect(receipt.netAmount).toBe('81.3008')
56
- expect(receipt.taxAmount).toBe('18.6992')
57
- expect(receipt.taxRate).toBe(23)
24
+ expect(receipt.invoiceNumber).toMatch(RECEIPT_NUMBER)
25
+ expect(receipt).toMatchObject({ grossAmount: '100.0000', netAmount: '81.3000', taxAmount: '18.7000', taxRate: 23 })
26
+ expect(em.sequenceClaims).toEqual(['receipt'])
58
27
 
59
- // The invoice was persisted as paid with a single top-up line.
60
- const invoice = em.persisted.find((e) => (e as { status?: string }).status === 'paid') as Record<
61
- string,
62
- unknown
63
- >
64
- expect(invoice).toBeTruthy()
65
- expect(invoice.paidTotalAmount).toBe('100.0000')
66
- expect(invoice.outstandingAmount).toBe('0')
67
- expect((invoice.metadata as Record<string, unknown>).kind).toBe('prepaid_topup')
28
+ const doc = em.persisted.find((e) => (e as { documentType?: string }).documentType === 'receipt') as Record<string, unknown>
29
+ expect(doc).toMatchObject({
30
+ status: 'paid',
31
+ series: 'receipt',
32
+ topupId: 'topup-1',
33
+ billAccountId: 'acct-1',
34
+ paidTotal: '100.0000',
35
+ outstanding: '0',
36
+ totalGross: '100.0000',
37
+ })
38
+ const line = em.persisted.find((e) => (e as { billingType?: string }).billingType === 'receipt') as Record<string, unknown>
39
+ expect(line).toMatchObject({ invoiceId: doc.id, taxRate: '23.0000', netAmount: '81.3000', taxAmount: '18.7000' })
68
40
  })
69
41
 
70
42
  it('0% VAT → net == gross, tax 0', async () => {
71
43
  const em = createPrepaidMockEm()
72
- const deps = makeDeps(null)
73
- const receipt = await createTopupReceipt(em as never, deps, {
44
+ const receipt = await createTopupReceipt(em as never, {
74
45
  account: ACCOUNT,
75
46
  topupId: 'topup-2',
76
47
  paymentId: 'pay-2',
77
48
  amount: '50.0000',
78
49
  taxRate: 0,
79
50
  })
80
- expect(receipt.netAmount).toBe('50.0000')
81
- expect(receipt.grossAmount).toBe('50.0000')
82
- expect(receipt.taxAmount).toBe('0.0000')
51
+ expect(receipt).toMatchObject({ netAmount: '50.0000', grossAmount: '50.0000', taxAmount: '0.0000', taxRate: 0 })
83
52
  })
84
53
  })
@@ -0,0 +1,51 @@
1
+ import { DefaultTaxCalculationService } from '@open-mercato/core/modules/sales/services/taxCalculationService'
2
+ import { lineAmountsFromGross, lineAmountsFromNet, money4, round2, sumTotals } from '../../lib/vat'
3
+
4
+ describe('vat', () => {
5
+ it('rounds half-up symmetrically', () => {
6
+ expect(round2(1.005)).toBe(1.01)
7
+ expect(round2(-1.005)).toBe(-1.01)
8
+ expect(round2(2.675)).toBe(2.68)
9
+ })
10
+
11
+ it('computes from net with net + tax = gross', () => {
12
+ expect(lineAmountsFromNet(100, 23)).toEqual({ net: 100, tax: 23, gross: 123 })
13
+ expect(lineAmountsFromNet(56.67, 23)).toEqual({ net: 56.67, tax: 13.03, gross: 69.7 })
14
+ expect(lineAmountsFromNet(10, 0)).toEqual({ net: 10, tax: 0, gross: 10 })
15
+ expect(lineAmountsFromNet(-51.61, 23)).toEqual({ net: -51.61, tax: -11.87, gross: -63.48 })
16
+ })
17
+
18
+ it('splits gross with net + tax = gross exactly', () => {
19
+ for (const [gross, rate] of [[100, 23], [99.99, 8], [0.01, 23], [123, 5], [50, 0]] as const) {
20
+ const r = lineAmountsFromGross(gross, rate)
21
+ expect(round2(r.net + r.tax)).toBe(r.gross)
22
+ expect(r.gross).toBe(round2(gross))
23
+ }
24
+ expect(lineAmountsFromGross(123, 23)).toEqual({ net: 100, tax: 23, gross: 123 })
25
+ })
26
+
27
+ it('sums rounded lines into 4dp column strings', () => {
28
+ expect(sumTotals([lineAmountsFromNet(100, 23), lineAmountsFromNet(56.67, 23)])).toEqual({
29
+ subtotalNet: '156.6700',
30
+ taxTotal: '36.0300',
31
+ totalGross: '192.7000',
32
+ })
33
+ expect(money4(Number.NaN)).toBe('0.0000')
34
+ })
35
+
36
+ it('stays within half a cent of the core tax service (gross split parity)', async () => {
37
+ const core = new DefaultTaxCalculationService({} as never)
38
+ for (const [gross, rate] of [[100, 23], [99.99, 8], [250, 5], [1234.56, 23], [0.99, 23]] as const) {
39
+ const ours = lineAmountsFromGross(gross, rate)
40
+ const theirs = await core.calculateUnitAmounts({
41
+ amount: gross,
42
+ mode: 'gross',
43
+ organizationId: 'o',
44
+ tenantId: 't',
45
+ taxRate: rate,
46
+ })
47
+ expect(Math.abs(ours.net - theirs.netAmount)).toBeLessThanOrEqual(0.005)
48
+ expect(Math.abs(ours.tax - theirs.taxAmount)).toBeLessThanOrEqual(0.005)
49
+ }
50
+ })
51
+ })