@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
@@ -5,7 +5,9 @@ const TENANT = 'ten-1'
5
5
  const ORG = 'org-1'
6
6
  const ACCT = 'acct-1'
7
7
 
8
- function prepaidAccount(overrides: Record<string, unknown> = {}) {
8
+ type Row = Record<string, unknown>
9
+
10
+ function prepaidAccount(overrides: Row = {}): Row {
9
11
  return {
10
12
  id: ACCT,
11
13
  tenantId: TENANT,
@@ -26,47 +28,83 @@ const realParams = {
26
28
  asOfDate: new Date('2026-06-01'),
27
29
  mode: 'real' as const,
28
30
  triggeredBy: 'manual' as const,
29
- catchUp: false,
30
31
  }
31
32
 
32
- function recurringItem() {
33
+ /** A recurring item already charged through April, billed in arrears (the pre-Spec F behaviour). */
34
+ function arrearsItem(overrides: Row = {}): Row {
33
35
  return {
34
36
  id: 'item-rec',
35
37
  type: 'recurring',
36
38
  billStartDate: new Date('2026-01-01'),
37
39
  billEndDate: null,
38
- billedToDate: null,
40
+ billedToDate: new Date('2026-04-30'),
41
+ chargeTiming: 'in_arrears',
42
+ prorate: true,
43
+ taxRate: '23',
44
+ priceBasis: 'net',
39
45
  isActive: true,
40
46
  deletedAt: null,
41
47
  rateJson: { unit_price: 20 },
42
48
  description: 'Platform fee',
49
+ ...overrides,
43
50
  }
44
51
  }
45
52
 
46
53
  // Seed the period's real-time movements: a 100 top-up + 103 usage (May 2026).
47
54
  function seedWindowActivity(em: MockEm) {
48
55
  em.transactions.push(
49
- {
50
- id: 't-top',
51
- type: 'topup',
52
- amount: '100.0000',
53
- billAccountId: ACCT,
54
- createdAt: new Date('2026-05-02'),
55
- },
56
- {
57
- id: 't-use',
58
- type: 'usage',
59
- amount: '-103.0000',
60
- billAccountId: ACCT,
61
- createdAt: new Date('2026-05-15'),
62
- },
56
+ { id: 't-top', type: 'topup', amount: '100.0000', billAccountId: ACCT, createdAt: new Date('2026-05-02') },
57
+ { id: 't-use', type: 'usage', amount: '-103.0000', billAccountId: ACCT, createdAt: new Date('2026-05-15') },
63
58
  )
64
59
  }
65
60
 
66
- describe('processPrepaidAccount — period close (spec story step 6)', () => {
61
+ function persistedStatement(em: MockEm): Row {
62
+ return em.persisted.find((e) => (e as { status?: string }).status === 'generated') as Row
63
+ }
64
+
65
+ function iso(value: unknown): string {
66
+ return new Date(value as Date | string).toISOString().slice(0, 10)
67
+ }
68
+
69
+ function okResult<T extends { status: string }>(result: T): Exclude<T, { status: 'failed' }> {
70
+ if (result.status === 'failed') throw new Error('unexpected failure')
71
+ return result as Exclude<T, { status: 'failed' }>
72
+ }
73
+
74
+ describe('processPrepaidAccount — period close and statement (SPEC-002)', () => {
75
+ it('catches up on every due period in one real run', async () => {
76
+ const account = prepaidAccount()
77
+ const em = createPrepaidMockEm({
78
+ account,
79
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '0.0000' },
80
+ items: [arrearsItem()],
81
+ existingStatement: null,
82
+ })
83
+
84
+ const result = okResult(
85
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
86
+ ...realParams,
87
+ triggeredBy: 'schedule',
88
+ asOfDate: new Date('2026-08-01'),
89
+ }),
90
+ )
91
+ expect(result.cyclesEmitted).toBe(3)
92
+ expect(result.cycles.map((c) => [c.bill_date, c.status])).toEqual([
93
+ ['2026-06-01', 'charged'],
94
+ ['2026-07-01', 'charged'],
95
+ ['2026-08-01', 'charged'],
96
+ ])
97
+ expect(iso(account.nextBillDate)).toBe('2026-09-01')
98
+ expect(em.transactions.filter((t) => t.type === 'recurring').map((t) => t.sourceRef)).toEqual([
99
+ 'recurring-item-rec-charge-2026-05-01-2026-05-31',
100
+ 'recurring-item-rec-charge-2026-06-01-2026-06-30',
101
+ 'recurring-item-rec-charge-2026-07-01-2026-07-31',
102
+ ])
103
+ })
104
+
67
105
  it('charges recurring to the balance and builds the statement', async () => {
68
106
  const account = prepaidAccount()
69
- const item = recurringItem()
107
+ const item = arrearsItem()
70
108
  const em = createPrepaidMockEm({
71
109
  account,
72
110
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '-3.0000' },
@@ -75,36 +113,34 @@ describe('processPrepaidAccount — period close (spec story step 6)', () => {
75
113
  })
76
114
  seedWindowActivity(em)
77
115
 
78
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
79
-
116
+ const result = okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
80
117
  expect(result.status).toBe('success')
81
- if (result.status === 'failed') throw new Error('unexpected failure')
82
118
  expect(result.statementId).toBeTruthy()
83
119
  expect(result.statementEvents.map((e) => e.id)).toEqual(['billing.statement.generated'])
84
120
 
85
- // The recurring charge hit the balance with a deterministic source_ref.
86
- const recurringTxn = em.transactions.find((t) => t.type === 'recurring')
87
- expect(recurringTxn).toBeTruthy()
88
- expect(recurringTxn!.amount).toBe('-20.0000')
89
- expect(recurringTxn!.sourceRef).toBe('recurring-item-rec-2026-05-31')
90
-
91
- // The statement chains: opening 0, +100 topups, −103 usage, −20 recurring = −23.
92
- const statement = em.persisted.find(
93
- (e) => (e as { status?: string }).status === 'generated',
94
- ) as Record<string, unknown>
95
- expect(statement).toBeTruthy()
121
+ const recurringTxn = em.transactions.find((t) => t.type === 'recurring')!
122
+ expect(recurringTxn.amount).toBe('-20.0000')
123
+ expect(recurringTxn.metadata).toMatchObject({
124
+ service_period_start: '2026-05-01',
125
+ service_period_end: '2026-05-31',
126
+ tax_point: 'topup',
127
+ tax: '0.0000',
128
+ })
129
+
130
+ // opening 0, +100 top-ups, −103 usage, −20 charges = −23.
131
+ const statement = persistedStatement(em)
96
132
  expect(statement.openingBalance).toBe('0.0000')
97
133
  expect(statement.totalTopups).toBe('100.0000')
98
134
  expect(statement.totalUsage).toBe('103.0000')
99
135
  expect(statement.totalRecurring).toBe('20.0000')
100
136
  expect(statement.closingBalance).toBe('-23.0000')
137
+ expect(statement.vatSummary).toEqual([])
101
138
 
102
- // billed_to_date guard set; the cycle advanced.
103
- expect(item.billedToDate).toEqual(new Date('2026-05-31'))
104
- expect((account.nextBillDate as Date).toISOString().slice(0, 7)).toBe('2026-07')
139
+ expect(iso(item.billedToDate)).toBe('2026-05-31')
140
+ expect(iso(account.nextBillDate)).toBe('2026-07-01')
105
141
  })
106
142
 
107
- it('still generates a statement with no recurring items (usage-only account)', async () => {
143
+ it('still generates a statement with no charges (usage-only account)', async () => {
108
144
  const account = prepaidAccount()
109
145
  const em = createPrepaidMockEm({
110
146
  account,
@@ -113,25 +149,20 @@ describe('processPrepaidAccount — period close (spec story step 6)', () => {
113
149
  })
114
150
  seedWindowActivity(em)
115
151
 
116
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
117
- if (result.status === 'failed') throw new Error('unexpected failure')
152
+ const result = okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
118
153
  expect(result.statementId).toBeTruthy()
119
- const statement = em.persisted.find(
120
- (e) => (e as { status?: string }).status === 'generated',
121
- ) as Record<string, unknown>
154
+ expect(result.cycles[0].status).toBe('empty')
155
+ const statement = persistedStatement(em)
122
156
  expect(statement.totalRecurring).toBe('0.0000')
123
157
  expect(statement.closingBalance).toBe('-3.0000') // 0 + 100 − 103 − 0
124
158
  })
125
159
 
126
160
  it('chains the opening balance from the prior statement closing', async () => {
127
- // Prior month closed at −23. This month: +50 top-ups, −40 usage, −20 recurring
128
- // → opening −23, closing −23 + 50 − 40 − 20 = −33. (A created_at sum would
129
- // wrongly drop the prior recurring and overstate the opening.)
130
161
  const account = prepaidAccount()
131
162
  const em = createPrepaidMockEm({
132
163
  account,
133
164
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '-13.0000' },
134
- items: [recurringItem()],
165
+ items: [arrearsItem()],
135
166
  existingStatement: null,
136
167
  priorStatement: { id: 'stmt-may', closingBalance: '-23.0000' },
137
168
  })
@@ -140,93 +171,338 @@ describe('processPrepaidAccount — period close (spec story step 6)', () => {
140
171
  { id: 't-use2', type: 'usage', amount: '-40.0000', billAccountId: ACCT, createdAt: new Date('2026-05-20') },
141
172
  )
142
173
 
143
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
144
- if (result.status === 'failed') throw new Error('unexpected failure')
145
- const statement = em.persisted.find(
146
- (e) => (e as { status?: string }).status === 'generated',
147
- ) as Record<string, unknown>
174
+ okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
175
+ const statement = persistedStatement(em)
148
176
  expect(statement.openingBalance).toBe('-23.0000')
149
- expect(statement.totalTopups).toBe('50.0000')
150
- expect(statement.totalUsage).toBe('40.0000')
151
- expect(statement.totalRecurring).toBe('20.0000')
152
- expect(statement.closingBalance).toBe('-33.0000')
177
+ expect(statement.closingBalance).toBe('-33.0000') // −23 + 50 − 40 − 20
153
178
  })
154
179
 
155
- it('fires a balance.low crossing when the recurring charge drops into the low band', async () => {
156
- // Balance 25 with threshold 10; the €20 recurring fee drops it to 5 → low.
180
+ it('fires a balance.low crossing when a charge drops into the low band', async () => {
157
181
  const account = prepaidAccount()
158
182
  const em = createPrepaidMockEm({
159
183
  account,
160
184
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '25.0000', lowBalanceThreshold: '10.0000' },
161
- items: [recurringItem()],
185
+ items: [arrearsItem()],
162
186
  })
163
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
164
- if (result.status === 'failed') throw new Error('unexpected failure')
165
- expect(result.statementEvents.map((e) => e.id)).toContain('billing.balance.low')
166
- expect(result.statementEvents.map((e) => e.id)).toContain('billing.statement.generated')
187
+ const result = okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
188
+ expect(result.statementEvents.map((e) => e.id)).toEqual(
189
+ expect.arrayContaining(['billing.balance.low', 'billing.statement.generated']),
190
+ )
167
191
  })
168
192
 
169
- it('includes manual adjustments in the statement math (closing stays consistent)', async () => {
170
- // Window has a +10 adjustment. opening 0, topups 100, usage 103, adj +10,
171
- // recurring 20 → closing 0 + 100 + 10 − 103 − 20 = −13.
193
+ it('includes manual adjustments in the statement math', async () => {
172
194
  const account = prepaidAccount()
173
195
  const em = createPrepaidMockEm({
174
196
  account,
175
197
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '7.0000' },
176
- items: [recurringItem()],
198
+ items: [arrearsItem()],
177
199
  })
178
200
  seedWindowActivity(em)
179
- em.transactions.push({
180
- id: 't-adj',
181
- type: 'adjustment',
182
- amount: '10.0000',
183
- billAccountId: ACCT,
184
- createdAt: new Date('2026-05-12'),
185
- })
186
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
187
- if (result.status === 'failed') throw new Error('unexpected failure')
188
- const statement = em.persisted.find(
189
- (e) => (e as { status?: string }).status === 'generated',
190
- ) as Record<string, unknown>
201
+ em.transactions.push({ id: 't-adj', type: 'adjustment', amount: '10.0000', billAccountId: ACCT, createdAt: new Date('2026-05-12') })
202
+ okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
203
+ const statement = persistedStatement(em)
191
204
  expect(statement.totalAdjustments).toBe('10.0000')
192
205
  expect(statement.closingBalance).toBe('-13.0000')
193
206
  })
207
+ })
194
208
 
195
- it('skips when a statement already exists for the period (anti-duplicate)', async () => {
209
+ describe('processPrepaidAccount — anti-duplicate (Spec F)', () => {
210
+ it('an existing statement is not duplicated; charges stay idempotent and the account advances', async () => {
196
211
  const account = prepaidAccount()
197
212
  const em = createPrepaidMockEm({
198
213
  account,
199
214
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '-3.0000' },
200
- items: [recurringItem()],
215
+ items: [arrearsItem()],
201
216
  existingStatement: { id: 'stmt-prior' },
202
217
  })
203
- seedWindowActivity(em)
204
-
205
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, realParams)
206
- expect(result.status).toBe('skipped_existing_statement')
207
- if (result.status === 'failed') throw new Error('unexpected failure')
208
- expect(result.statementId).toBe('stmt-prior')
209
- // No recurring charge applied.
210
- expect(em.transactions.find((t) => t.type === 'recurring')).toBeUndefined()
218
+ const result = okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
219
+ expect(result.statementId).toBeNull()
220
+ expect(persistedStatement(em)).toBeUndefined()
221
+ expect(result.cycles[0]).toMatchObject({ status: 'charged', statement_id: 'stmt-prior' })
222
+ // Never stuck behind the existing statement.
223
+ expect(iso(account.nextBillDate)).toBe('2026-07-01')
211
224
  })
212
225
 
213
- it('dry run computes nothing persisted and does not advance', async () => {
226
+ it('reports skipped_existing when the statement and the charge both already exist', async () => {
214
227
  const account = prepaidAccount()
215
228
  const em = createPrepaidMockEm({
216
229
  account,
217
230
  balance: { tenantId: TENANT, billAccountId: ACCT, balance: '-3.0000' },
218
- items: [recurringItem()],
231
+ items: [arrearsItem()],
232
+ existingStatement: { id: 'stmt-prior' },
219
233
  })
220
- seedWindowActivity(em)
234
+ em.transactions.push({
235
+ id: 't-charged',
236
+ type: 'recurring',
237
+ amount: '-20.0000',
238
+ billAccountId: ACCT,
239
+ sourceRef: 'recurring-item-rec-charge-2026-05-01-2026-05-31',
240
+ createdAt: new Date('2026-06-01'),
241
+ })
242
+ const result = okResult(await processPrepaidAccount(em as never, account as never, billRun as never, realParams))
243
+ expect(result.cycles[0].status).toBe('skipped_existing')
244
+ expect(em.transactions.filter((t) => t.type === 'recurring')).toHaveLength(1)
245
+ })
246
+ })
221
247
 
222
- const result = await processPrepaidAccount(em as never, account as never, billRun as never, {
223
- ...realParams,
224
- mode: 'dry',
248
+ describe('processPrepaidAccount — charge timing and proration (Spec F, F-D4)', () => {
249
+ // The operator's scenario, with dates as MikroORM hydrates `date` columns
250
+ // (YYYY-MM-DD strings) — the F4 report: a real run as of the second bill
251
+ // date must close BOTH bill dates.
252
+ function operatorScenario(chargeTiming: 'in_advance' | 'in_arrears') {
253
+ const account = prepaidAccount({ nextBillDate: '2026-11-14' })
254
+ const setupFee = {
255
+ id: 'item-setup',
256
+ type: 'one_time',
257
+ billStartDate: '2026-11-14',
258
+ billEndDate: null,
259
+ billedToDate: null,
260
+ taxRate: '23',
261
+ priceBasis: 'net',
262
+ isActive: true,
263
+ deletedAt: null,
264
+ rateJson: { amount: 99 },
265
+ description: 'Setup fee',
266
+ }
267
+ const plan = {
268
+ ...arrearsItem({ id: 'item-plan', description: 'Plan', rateJson: { unit_price: 49 } }),
269
+ billStartDate: '2026-11-14',
270
+ billedToDate: null,
271
+ chargeTiming,
272
+ }
273
+ const em = createPrepaidMockEm({
274
+ account,
275
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '500.0000' },
276
+ items: [setupFee, plan],
225
277
  })
226
- if (result.status === 'failed') throw new Error('unexpected failure')
278
+ return { account, em, plan, setupFee }
279
+ }
280
+
281
+ it('in advance: the Nov 14 run charges the setup fee + Nov 14–Dec 13, the Dec 14 cycle charges Dec 14–Jan 13', async () => {
282
+ const { account, em, plan } = operatorScenario('in_advance')
283
+ const result = okResult(
284
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
285
+ ...realParams,
286
+ asOfDate: new Date('2026-12-14'),
287
+ }),
288
+ )
289
+ expect(result.cycles.map((c) => [c.bill_date, c.status, c.total_debit])).toEqual([
290
+ ['2026-11-14', 'charged', '148.0000'],
291
+ ['2026-12-14', 'charged', '49.0000'],
292
+ ])
293
+ expect(em.transactions.filter((t) => t.type !== 'topup').map((t) => [t.type, t.amount, t.sourceRef])).toEqual([
294
+ ['recurring', '-49.0000', 'recurring-item-plan-charge-2026-11-14-2026-12-13'],
295
+ ['one_time', '-99.0000', 'one_time-item-setup'],
296
+ ['recurring', '-49.0000', 'recurring-item-plan-charge-2026-12-14-2027-01-13'],
297
+ ])
298
+ expect(iso(account.nextBillDate)).toBe('2027-01-14')
299
+ expect(iso(plan.billedToDate)).toBe('2027-01-13')
300
+ })
301
+
302
+ it('in arrears: the Nov 14 bill date charges only the setup fee; Dec 14 charges Nov 14–Dec 13', async () => {
303
+ const { account, em } = operatorScenario('in_arrears')
304
+ const result = okResult(
305
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
306
+ ...realParams,
307
+ asOfDate: new Date('2026-12-14'),
308
+ }),
309
+ )
310
+ expect(result.cycles.map((c) => [c.bill_date, c.total_debit])).toEqual([
311
+ ['2026-11-14', '99.0000'],
312
+ ['2026-12-14', '49.0000'],
313
+ ])
314
+ expect(em.transactions.find((t) => t.type === 'recurring')!.sourceRef).toBe(
315
+ 'recurring-item-plan-charge-2026-11-14-2026-12-13',
316
+ )
317
+ expect(iso(account.nextBillDate)).toBe('2027-01-14')
318
+ })
319
+
320
+ it('switching in advance → in arrears never charges a period twice', async () => {
321
+ const account = prepaidAccount({ nextBillDate: '2026-12-14' })
322
+ const item = arrearsItem({ billStartDate: '2026-11-14', billedToDate: '2026-12-13', chargeTiming: 'in_arrears' })
323
+ const em = createPrepaidMockEm({ account, balance: { tenantId: TENANT, billAccountId: ACCT, balance: '0' }, items: [item] })
324
+ const result = okResult(
325
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
326
+ ...realParams,
327
+ asOfDate: new Date('2026-12-14'),
328
+ }),
329
+ )
330
+ expect(result.cycles[0].status).toBe('empty')
331
+ expect(em.transactions.filter((t) => t.type === 'recurring')).toHaveLength(0)
332
+ })
333
+
334
+ it('prorates a mid-period start; with prorate off it is skipped and reported', async () => {
335
+ const make = (prorate: boolean) => {
336
+ const account = prepaidAccount({ nextBillDate: '2026-11-14' })
337
+ const item = arrearsItem({
338
+ billStartDate: '2026-11-20',
339
+ billedToDate: null,
340
+ chargeTiming: 'in_advance',
341
+ prorate,
342
+ rateJson: { unit_price: 49 },
343
+ })
344
+ return { account, em: createPrepaidMockEm({ account, balance: { tenantId: TENANT, billAccountId: ACCT, balance: '0' }, items: [item] }) }
345
+ }
346
+ const params = { ...realParams, asOfDate: new Date('2026-11-14') }
347
+
348
+ const prorated = make(true)
349
+ okResult(await processPrepaidAccount(prorated.em as never, prorated.account as never, billRun as never, params))
350
+ // Nov 20 – Dec 13 = 24 of 30 days → 49 × 24 / 30 = 39.20.
351
+ expect(prorated.em.transactions.find((t) => t.type === 'recurring')!.amount).toBe('-39.2000')
352
+
353
+ const skipped = make(false)
354
+ const result = okResult(await processPrepaidAccount(skipped.em as never, skipped.account as never, billRun as never, params))
355
+ expect(skipped.em.transactions.filter((t) => t.type === 'recurring')).toHaveLength(0)
356
+ expect(result.warnings?.skipped_items?.[0]).toMatchObject({ item_id: 'item-rec', reason: 'partial-period-not-prorated' })
357
+ })
358
+
359
+ it('credits unused days back to the balance when an item ends inside a charged period', async () => {
360
+ const account = prepaidAccount({ nextBillDate: '2026-12-14' })
361
+ const item = arrearsItem({
362
+ billStartDate: '2026-11-14',
363
+ billEndDate: '2026-11-30',
364
+ billedToDate: '2026-12-13',
365
+ chargeTiming: 'in_advance',
366
+ rateJson: { unit_price: 30 },
367
+ })
368
+ const em = createPrepaidMockEm({ account, balance: { tenantId: TENANT, billAccountId: ACCT, balance: '0' }, items: [item] })
369
+ okResult(
370
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
371
+ ...realParams,
372
+ asOfDate: new Date('2026-12-14'),
373
+ }),
374
+ )
375
+ const credit = em.transactions.find((t) => String(t.sourceRef).includes('-credit-'))!
376
+ expect(credit.type).toBe('recurring')
377
+ expect(Number(credit.amount)).toBeGreaterThan(0)
378
+ })
379
+ })
380
+
381
+ describe('processPrepaidAccount — tax point (Spec F, F-D3)', () => {
382
+ function run(taxPoint: 'topup' | 'consumption', item: Row) {
383
+ const account = prepaidAccount()
384
+ const em = createPrepaidMockEm({
385
+ account,
386
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '100.0000' },
387
+ items: [item],
388
+ configs: { 'prepaid.tax_point': taxPoint },
389
+ })
390
+ return { em, promise: processPrepaidAccount(em as never, account as never, billRun as never, realParams) }
391
+ }
392
+
393
+ it('topup: debits the item amount as entered, without VAT', async () => {
394
+ const { em, promise } = run('topup', arrearsItem({ rateJson: { unit_price: 49 } }))
395
+ okResult(await promise)
396
+ expect(em.transactions.find((t) => t.type === 'recurring')!.amount).toBe('-49.0000')
397
+ expect(persistedStatement(em).vatSummary).toEqual([])
398
+ })
399
+
400
+ it('consumption: debits the gross at the item rate (10 net @ 23 % → 12.30)', async () => {
401
+ const { em, promise } = run('consumption', arrearsItem({ rateJson: { unit_price: 10 } }))
402
+ okResult(await promise)
403
+ const txn = em.transactions.find((t) => t.type === 'recurring')!
404
+ expect(txn.amount).toBe('-12.3000')
405
+ expect(txn.metadata).toMatchObject({ net: '10.0000', tax: '2.3000', tax_rate: '23', tax_point: 'consumption' })
406
+ expect(persistedStatement(em).vatSummary).toEqual([{ rate: '23', net: '10.0000', tax: '2.3000', gross: '12.3000' }])
407
+ expect(em.balances.get(`${TENANT}:${ACCT}`)!.balance).toBe('87.7000')
408
+ })
409
+
410
+ it('consumption: a gross-basis price is debited exactly as typed', async () => {
411
+ const { em, promise } = run('consumption', arrearsItem({ priceBasis: 'gross', rateJson: { unit_price: 12.3 } }))
412
+ okResult(await promise)
413
+ expect(em.transactions.find((t) => t.type === 'recurring')!.amount).toBe('-12.3000')
414
+ })
415
+ })
416
+
417
+ describe('processPrepaidAccount — test and dry runs (Spec F, P-D9)', () => {
418
+ it('test mode previews every due cycle and persists nothing', async () => {
419
+ const account = prepaidAccount()
420
+ const item = arrearsItem()
421
+ const em = createPrepaidMockEm({ account, balance: { tenantId: TENANT, billAccountId: ACCT, balance: '0' }, items: [item] })
422
+ const result = okResult(
423
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
424
+ ...realParams,
425
+ mode: 'test',
426
+ asOfDate: new Date('2026-08-01'),
427
+ }),
428
+ )
429
+ expect(result.cycles.map((c) => c.status)).toEqual(['previewed', 'previewed', 'previewed'])
430
+ expect(result.cyclesEmitted).toBe(3)
431
+ expect(em.transactions.filter((t) => t.type === 'recurring')).toHaveLength(0)
432
+ expect(persistedStatement(em)).toBeUndefined()
433
+ expect(iso(account.nextBillDate)).toBe('2026-06-01')
434
+ expect(iso(item.billedToDate)).toBe('2026-04-30')
435
+ })
436
+
437
+ it('dry run persists nothing and does not advance', async () => {
438
+ const account = prepaidAccount()
439
+ const em = createPrepaidMockEm({
440
+ account,
441
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '-3.0000' },
442
+ items: [arrearsItem()],
443
+ })
444
+ seedWindowActivity(em)
445
+ const result = okResult(
446
+ await processPrepaidAccount(em as never, account as never, billRun as never, { ...realParams, mode: 'dry' }),
447
+ )
227
448
  expect(result.statementId).toBeNull()
449
+ expect(result.cycles[0]).toMatchObject({ status: 'previewed', total_debit: '20.0000' })
228
450
  expect(em.transactions.find((t) => t.type === 'recurring')).toBeUndefined()
229
- // Cycle not advanced (still June 1).
230
- expect((account.nextBillDate as Date).toISOString().slice(0, 10)).toBe('2026-06-01')
451
+ expect(iso(account.nextBillDate)).toBe('2026-06-01')
452
+ })
453
+ })
454
+
455
+ describe('processPrepaidAccount — statement window includes the bill date (Spec F tweak)', () => {
456
+ it('a top-up made ON the bill date funds that statement: no negative opening on the next one', async () => {
457
+ // Bill date Nov 15; 300 topped up on Nov 15; one-time 99 + monthly 49 in
458
+ // advance, both from Nov 1; run executed later, as of Dec 31.
459
+ const account = prepaidAccount({ nextBillDate: '2026-11-15' })
460
+ const fee = {
461
+ id: 'item-fee',
462
+ type: 'one_time',
463
+ billStartDate: '2026-11-01',
464
+ billEndDate: null,
465
+ billedToDate: null,
466
+ taxRate: '23',
467
+ priceBasis: 'net',
468
+ isActive: true,
469
+ deletedAt: null,
470
+ rateJson: { amount: 99 },
471
+ description: 'Setup fee',
472
+ }
473
+ const plan = arrearsItem({
474
+ id: 'item-plan',
475
+ billStartDate: '2026-11-01',
476
+ billedToDate: null,
477
+ chargeTiming: 'in_advance',
478
+ rateJson: { unit_price: 49 },
479
+ })
480
+ const em = createPrepaidMockEm({
481
+ account,
482
+ balance: { tenantId: TENANT, billAccountId: ACCT, balance: '300.0000' },
483
+ items: [fee, plan],
484
+ })
485
+ em.transactions.push({
486
+ id: 't-topup',
487
+ type: 'topup',
488
+ amount: '300.0000',
489
+ billAccountId: ACCT,
490
+ createdAt: new Date('2026-11-15T10:00:00Z'),
491
+ })
492
+
493
+ okResult(
494
+ await processPrepaidAccount(em as never, account as never, billRun as never, {
495
+ ...realParams,
496
+ asOfDate: new Date('2026-12-31'),
497
+ }),
498
+ )
499
+ const statements = em.persisted.filter((e) => (e as { status?: string }).status === 'generated') as Row[]
500
+ expect(statements).toHaveLength(2)
501
+ const [first, second] = statements
502
+ expect(first.openingBalance).toBe('0.0000')
503
+ expect(first.totalTopups).toBe('300.0000')
504
+ expect(Number(first.closingBalance)).toBeGreaterThan(0)
505
+ expect(second.openingBalance).toBe(first.closingBalance)
506
+ expect(second.totalTopups).toBe('0.0000')
231
507
  })
232
508
  })