@dainamite/billing 0.20.0 → 0.22.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 (604) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/dist/modules/billing/acl.js +13 -1
  3. package/dist/modules/billing/acl.js.map +2 -2
  4. package/dist/modules/billing/api/accounts/[id]/summary/route.js +52 -0
  5. package/dist/modules/billing/api/accounts/[id]/summary/route.js.map +7 -0
  6. package/dist/modules/billing/api/accounts/route.js +47 -4
  7. package/dist/modules/billing/api/accounts/route.js.map +2 -2
  8. package/dist/modules/billing/api/export/account/[id]/route.js +11 -7
  9. package/dist/modules/billing/api/export/account/[id]/route.js.map +2 -2
  10. package/dist/modules/billing/api/invoices/[id]/memos/route.js +54 -0
  11. package/dist/modules/billing/api/invoices/[id]/memos/route.js.map +7 -0
  12. package/dist/modules/billing/api/invoices/[id]/pdf/route.js +70 -0
  13. package/dist/modules/billing/api/invoices/[id]/pdf/route.js.map +7 -0
  14. package/dist/modules/billing/api/invoices/[id]/route.js +44 -24
  15. package/dist/modules/billing/api/invoices/[id]/route.js.map +2 -2
  16. package/dist/modules/billing/api/invoices/[id]/send/route.js +107 -0
  17. package/dist/modules/billing/api/invoices/[id]/send/route.js.map +7 -0
  18. package/dist/modules/billing/api/invoices/add-line/route.js +2 -2
  19. package/dist/modules/billing/api/invoices/add-line/route.js.map +2 -2
  20. package/dist/modules/billing/api/invoices/delete-draft/route.js +33 -0
  21. package/dist/modules/billing/api/invoices/delete-draft/route.js.map +7 -0
  22. package/dist/modules/billing/api/invoices/edit-line/route.js +2 -2
  23. package/dist/modules/billing/api/invoices/edit-line/route.js.map +2 -2
  24. package/dist/modules/billing/api/invoices/post/route.js +2 -2
  25. package/dist/modules/billing/api/invoices/post/route.js.map +2 -2
  26. package/dist/modules/billing/api/invoices/remove-line/route.js +2 -2
  27. package/dist/modules/billing/api/invoices/remove-line/route.js.map +2 -2
  28. package/dist/modules/billing/api/invoices/route.js +45 -46
  29. package/dist/modules/billing/api/invoices/route.js.map +2 -2
  30. package/dist/modules/billing/api/items/bulk/route.js +1 -1
  31. package/dist/modules/billing/api/items/bulk/route.js.map +2 -2
  32. package/dist/modules/billing/api/items/change-price/route.js +44 -0
  33. package/dist/modules/billing/api/items/change-price/route.js.map +7 -0
  34. package/dist/modules/billing/api/items/route.js +19 -7
  35. package/dist/modules/billing/api/items/route.js.map +2 -2
  36. package/dist/modules/billing/api/payment-imports/[id]/route.js +49 -0
  37. package/dist/modules/billing/api/payment-imports/[id]/route.js.map +7 -0
  38. package/dist/modules/billing/api/payment-imports/route.js +57 -0
  39. package/dist/modules/billing/api/payment-imports/route.js.map +7 -0
  40. package/dist/modules/billing/api/payments/[id]/route.js +60 -0
  41. package/dist/modules/billing/api/payments/[id]/route.js.map +7 -0
  42. package/dist/modules/billing/api/payments/allocate/route.js +35 -0
  43. package/dist/modules/billing/api/payments/allocate/route.js.map +7 -0
  44. package/dist/modules/billing/api/payments/assign/route.js +36 -0
  45. package/dist/modules/billing/api/payments/assign/route.js.map +7 -0
  46. package/dist/modules/billing/api/payments/convert-to-topup/route.js +35 -0
  47. package/dist/modules/billing/api/payments/convert-to-topup/route.js.map +7 -0
  48. package/dist/modules/billing/api/payments/ignore/route.js +35 -0
  49. package/dist/modules/billing/api/payments/ignore/route.js.map +7 -0
  50. package/dist/modules/billing/api/payments/import/route.js +63 -0
  51. package/dist/modules/billing/api/payments/import/route.js.map +7 -0
  52. package/dist/modules/billing/api/payments/restore/route.js +35 -0
  53. package/dist/modules/billing/api/payments/restore/route.js.map +7 -0
  54. package/dist/modules/billing/api/payments/route.js +114 -0
  55. package/dist/modules/billing/api/payments/route.js.map +7 -0
  56. package/dist/modules/billing/api/payments/unallocate/route.js +35 -0
  57. package/dist/modules/billing/api/payments/unallocate/route.js.map +7 -0
  58. package/dist/modules/billing/api/payments/unassign/route.js +35 -0
  59. package/dist/modules/billing/api/payments/unassign/route.js.map +7 -0
  60. package/dist/modules/billing/api/run-outcomes/route.js +43 -6
  61. package/dist/modules/billing/api/run-outcomes/route.js.map +2 -2
  62. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js +61 -0
  63. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js.map +7 -0
  64. package/dist/modules/billing/api/runs/[id]/route.js +53 -0
  65. package/dist/modules/billing/api/runs/[id]/route.js.map +7 -0
  66. package/dist/modules/billing/api/runs/retry-failed/route.js +1 -1
  67. package/dist/modules/billing/api/runs/retry-failed/route.js.map +2 -2
  68. package/dist/modules/billing/api/runs/route.js +9 -3
  69. package/dist/modules/billing/api/runs/route.js.map +2 -2
  70. package/dist/modules/billing/api/settings/number-preview/route.js +42 -0
  71. package/dist/modules/billing/api/settings/number-preview/route.js.map +7 -0
  72. package/dist/modules/billing/api/settings/route.js +92 -0
  73. package/dist/modules/billing/api/settings/route.js.map +7 -0
  74. package/dist/modules/billing/api/statements/route.js +3 -0
  75. package/dist/modules/billing/api/statements/route.js.map +2 -2
  76. package/dist/modules/billing/api/test-invoices/wipe/route.js +2 -2
  77. package/dist/modules/billing/api/test-invoices/wipe/route.js.map +2 -2
  78. package/dist/modules/billing/backend/billing/accounts/[id]/page.js +121 -232
  79. package/dist/modules/billing/backend/billing/accounts/[id]/page.js.map +2 -2
  80. package/dist/modules/billing/backend/billing/accounts/create/page.js +6 -0
  81. package/dist/modules/billing/backend/billing/accounts/create/page.js.map +2 -2
  82. package/dist/modules/billing/backend/billing/accounts/page.js +63 -4
  83. package/dist/modules/billing/backend/billing/accounts/page.js.map +2 -2
  84. package/dist/modules/billing/backend/billing/invoices/[id]/page.js +297 -65
  85. package/dist/modules/billing/backend/billing/invoices/[id]/page.js.map +3 -3
  86. package/dist/modules/billing/backend/billing/invoices/page.js +6 -172
  87. package/dist/modules/billing/backend/billing/invoices/page.js.map +2 -2
  88. package/dist/modules/billing/backend/billing/items/[id]/page.js +51 -7
  89. package/dist/modules/billing/backend/billing/items/[id]/page.js.map +2 -2
  90. package/dist/modules/billing/backend/billing/items/create/page.js +9 -6
  91. package/dist/modules/billing/backend/billing/items/create/page.js.map +2 -2
  92. package/dist/modules/billing/backend/billing/items/page.js +8 -2
  93. package/dist/modules/billing/backend/billing/items/page.js.map +2 -2
  94. package/dist/modules/billing/backend/billing/payments/[id]/page.js +297 -0
  95. package/dist/modules/billing/backend/billing/payments/[id]/page.js.map +7 -0
  96. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js +21 -0
  97. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js.map +7 -0
  98. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js +74 -0
  99. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js.map +7 -0
  100. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js +21 -0
  101. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js.map +7 -0
  102. package/dist/modules/billing/backend/billing/payments/page.js +58 -0
  103. package/dist/modules/billing/backend/billing/payments/page.js.map +7 -0
  104. package/dist/modules/billing/backend/billing/payments/page.meta.js +18 -0
  105. package/dist/modules/billing/backend/billing/payments/page.meta.js.map +7 -0
  106. package/dist/modules/billing/backend/billing/runs/[id]/page.js +49 -14
  107. package/dist/modules/billing/backend/billing/runs/[id]/page.js.map +2 -2
  108. package/dist/modules/billing/backend/billing/runs/page.js +58 -7
  109. package/dist/modules/billing/backend/billing/runs/page.js.map +2 -2
  110. package/dist/modules/billing/backend/billing/statements/[id]/page.js +61 -6
  111. package/dist/modules/billing/backend/billing/statements/[id]/page.js.map +2 -2
  112. package/dist/modules/billing/backend/billing/statements/page.js +1 -1
  113. package/dist/modules/billing/backend/billing/statements/page.js.map +2 -2
  114. package/dist/modules/billing/backend/billing/topups/page.js +1 -1
  115. package/dist/modules/billing/backend/billing/topups/page.js.map +2 -2
  116. package/dist/modules/billing/backend/billing/transactions/page.js +1 -1
  117. package/dist/modules/billing/backend/billing/transactions/page.js.map +2 -2
  118. package/dist/modules/billing/backend/billing/usage/create/page.js +3 -2
  119. package/dist/modules/billing/backend/billing/usage/create/page.js.map +2 -2
  120. package/dist/modules/billing/backend/config/billing/page.js +472 -0
  121. package/dist/modules/billing/backend/config/billing/page.js.map +7 -0
  122. package/dist/modules/billing/backend/config/billing/page.meta.js +19 -0
  123. package/dist/modules/billing/backend/config/billing/page.meta.js.map +7 -0
  124. package/dist/modules/billing/cli.js +22 -1
  125. package/dist/modules/billing/cli.js.map +2 -2
  126. package/dist/modules/billing/commands/accounts.js +6 -0
  127. package/dist/modules/billing/commands/accounts.js.map +2 -2
  128. package/dist/modules/billing/commands/index.js +3 -0
  129. package/dist/modules/billing/commands/index.js.map +2 -2
  130. package/dist/modules/billing/commands/invoices.js +269 -167
  131. package/dist/modules/billing/commands/invoices.js.map +2 -2
  132. package/dist/modules/billing/commands/items.js +108 -0
  133. package/dist/modules/billing/commands/items.js.map +2 -2
  134. package/dist/modules/billing/commands/memos.js +179 -0
  135. package/dist/modules/billing/commands/memos.js.map +7 -0
  136. package/dist/modules/billing/commands/payments.js +379 -0
  137. package/dist/modules/billing/commands/payments.js.map +7 -0
  138. package/dist/modules/billing/commands/runs.js +151 -4
  139. package/dist/modules/billing/commands/runs.js.map +2 -2
  140. package/dist/modules/billing/commands/settings.js +59 -0
  141. package/dist/modules/billing/commands/settings.js.map +7 -0
  142. package/dist/modules/billing/commands/topups.js +9 -2
  143. package/dist/modules/billing/commands/topups.js.map +2 -2
  144. package/dist/modules/billing/commands/transactions.js +2 -2
  145. package/dist/modules/billing/commands/transactions.js.map +2 -2
  146. package/dist/modules/billing/components/AccountForm.js +149 -42
  147. package/dist/modules/billing/components/AccountForm.js.map +2 -2
  148. package/dist/modules/billing/components/AccountInvoicesSection.js +64 -0
  149. package/dist/modules/billing/components/AccountInvoicesSection.js.map +7 -0
  150. package/dist/modules/billing/components/AccountPaymentsSection.js +43 -0
  151. package/dist/modules/billing/components/AccountPaymentsSection.js.map +7 -0
  152. package/dist/modules/billing/components/AccountPicker.js +56 -0
  153. package/dist/modules/billing/components/AccountPicker.js.map +7 -0
  154. package/dist/modules/billing/components/AllocatePaymentDialog.js +134 -0
  155. package/dist/modules/billing/components/AllocatePaymentDialog.js.map +7 -0
  156. package/dist/modules/billing/components/BillingDataTable.js +21 -0
  157. package/dist/modules/billing/components/BillingDataTable.js.map +7 -0
  158. package/dist/modules/billing/components/BillingSettingsLink.js +19 -0
  159. package/dist/modules/billing/components/BillingSettingsLink.js.map +7 -0
  160. package/dist/modules/billing/components/ChangeItemPriceDialog.js +158 -0
  161. package/dist/modules/billing/components/ChangeItemPriceDialog.js.map +7 -0
  162. package/dist/modules/billing/components/CreateMemoDialog.js +200 -0
  163. package/dist/modules/billing/components/CreateMemoDialog.js.map +7 -0
  164. package/dist/modules/billing/components/CustomerLabel.js +33 -0
  165. package/dist/modules/billing/components/CustomerLabel.js.map +7 -0
  166. package/dist/modules/billing/components/InvoicesTable.js +270 -0
  167. package/dist/modules/billing/components/InvoicesTable.js.map +7 -0
  168. package/dist/modules/billing/components/ItemForm.js +176 -44
  169. package/dist/modules/billing/components/ItemForm.js.map +2 -2
  170. package/dist/modules/billing/components/ItemPriceField.js +46 -0
  171. package/dist/modules/billing/components/ItemPriceField.js.map +7 -0
  172. package/dist/modules/billing/components/LineFormDialog.js +25 -2
  173. package/dist/modules/billing/components/LineFormDialog.js.map +2 -2
  174. package/dist/modules/billing/components/ManualPaymentDialog.js +122 -0
  175. package/dist/modules/billing/components/ManualPaymentDialog.js.map +7 -0
  176. package/dist/modules/billing/components/MoneyInput.js +14 -0
  177. package/dist/modules/billing/components/MoneyInput.js.map +7 -0
  178. package/dist/modules/billing/components/PaymentUploadDialog.js +115 -0
  179. package/dist/modules/billing/components/PaymentUploadDialog.js.map +7 -0
  180. package/dist/modules/billing/components/PaymentsTable.js +171 -0
  181. package/dist/modules/billing/components/PaymentsTable.js.map +7 -0
  182. package/dist/modules/billing/components/PostRunDraftsButton.js +105 -0
  183. package/dist/modules/billing/components/PostRunDraftsButton.js.map +7 -0
  184. package/dist/modules/billing/components/PrepaidPanel.js +14 -4
  185. package/dist/modules/billing/components/PrepaidPanel.js.map +2 -2
  186. package/dist/modules/billing/components/RunCyclesSection.js +209 -0
  187. package/dist/modules/billing/components/RunCyclesSection.js.map +7 -0
  188. package/dist/modules/billing/components/TestRunActions.js +127 -0
  189. package/dist/modules/billing/components/TestRunActions.js.map +7 -0
  190. package/dist/modules/billing/components/account/AccountItemsTab.js +157 -0
  191. package/dist/modules/billing/components/account/AccountItemsTab.js.map +7 -0
  192. package/dist/modules/billing/components/account/AccountRunBillingDialog.js +122 -0
  193. package/dist/modules/billing/components/account/AccountRunBillingDialog.js.map +7 -0
  194. package/dist/modules/billing/components/account/AccountRunsTab.js +152 -0
  195. package/dist/modules/billing/components/account/AccountRunsTab.js.map +7 -0
  196. package/dist/modules/billing/components/account/AccountStatementsTab.js +98 -0
  197. package/dist/modules/billing/components/account/AccountStatementsTab.js.map +7 -0
  198. package/dist/modules/billing/components/account/AccountSummaryCards.js +125 -0
  199. package/dist/modules/billing/components/account/AccountSummaryCards.js.map +7 -0
  200. package/dist/modules/billing/components/account/AccountUsageTab.js +91 -0
  201. package/dist/modules/billing/components/account/AccountUsageTab.js.map +7 -0
  202. package/dist/modules/billing/components/account/AccountView.js +73 -0
  203. package/dist/modules/billing/components/account/AccountView.js.map +7 -0
  204. package/dist/modules/billing/components/account/accountRow.js +39 -0
  205. package/dist/modules/billing/components/account/accountRow.js.map +7 -0
  206. package/dist/modules/billing/components/customerNames.js +42 -0
  207. package/dist/modules/billing/components/customerNames.js.map +7 -0
  208. package/dist/modules/billing/data/entities.js +560 -4
  209. package/dist/modules/billing/data/entities.js.map +2 -2
  210. package/dist/modules/billing/data/entityIds.js +10 -1
  211. package/dist/modules/billing/data/entityIds.js.map +2 -2
  212. package/dist/modules/billing/data/validators.js +269 -15
  213. package/dist/modules/billing/data/validators.js.map +2 -2
  214. package/dist/modules/billing/events.js +50 -0
  215. package/dist/modules/billing/events.js.map +2 -2
  216. package/dist/modules/billing/i18n/de.json +880 -0
  217. package/dist/modules/billing/i18n/en.json +457 -21
  218. package/dist/modules/billing/i18n/es.json +880 -0
  219. package/dist/modules/billing/i18n/pl.json +458 -22
  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 +237 -102
  237. package/dist/modules/billing/lib/billRunEngine.js.map +2 -2
  238. package/dist/modules/billing/lib/billingSettings.js +116 -0
  239. package/dist/modules/billing/lib/billingSettings.js.map +7 -0
  240. package/dist/modules/billing/lib/commandRoute.js +81 -0
  241. package/dist/modules/billing/lib/commandRoute.js.map +7 -0
  242. package/dist/modules/billing/lib/customerLookup.js +97 -0
  243. package/dist/modules/billing/lib/customerLookup.js.map +7 -0
  244. package/dist/modules/billing/lib/dateOnly.js +13 -0
  245. package/dist/modules/billing/lib/dateOnly.js.map +7 -0
  246. package/dist/modules/billing/lib/documentParties.js +16 -0
  247. package/dist/modules/billing/lib/documentParties.js.map +7 -0
  248. package/dist/modules/billing/lib/documentTypes.js +27 -0
  249. package/dist/modules/billing/lib/documentTypes.js.map +7 -0
  250. package/dist/modules/billing/lib/dueDate.js +18 -0
  251. package/dist/modules/billing/lib/dueDate.js.map +7 -0
  252. package/dist/modules/billing/lib/iban.js +29 -0
  253. package/dist/modules/billing/lib/iban.js.map +7 -0
  254. package/dist/modules/billing/lib/invoiceDelivery.js +133 -0
  255. package/dist/modules/billing/lib/invoiceDelivery.js.map +7 -0
  256. package/dist/modules/billing/lib/invoiceLanguages.js +28 -0
  257. package/dist/modules/billing/lib/invoiceLanguages.js.map +7 -0
  258. package/dist/modules/billing/lib/invoiceWriter.js +107 -99
  259. package/dist/modules/billing/lib/invoiceWriter.js.map +2 -2
  260. package/dist/modules/billing/lib/itemBillingState.js +27 -0
  261. package/dist/modules/billing/lib/itemBillingState.js.map +7 -0
  262. package/dist/modules/billing/lib/itemPriceChange.js +18 -0
  263. package/dist/modules/billing/lib/itemPriceChange.js.map +7 -0
  264. package/dist/modules/billing/lib/itemSelector.js.map +2 -2
  265. package/dist/modules/billing/lib/lineAmounts.js +32 -0
  266. package/dist/modules/billing/lib/lineAmounts.js.map +7 -0
  267. package/dist/modules/billing/lib/memoGuards.js +25 -0
  268. package/dist/modules/billing/lib/memoGuards.js.map +7 -0
  269. package/dist/modules/billing/lib/navigation.js +48 -0
  270. package/dist/modules/billing/lib/navigation.js.map +7 -0
  271. package/dist/modules/billing/lib/numbering.js +120 -0
  272. package/dist/modules/billing/lib/numbering.js.map +7 -0
  273. package/dist/modules/billing/lib/overdue.js +36 -0
  274. package/dist/modules/billing/lib/overdue.js.map +7 -0
  275. package/dist/modules/billing/lib/paymentCsv.js +125 -0
  276. package/dist/modules/billing/lib/paymentCsv.js.map +7 -0
  277. package/dist/modules/billing/lib/paymentGateway.js +15 -0
  278. package/dist/modules/billing/lib/paymentGateway.js.map +7 -0
  279. package/dist/modules/billing/lib/paymentImport.js +164 -0
  280. package/dist/modules/billing/lib/paymentImport.js.map +7 -0
  281. package/dist/modules/billing/lib/paymentMatcher.js +36 -0
  282. package/dist/modules/billing/lib/paymentMatcher.js.map +7 -0
  283. package/dist/modules/billing/lib/pdf/attachmentStore.js +46 -0
  284. package/dist/modules/billing/lib/pdf/attachmentStore.js.map +7 -0
  285. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js +7 -0
  286. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js.map +7 -0
  287. package/dist/modules/billing/lib/pdf/invoiceModel.js +194 -0
  288. package/dist/modules/billing/lib/pdf/invoiceModel.js.map +7 -0
  289. package/dist/modules/billing/lib/pdf/invoicePdf.js +165 -0
  290. package/dist/modules/billing/lib/pdf/invoicePdf.js.map +7 -0
  291. package/dist/modules/billing/lib/pdf/invoiceTemplate.js +276 -0
  292. package/dist/modules/billing/lib/pdf/invoiceTemplate.js.map +7 -0
  293. package/dist/modules/billing/lib/prepaidConfig.js +17 -25
  294. package/dist/modules/billing/lib/prepaidConfig.js.map +2 -2
  295. package/dist/modules/billing/lib/prepaidConsume.js +26 -7
  296. package/dist/modules/billing/lib/prepaidConsume.js.map +2 -2
  297. package/dist/modules/billing/lib/prepaidPeriodClose.js +277 -158
  298. package/dist/modules/billing/lib/prepaidPeriodClose.js.map +2 -2
  299. package/dist/modules/billing/lib/prepaidTaxPoint.js +37 -0
  300. package/dist/modules/billing/lib/prepaidTaxPoint.js.map +7 -0
  301. package/dist/modules/billing/lib/seeds/demo.js +51 -3
  302. package/dist/modules/billing/lib/seeds/demo.js.map +2 -2
  303. package/dist/modules/billing/lib/seeds/paymentsSample.js +93 -0
  304. package/dist/modules/billing/lib/seeds/paymentsSample.js.map +7 -0
  305. package/dist/modules/billing/lib/seeds/sellerSettings.js +41 -0
  306. package/dist/modules/billing/lib/seeds/sellerSettings.js.map +7 -0
  307. package/dist/modules/billing/lib/servicePeriods.js +121 -0
  308. package/dist/modules/billing/lib/servicePeriods.js.map +7 -0
  309. package/dist/modules/billing/lib/testRunCleanup.js +24 -0
  310. package/dist/modules/billing/lib/testRunCleanup.js.map +7 -0
  311. package/dist/modules/billing/lib/topupCapture.js +2 -2
  312. package/dist/modules/billing/lib/topupCapture.js.map +2 -2
  313. package/dist/modules/billing/lib/topupReceipt.js +58 -79
  314. package/dist/modules/billing/lib/topupReceipt.js.map +2 -2
  315. package/dist/modules/billing/lib/usageRater.js.map +1 -1
  316. package/dist/modules/billing/lib/usageRunner.js +14 -6
  317. package/dist/modules/billing/lib/usageRunner.js.map +2 -2
  318. package/dist/modules/billing/lib/vat.js +39 -0
  319. package/dist/modules/billing/lib/vat.js.map +7 -0
  320. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js +15 -0
  321. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js.map +7 -0
  322. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js +25 -0
  323. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js.map +7 -0
  324. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js +115 -0
  325. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js.map +7 -0
  326. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js +47 -0
  327. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js.map +7 -0
  328. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js +89 -0
  329. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js.map +7 -0
  330. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js +17 -0
  331. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js.map +7 -0
  332. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js +27 -0
  333. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js.map +7 -0
  334. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js +29 -0
  335. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js.map +7 -0
  336. package/dist/modules/billing/setup.js +7 -184
  337. package/dist/modules/billing/setup.js.map +2 -2
  338. package/dist/modules/billing/subscribers/credit-memo-auto-send.js +16 -0
  339. package/dist/modules/billing/subscribers/credit-memo-auto-send.js.map +7 -0
  340. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js +16 -0
  341. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js.map +7 -0
  342. package/dist/modules/billing/subscribers/debit-memo-auto-send.js +16 -0
  343. package/dist/modules/billing/subscribers/debit-memo-auto-send.js.map +7 -0
  344. package/dist/modules/billing/subscribers/invoice-apply-credit.js +34 -0
  345. package/dist/modules/billing/subscribers/invoice-apply-credit.js.map +7 -0
  346. package/dist/modules/billing/subscribers/invoice-auto-send.js +30 -0
  347. package/dist/modules/billing/subscribers/invoice-auto-send.js.map +7 -0
  348. package/dist/modules/billing/subscribers/payment-captured-to-paid.js +69 -33
  349. package/dist/modules/billing/subscribers/payment-captured-to-paid.js.map +2 -2
  350. package/dist/modules/billing/subscribers/prepaid-topup-captured.js +4 -6
  351. package/dist/modules/billing/subscribers/prepaid-topup-captured.js.map +2 -2
  352. package/generated/entities/billing_account/index.ts +3 -0
  353. package/generated/entities/billing_allocation/index.ts +18 -0
  354. package/generated/entities/billing_document_sequence/index.ts +11 -0
  355. package/generated/entities/billing_invoice/index.ts +38 -0
  356. package/generated/entities/billing_invoice_line/index.ts +24 -0
  357. package/generated/entities/billing_item/index.ts +4 -0
  358. package/generated/entities/billing_payment/index.ts +25 -0
  359. package/generated/entities/billing_payment_import/index.ts +14 -0
  360. package/generated/entities/billing_run/index.ts +0 -1
  361. package/generated/entities/billing_run_outcome/index.ts +1 -0
  362. package/generated/entities/billing_settings/index.ts +26 -0
  363. package/generated/entities/billing_statement/index.ts +1 -0
  364. package/generated/entities.ids.generated.ts +7 -0
  365. package/package.json +5 -1
  366. package/src/modules/billing/__integration__/TC-BILL-004.spec.ts +171 -0
  367. package/src/modules/billing/__integration__/TC-BILL-005.spec.ts +134 -0
  368. package/src/modules/billing/__integration__/TC-BILL-006.spec.ts +101 -0
  369. package/src/modules/billing/__integration__/TC-BILL-007.spec.ts +140 -0
  370. package/src/modules/billing/__integration__/TC-BILL-008.spec.ts +108 -0
  371. package/src/modules/billing/__integration__/TC-BILL-009.spec.ts +113 -0
  372. package/src/modules/billing/__integration__/TC-BILL-010.spec.ts +118 -0
  373. package/src/modules/billing/__integration__/TC-BILL-011.spec.ts +142 -0
  374. package/src/modules/billing/__integration__/TC-BILL-012.spec.ts +115 -0
  375. package/src/modules/billing/__integration__/TC-BILL-013.spec.ts +118 -0
  376. package/src/modules/billing/__integration__/sellerSettings.ts +24 -0
  377. package/src/modules/billing/__tests__/commands/invoices.test.ts +436 -354
  378. package/src/modules/billing/__tests__/commands/itemsBulk.test.ts +33 -0
  379. package/src/modules/billing/__tests__/commands/memos.test.ts +205 -0
  380. package/src/modules/billing/__tests__/commands/payments.test.ts +241 -0
  381. package/src/modules/billing/__tests__/commands/runsDelete.test.ts +146 -0
  382. package/src/modules/billing/__tests__/commands/runsPostDrafts.test.ts +106 -0
  383. package/src/modules/billing/__tests__/commands/topups.test.ts +11 -0
  384. package/src/modules/billing/__tests__/entityRegistry.test.ts +8 -1
  385. package/src/modules/billing/__tests__/helpers/prepaidMockEm.ts +28 -11
  386. package/src/modules/billing/__tests__/i18n/dictionaries.test.ts +64 -0
  387. package/src/modules/billing/__tests__/lib/accountFinancials.test.ts +53 -0
  388. package/src/modules/billing/__tests__/lib/accountSummary.test.ts +97 -0
  389. package/src/modules/billing/__tests__/lib/allocation.test.ts +319 -0
  390. package/src/modules/billing/__tests__/lib/billRunEngine.test.ts +228 -17
  391. package/src/modules/billing/__tests__/lib/billingSettings.test.ts +109 -0
  392. package/src/modules/billing/__tests__/lib/customerLookup.test.ts +156 -0
  393. package/src/modules/billing/__tests__/lib/dueDate.test.ts +35 -0
  394. package/src/modules/billing/__tests__/lib/iban.test.ts +38 -0
  395. package/src/modules/billing/__tests__/lib/invoiceDelivery.test.ts +206 -0
  396. package/src/modules/billing/__tests__/lib/invoiceLanguages.test.ts +49 -0
  397. package/src/modules/billing/__tests__/lib/invoiceWriter.test.ts +212 -10
  398. package/src/modules/billing/__tests__/lib/itemBillingState.test.ts +42 -0
  399. package/src/modules/billing/__tests__/lib/itemPriceChange.test.ts +165 -0
  400. package/src/modules/billing/__tests__/lib/lineAmounts.test.ts +86 -0
  401. package/src/modules/billing/__tests__/lib/navigation.test.ts +71 -0
  402. package/src/modules/billing/__tests__/lib/numbering.test.ts +91 -0
  403. package/src/modules/billing/__tests__/lib/overdue.test.ts +36 -0
  404. package/src/modules/billing/__tests__/lib/paymentCsv.test.ts +148 -0
  405. package/src/modules/billing/__tests__/lib/paymentImport.test.ts +113 -0
  406. package/src/modules/billing/__tests__/lib/paymentsSample.test.ts +73 -0
  407. package/src/modules/billing/__tests__/lib/pdf/invoicePdf.test.ts +269 -0
  408. package/src/modules/billing/__tests__/lib/pdf/invoicePdfService.test.ts +147 -0
  409. package/src/modules/billing/__tests__/lib/prepaidPeriodClose.test.ts +374 -98
  410. package/src/modules/billing/__tests__/lib/prepaidTaxPoint.test.ts +118 -0
  411. package/src/modules/billing/__tests__/lib/seedsDemo.test.ts +53 -2
  412. package/src/modules/billing/__tests__/lib/sellerSettings.test.ts +28 -0
  413. package/src/modules/billing/__tests__/lib/servicePeriods.test.ts +190 -0
  414. package/src/modules/billing/__tests__/lib/topupCapture.test.ts +6 -28
  415. package/src/modules/billing/__tests__/lib/topupReceipt.test.ts +21 -52
  416. package/src/modules/billing/__tests__/lib/vat.test.ts +51 -0
  417. package/src/modules/billing/__tests__/package-isolation.test.ts +22 -8
  418. package/src/modules/billing/__tests__/setup.test.ts +13 -4
  419. package/src/modules/billing/__tests__/validators.test.ts +197 -3
  420. package/src/modules/billing/acl.ts +12 -0
  421. package/src/modules/billing/api/accounts/[id]/summary/route.ts +62 -0
  422. package/src/modules/billing/api/accounts/route.ts +59 -4
  423. package/src/modules/billing/api/export/account/[id]/route.ts +13 -11
  424. package/src/modules/billing/api/invoices/[id]/memos/route.ts +63 -0
  425. package/src/modules/billing/api/invoices/[id]/pdf/route.ts +80 -0
  426. package/src/modules/billing/api/invoices/[id]/route.ts +57 -70
  427. package/src/modules/billing/api/invoices/[id]/send/route.ts +127 -0
  428. package/src/modules/billing/api/invoices/add-line/route.ts +2 -2
  429. package/src/modules/billing/api/invoices/delete-draft/route.ts +33 -0
  430. package/src/modules/billing/api/invoices/edit-line/route.ts +2 -2
  431. package/src/modules/billing/api/invoices/post/route.ts +7 -6
  432. package/src/modules/billing/api/invoices/remove-line/route.ts +2 -2
  433. package/src/modules/billing/api/invoices/route.ts +81 -86
  434. package/src/modules/billing/api/items/bulk/route.ts +2 -1
  435. package/src/modules/billing/api/items/change-price/route.ts +54 -0
  436. package/src/modules/billing/api/items/route.ts +23 -7
  437. package/src/modules/billing/api/payment-imports/[id]/route.ts +49 -0
  438. package/src/modules/billing/api/payment-imports/route.ts +57 -0
  439. package/src/modules/billing/api/payments/[id]/route.ts +63 -0
  440. package/src/modules/billing/api/payments/allocate/route.ts +35 -0
  441. package/src/modules/billing/api/payments/assign/route.ts +36 -0
  442. package/src/modules/billing/api/payments/convert-to-topup/route.ts +35 -0
  443. package/src/modules/billing/api/payments/ignore/route.ts +35 -0
  444. package/src/modules/billing/api/payments/import/route.ts +72 -0
  445. package/src/modules/billing/api/payments/restore/route.ts +35 -0
  446. package/src/modules/billing/api/payments/route.ts +147 -0
  447. package/src/modules/billing/api/payments/unallocate/route.ts +35 -0
  448. package/src/modules/billing/api/payments/unassign/route.ts +35 -0
  449. package/src/modules/billing/api/run-outcomes/route.ts +49 -6
  450. package/src/modules/billing/api/runs/[id]/post-drafts/route.ts +71 -0
  451. package/src/modules/billing/api/runs/[id]/route.ts +59 -0
  452. package/src/modules/billing/api/runs/retry-failed/route.ts +2 -1
  453. package/src/modules/billing/api/runs/route.ts +15 -7
  454. package/src/modules/billing/api/settings/number-preview/route.ts +46 -0
  455. package/src/modules/billing/api/settings/route.ts +116 -0
  456. package/src/modules/billing/api/statements/route.ts +5 -0
  457. package/src/modules/billing/api/test-invoices/wipe/route.ts +2 -2
  458. package/src/modules/billing/backend/billing/accounts/[id]/page.tsx +151 -372
  459. package/src/modules/billing/backend/billing/accounts/create/page.tsx +6 -0
  460. package/src/modules/billing/backend/billing/accounts/page.tsx +70 -4
  461. package/src/modules/billing/backend/billing/invoices/[id]/page.tsx +444 -95
  462. package/src/modules/billing/backend/billing/invoices/page.tsx +8 -227
  463. package/src/modules/billing/backend/billing/items/[id]/page.tsx +75 -6
  464. package/src/modules/billing/backend/billing/items/create/page.tsx +13 -8
  465. package/src/modules/billing/backend/billing/items/page.tsx +18 -2
  466. package/src/modules/billing/backend/billing/payments/[id]/page.meta.ts +19 -0
  467. package/src/modules/billing/backend/billing/payments/[id]/page.tsx +415 -0
  468. package/src/modules/billing/backend/billing/payments/imports/[id]/page.meta.ts +19 -0
  469. package/src/modules/billing/backend/billing/payments/imports/[id]/page.tsx +106 -0
  470. package/src/modules/billing/backend/billing/payments/page.meta.ts +16 -0
  471. package/src/modules/billing/backend/billing/payments/page.tsx +56 -0
  472. package/src/modules/billing/backend/billing/runs/[id]/page.tsx +49 -18
  473. package/src/modules/billing/backend/billing/runs/page.tsx +59 -8
  474. package/src/modules/billing/backend/billing/statements/[id]/page.tsx +86 -5
  475. package/src/modules/billing/backend/billing/statements/page.tsx +1 -1
  476. package/src/modules/billing/backend/billing/topups/page.tsx +1 -1
  477. package/src/modules/billing/backend/billing/transactions/page.tsx +1 -1
  478. package/src/modules/billing/backend/billing/usage/create/page.tsx +3 -2
  479. package/src/modules/billing/backend/config/billing/page.meta.ts +21 -0
  480. package/src/modules/billing/backend/config/billing/page.tsx +549 -0
  481. package/src/modules/billing/cli.ts +31 -1
  482. package/src/modules/billing/commands/accounts.ts +6 -0
  483. package/src/modules/billing/commands/index.ts +3 -0
  484. package/src/modules/billing/commands/invoices.ts +364 -231
  485. package/src/modules/billing/commands/items.ts +143 -0
  486. package/src/modules/billing/commands/memos.ts +218 -0
  487. package/src/modules/billing/commands/payments.ts +428 -0
  488. package/src/modules/billing/commands/runs.ts +205 -3
  489. package/src/modules/billing/commands/settings.ts +77 -0
  490. package/src/modules/billing/commands/topups.ts +12 -3
  491. package/src/modules/billing/commands/transactions.ts +2 -2
  492. package/src/modules/billing/components/AccountForm.tsx +199 -53
  493. package/src/modules/billing/components/AccountInvoicesSection.tsx +75 -0
  494. package/src/modules/billing/components/AccountPaymentsSection.tsx +42 -0
  495. package/src/modules/billing/components/AccountPicker.tsx +70 -0
  496. package/src/modules/billing/components/AllocatePaymentDialog.tsx +167 -0
  497. package/src/modules/billing/components/BillingDataTable.tsx +34 -0
  498. package/src/modules/billing/components/BillingSettingsLink.tsx +25 -0
  499. package/src/modules/billing/components/ChangeItemPriceDialog.tsx +180 -0
  500. package/src/modules/billing/components/CreateMemoDialog.tsx +232 -0
  501. package/src/modules/billing/components/CustomerLabel.tsx +53 -0
  502. package/src/modules/billing/components/InvoicesTable.tsx +344 -0
  503. package/src/modules/billing/components/ItemForm.tsx +233 -44
  504. package/src/modules/billing/components/ItemPriceField.tsx +81 -0
  505. package/src/modules/billing/components/LineFormDialog.tsx +25 -1
  506. package/src/modules/billing/components/ManualPaymentDialog.tsx +140 -0
  507. package/src/modules/billing/components/MoneyInput.tsx +26 -0
  508. package/src/modules/billing/components/PaymentUploadDialog.tsx +148 -0
  509. package/src/modules/billing/components/PaymentsTable.tsx +213 -0
  510. package/src/modules/billing/components/PostRunDraftsButton.tsx +129 -0
  511. package/src/modules/billing/components/PrepaidPanel.tsx +19 -6
  512. package/src/modules/billing/components/RunCyclesSection.tsx +298 -0
  513. package/src/modules/billing/components/TestRunActions.tsx +152 -0
  514. package/src/modules/billing/components/account/AccountItemsTab.tsx +192 -0
  515. package/src/modules/billing/components/account/AccountRunBillingDialog.tsx +147 -0
  516. package/src/modules/billing/components/account/AccountRunsTab.tsx +201 -0
  517. package/src/modules/billing/components/account/AccountStatementsTab.tsx +120 -0
  518. package/src/modules/billing/components/account/AccountSummaryCards.tsx +153 -0
  519. package/src/modules/billing/components/account/AccountUsageTab.tsx +122 -0
  520. package/src/modules/billing/components/account/AccountView.tsx +101 -0
  521. package/src/modules/billing/components/account/accountRow.ts +70 -0
  522. package/src/modules/billing/components/customerNames.ts +62 -0
  523. package/src/modules/billing/data/entities.ts +656 -6
  524. package/src/modules/billing/data/entityIds.ts +9 -0
  525. package/src/modules/billing/data/validators.ts +388 -8
  526. package/src/modules/billing/events.ts +56 -3
  527. package/src/modules/billing/i18n/de.json +880 -0
  528. package/src/modules/billing/i18n/en.json +457 -21
  529. package/src/modules/billing/i18n/es.json +880 -0
  530. package/src/modules/billing/i18n/pl.json +458 -22
  531. package/src/modules/billing/index.ts +6 -2
  532. package/src/modules/billing/lib/accountFinancials.ts +84 -0
  533. package/src/modules/billing/lib/accountLock.ts +32 -0
  534. package/src/modules/billing/lib/accountStatus.ts +11 -9
  535. package/src/modules/billing/lib/accountSummary.ts +172 -0
  536. package/src/modules/billing/lib/allocation.ts +515 -0
  537. package/src/modules/billing/lib/allocationEvents.ts +26 -0
  538. package/src/modules/billing/lib/billPeriod.ts +19 -0
  539. package/src/modules/billing/lib/billRunEngine.ts +350 -150
  540. package/src/modules/billing/lib/billingSettings.ts +145 -0
  541. package/src/modules/billing/lib/commandRoute.ts +112 -0
  542. package/src/modules/billing/lib/customerLookup.ts +157 -0
  543. package/src/modules/billing/lib/dateOnly.ts +22 -0
  544. package/src/modules/billing/lib/documentParties.ts +23 -0
  545. package/src/modules/billing/lib/documentTypes.ts +37 -0
  546. package/src/modules/billing/lib/dueDate.ts +26 -0
  547. package/src/modules/billing/lib/iban.ts +36 -0
  548. package/src/modules/billing/lib/invoiceDelivery.ts +196 -0
  549. package/src/modules/billing/lib/invoiceLanguages.ts +57 -0
  550. package/src/modules/billing/lib/invoiceWriter.ts +162 -148
  551. package/src/modules/billing/lib/itemBillingState.ts +67 -0
  552. package/src/modules/billing/lib/itemPriceChange.ts +56 -0
  553. package/src/modules/billing/lib/itemSelector.ts +4 -1
  554. package/src/modules/billing/lib/lineAmounts.ts +61 -0
  555. package/src/modules/billing/lib/memoGuards.ts +41 -0
  556. package/src/modules/billing/lib/navigation.ts +64 -0
  557. package/src/modules/billing/lib/numbering.ts +174 -0
  558. package/src/modules/billing/lib/overdue.ts +60 -0
  559. package/src/modules/billing/lib/paymentCsv.ts +171 -0
  560. package/src/modules/billing/lib/paymentGateway.ts +52 -0
  561. package/src/modules/billing/lib/paymentImport.ts +228 -0
  562. package/src/modules/billing/lib/paymentMatcher.ts +88 -0
  563. package/src/modules/billing/lib/pdf/attachmentStore.ts +60 -0
  564. package/src/modules/billing/lib/pdf/fonts/NotoSans-Bold.ttf +0 -0
  565. package/src/modules/billing/lib/pdf/fonts/NotoSans-Regular.ttf +0 -0
  566. package/src/modules/billing/lib/pdf/fonts/OFL.txt +93 -0
  567. package/src/modules/billing/lib/pdf/fonts/embeddedFonts.ts +9 -0
  568. package/src/modules/billing/lib/pdf/invoiceModel.ts +329 -0
  569. package/src/modules/billing/lib/pdf/invoicePdf.ts +220 -0
  570. package/src/modules/billing/lib/pdf/invoiceTemplate.ts +338 -0
  571. package/src/modules/billing/lib/prepaidConfig.ts +27 -36
  572. package/src/modules/billing/lib/prepaidConsume.ts +29 -6
  573. package/src/modules/billing/lib/prepaidPeriodClose.ts +407 -239
  574. package/src/modules/billing/lib/prepaidTaxPoint.ts +76 -0
  575. package/src/modules/billing/lib/seeds/demo.ts +79 -6
  576. package/src/modules/billing/lib/seeds/paymentsSample.ts +136 -0
  577. package/src/modules/billing/lib/seeds/sellerSettings.ts +78 -0
  578. package/src/modules/billing/lib/servicePeriods.ts +226 -0
  579. package/src/modules/billing/lib/testRunCleanup.ts +42 -0
  580. package/src/modules/billing/lib/topupCapture.ts +3 -4
  581. package/src/modules/billing/lib/topupReceipt.ts +70 -103
  582. package/src/modules/billing/lib/usageRater.ts +1 -1
  583. package/src/modules/billing/lib/usageRunner.ts +17 -5
  584. package/src/modules/billing/lib/vat.ts +56 -0
  585. package/src/modules/billing/migrations/Migration20261114000000_billing_customer_kind.ts +25 -0
  586. package/src/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.ts +37 -0
  587. package/src/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.ts +132 -0
  588. package/src/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.ts +58 -0
  589. package/src/modules/billing/migrations/Migration20261117000000_billing_payments.ts +97 -0
  590. package/src/modules/billing/migrations/Migration20261118000000_billing_memos.ts +21 -0
  591. package/src/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.ts +39 -0
  592. package/src/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.ts +35 -0
  593. package/src/modules/billing/setup.ts +11 -237
  594. package/src/modules/billing/subscribers/credit-memo-auto-send.ts +15 -0
  595. package/src/modules/billing/subscribers/debit-memo-apply-credit.ts +15 -0
  596. package/src/modules/billing/subscribers/debit-memo-auto-send.ts +15 -0
  597. package/src/modules/billing/subscribers/invoice-apply-credit.ts +39 -0
  598. package/src/modules/billing/subscribers/invoice-auto-send.ts +46 -0
  599. package/src/modules/billing/subscribers/payment-captured-to-paid.ts +84 -62
  600. package/src/modules/billing/subscribers/prepaid-topup-captured.ts +4 -8
  601. package/dist/modules/billing/lib/invoiceStatus.js +0 -38
  602. package/dist/modules/billing/lib/invoiceStatus.js.map +0 -7
  603. package/src/modules/billing/__tests__/lib/invoiceStatus.test.ts +0 -97
  604. package/src/modules/billing/lib/invoiceStatus.ts +0 -61
@@ -15,10 +15,10 @@ import { metadata } from '../index'
15
15
 
16
16
  const PACKAGE_ROOT = path.resolve(__dirname, '..')
17
17
 
18
- // Must mirror peerDependencies in packages/billing/package.json (plus
19
- // relatives + node builtins). Adding a prefix here without adding it to
20
- // peerDependencies = silent runtime failure for consumers that don't have
21
- // the dep transitively.
18
+ // Must mirror peerDependencies + dependencies in packages/billing/package.json
19
+ // (plus relatives + node builtins). Adding a prefix here without adding it to
20
+ // package.json = silent runtime failure for consumers that don't have the dep
21
+ // transitively. `pdf-lib` / `@pdf-lib/` are regular dependencies (Spec B PDF).
22
22
  const ALLOWED_IMPORT_PREFIXES = [
23
23
  './',
24
24
  '../',
@@ -36,6 +36,8 @@ const ALLOWED_IMPORT_PREFIXES = [
36
36
  '@dainamite/',
37
37
  'node:',
38
38
  '@tanstack/',
39
+ 'pdf-lib',
40
+ '@pdf-lib/',
39
41
  ]
40
42
 
41
43
  const NODE_BUILTINS = new Set([
@@ -128,10 +130,22 @@ describe('@dainamite/billing package isolation', () => {
128
130
  }
129
131
  })
130
132
 
131
- it('declares all required modules in metadata.requires', () => {
132
- expect(metadata.requires).toEqual(
133
- expect.arrayContaining(['auth', 'directory', 'dictionaries', 'configs', 'sales']),
134
- )
133
+ it('requires only platform modules (Spec 0: no core business modules; Spec B: attachments)', () => {
134
+ expect(metadata.requires).toEqual(['auth', 'directory', 'attachments'])
135
+ })
136
+
137
+ it('never imports core sales / configs / dictionaries / payment_gateways (Spec 0)', () => {
138
+ const banned = new Set(['sales', 'configs', 'dictionaries', 'payment_gateways'])
139
+ const violations: string[] = []
140
+ for (const [file, specs] of importsByFile) {
141
+ for (const spec of specs) {
142
+ const subModule = extractCoreModuleSubpath(spec)
143
+ if (subModule && banned.has(subModule)) violations.push(` ${path.relative(PACKAGE_ROOT, file)} → ${spec}`)
144
+ }
145
+ }
146
+ if (violations.length > 0) {
147
+ throw new Error(`Billing must not depend on core business modules:\n${violations.join('\n')}`)
148
+ }
135
149
  })
136
150
 
137
151
  it('does not import from sibling app modules', () => {
@@ -16,9 +16,17 @@ import setup from '../setup'
16
16
  const featureIds = new Set<string>(features.map((f) => f.id))
17
17
 
18
18
  describe('billing setup — contract', () => {
19
- it('exports onTenantCreated and seedDefaults hooks', () => {
20
- expect(typeof setup.onTenantCreated).toBe('function')
19
+ it('exports a seedDefaults hook (billing settings) and no core-config tenant hook', () => {
21
20
  expect(typeof setup.seedDefaults).toBe('function')
21
+ expect(setup.onTenantCreated).toBeUndefined()
22
+ })
23
+
24
+ it('seedDefaults warms up the organization billing settings row', async () => {
25
+ const row = { id: 's-1' }
26
+ const em = { findOne: jest.fn(async () => row), execute: jest.fn() }
27
+ await setup.seedDefaults!({ em, tenantId: 't-1', organizationId: 'o-1' } as never)
28
+ expect(em.findOne).toHaveBeenCalledTimes(1)
29
+ expect(em.execute).not.toHaveBeenCalled()
22
30
  })
23
31
 
24
32
  it('does not declare seedExamples (billing ships no demo data)', () => {
@@ -77,8 +85,8 @@ describe('billing setup — contract', () => {
77
85
  })
78
86
 
79
87
  describe('billing acl — surface', () => {
80
- it('exports exactly 19 features (12 Phase 0 + 7 SPEC-002 prepaid)', () => {
81
- expect(features).toHaveLength(19)
88
+ it('exports exactly 27 features (12 Phase 0 + 7 SPEC-002 prepaid + 2 Spec 0 settings + 1 Spec B send + 3 Spec C payments + 1 Spec D memos + 1 Spec F run delete)', () => {
89
+ expect(features).toHaveLength(27)
82
90
  })
83
91
 
84
92
  it('all feature IDs are prefixed `billing.` (no leaking module boundary)', () => {
@@ -98,6 +106,7 @@ describe('billing acl — surface', () => {
98
106
  'billing.run.trigger',
99
107
  'billing.run.dry_run',
100
108
  'billing.run.view',
109
+ 'billing.run.delete',
101
110
  'billing.invoice.post',
102
111
  'billing.invoice.edit_draft',
103
112
  'billing.invoice.view',
@@ -20,6 +20,7 @@ import {
20
20
  rateJsonUsageVolume,
21
21
  validateRateJson,
22
22
  } from '../data/validators'
23
+ import { DEFAULT_INVOICE_LANGUAGE, SUPPORTED_INVOICE_LANGUAGES } from '../lib/invoiceLanguages'
23
24
 
24
25
  describe('rate_json — one_time', () => {
25
26
  it('accepts a positive amount', () => {
@@ -293,9 +294,6 @@ describe('exported enums', () => {
293
294
  ])
294
295
  })
295
296
 
296
- it('INVOICE_STATUSES matches the dictionary entries seeded by setup', () => {
297
- expect([...INVOICE_STATUSES]).toEqual(['draft', 'posted', 'paid', 'void'])
298
- })
299
297
  })
300
298
 
301
299
  // ─── Phase 1 — CRUD payload schemas ────────────────────────────────
@@ -304,6 +302,11 @@ import {
304
302
  billingAccountCreateSchema,
305
303
  billingAccountListQuerySchema,
306
304
  billingAccountUpdateSchema,
305
+ billingItemBulkCreateSchema,
306
+ billingRunTriggerSchema,
307
+ CHARGE_TIMING_RECURRING_ONLY_MESSAGE,
308
+ billingInvoiceListQuerySchema,
309
+ billingSettingsUpdateSchema,
307
310
  billingItemCreateSchema,
308
311
  billingItemListQuerySchema,
309
312
  billingItemUpdateSchema,
@@ -367,6 +370,49 @@ describe('billingAccountCreateSchema', () => {
367
370
  expect(() => billingAccountCreateSchema.parse(withoutTenant)).toThrow()
368
371
  void tenantId
369
372
  })
373
+ // Spec E — B2C accounts + invoice-language picklist.
374
+ it('defaults customerKind to company', () => {
375
+ expect(billingAccountCreateSchema.parse(validAccountCreate).customerKind).toBe('company')
376
+ })
377
+
378
+ it('accepts customerKind person', () => {
379
+ const parsed = billingAccountCreateSchema.parse({ ...validAccountCreate, customerKind: 'person' })
380
+ expect(parsed.customerKind).toBe('person')
381
+ })
382
+
383
+ it('rejects an unknown customerKind', () => {
384
+ expect(() =>
385
+ billingAccountCreateSchema.parse({ ...validAccountCreate, customerKind: 'household' }),
386
+ ).toThrow()
387
+ })
388
+
389
+ it('accepts every template-supported invoice language, case/space tolerant', () => {
390
+ for (const { code } of SUPPORTED_INVOICE_LANGUAGES) {
391
+ const parsed = billingAccountCreateSchema.parse({
392
+ ...validAccountCreate,
393
+ invoiceLanguage: ` ${code.toUpperCase()} `,
394
+ })
395
+ expect(parsed.invoiceLanguage).toBe(code)
396
+ }
397
+ })
398
+
399
+ it('rejects an invoice language the template does not support', () => {
400
+ expect(() =>
401
+ billingAccountCreateSchema.parse({ ...validAccountCreate, invoiceLanguage: 'fr' }),
402
+ ).toThrow()
403
+ })
404
+
405
+ it.each(['en', 'es', 'de', 'pl'])('accepts the supported invoice language %s (case-insensitive)', (code) => {
406
+ expect(billingAccountCreateSchema.parse({ ...validAccountCreate, invoiceLanguage: ` ${code.toUpperCase()} ` }).invoiceLanguage).toBe(code)
407
+ })
408
+
409
+ it('defaults invoiceLanguage when omitted', () => {
410
+ const { invoiceLanguage, ...withoutLanguage } = validAccountCreate
411
+ void invoiceLanguage
412
+ expect(billingAccountCreateSchema.parse(withoutLanguage).invoiceLanguage).toBe(
413
+ DEFAULT_INVOICE_LANGUAGE,
414
+ )
415
+ })
370
416
  })
371
417
 
372
418
  describe('billingAccountUpdateSchema', () => {
@@ -397,6 +443,16 @@ describe('billingAccountUpdateSchema', () => {
397
443
  it('does not declare customerId (immutable per spec)', () => {
398
444
  expect('customerId' in billingAccountUpdateSchema.shape).toBe(false)
399
445
  })
446
+
447
+ it('does not declare customerKind (immutable per spec)', () => {
448
+ expect('customerKind' in billingAccountUpdateSchema.shape).toBe(false)
449
+ })
450
+
451
+ it('validates invoiceLanguage against supported languages', () => {
452
+ const base = { tenantId: TENANT, organizationId: ORG, id: ACCOUNT }
453
+ expect(billingAccountUpdateSchema.parse({ ...base, invoiceLanguage: 'PL' }).invoiceLanguage).toBe('pl')
454
+ expect(() => billingAccountUpdateSchema.parse({ ...base, invoiceLanguage: 'fr' })).toThrow()
455
+ })
400
456
  })
401
457
 
402
458
  describe('billingAccountListQuerySchema', () => {
@@ -415,6 +471,11 @@ describe('billingAccountListQuerySchema', () => {
415
471
  expect(parsed.page).toBe(1)
416
472
  expect(parsed.pageSize).toBe(50)
417
473
  })
474
+
475
+ it('accepts a customerKind filter and rejects unknown kinds', () => {
476
+ expect(billingAccountListQuerySchema.parse({ customerKind: 'person' }).customerKind).toBe('person')
477
+ expect(() => billingAccountListQuerySchema.parse({ customerKind: 'robot' })).toThrow()
478
+ })
418
479
  })
419
480
 
420
481
  const validItemRecurring = {
@@ -592,3 +653,136 @@ describe('billingUsageListQuerySchema', () => {
592
653
  expect(() => billingUsageListQuerySchema.parse({ pageSize: '101' })).toThrow()
593
654
  })
594
655
  })
656
+
657
+ // ─── Spec A — charge timing, proration, no catch-up flag ─────────
658
+
659
+ describe('Spec A validators', () => {
660
+ const recurring = {
661
+ tenantId: TENANT,
662
+ organizationId: ORG,
663
+ billAccountId: ACCOUNT,
664
+ type: 'recurring' as const,
665
+ billStartDate: '2026-11-14',
666
+ description: 'Internet 300',
667
+ rateJson: { unit_price: 79 },
668
+ }
669
+
670
+ it('accepts chargeTiming / prorate on recurring items and leaves defaults to the command', () => {
671
+ expect(billingItemCreateSchema.parse(recurring)).not.toHaveProperty('chargeTiming')
672
+ const parsed = billingItemCreateSchema.parse({ ...recurring, chargeTiming: 'in_arrears', prorate: false })
673
+ expect(parsed).toMatchObject({ chargeTiming: 'in_arrears', prorate: false })
674
+ })
675
+
676
+ it('rejects an unknown charge timing', () => {
677
+ expect(() => billingItemCreateSchema.parse({ ...recurring, chargeTiming: 'whenever' })).toThrow()
678
+ })
679
+
680
+ it('rejects non-default timing / proration on non-recurring items', () => {
681
+ const oneTime = { ...recurring, type: 'one_time' as const, rateJson: { amount: 10 } }
682
+ expect(billingItemCreateSchema.parse({ ...oneTime, chargeTiming: 'in_advance', prorate: true })).toBeTruthy()
683
+ expect(() => billingItemCreateSchema.parse({ ...oneTime, chargeTiming: 'in_arrears' })).toThrow(
684
+ CHARGE_TIMING_RECURRING_ONLY_MESSAGE,
685
+ )
686
+ expect(() => billingItemCreateSchema.parse({ ...oneTime, prorate: false })).toThrow(
687
+ CHARGE_TIMING_RECURRING_ONLY_MESSAGE,
688
+ )
689
+ })
690
+
691
+ it('applies the same rule to bulk entries and allows both on update', () => {
692
+ const { tenantId, organizationId, ...entry } = recurring
693
+ expect(() =>
694
+ billingItemBulkCreateSchema.parse({
695
+ tenantId,
696
+ organizationId,
697
+ items: [{ ...entry, type: 'usage', uomCode: 'gb', rateJson: { unit_price: 1 }, prorate: false }],
698
+ }),
699
+ ).toThrow()
700
+ expect(
701
+ billingItemUpdateSchema.parse({ tenantId, organizationId, id: ACCOUNT, chargeTiming: 'in_arrears', prorate: false }),
702
+ ).toMatchObject({ chargeTiming: 'in_arrears', prorate: false })
703
+ })
704
+
705
+ it('strips a legacy catchUp flag from the run trigger', () => {
706
+ const parsed = billingRunTriggerSchema.parse({ tenantId: TENANT, organizationId: ORG, catchUp: true })
707
+ expect(parsed).not.toHaveProperty('catchUp')
708
+ expect(parsed.mode).toBe('real')
709
+ })
710
+ })
711
+
712
+ // ─── Spec 0 — ledger validators ──────────────────────────────────
713
+
714
+ describe('Spec 0 validators', () => {
715
+ it('invoice statuses drop void and add partially_paid / credited', () => {
716
+ expect(INVOICE_STATUSES).toEqual(['draft', 'posted', 'partially_paid', 'paid', 'credited'])
717
+ })
718
+
719
+ it('parses testRun literally (false stays false)', () => {
720
+ expect(billingInvoiceListQuerySchema.parse({ testRun: 'false' }).testRun).toBe(false)
721
+ expect(billingInvoiceListQuerySchema.parse({ testRun: 'true' }).testRun).toBe(true)
722
+ expect(billingInvoiceListQuerySchema.parse({}).testRun).toBeUndefined()
723
+ expect(() => billingInvoiceListQuerySchema.parse({ status: 'void' })).toThrow()
724
+ })
725
+
726
+ it('validates number masks on settings update', () => {
727
+ const base = { tenantId: TENANT, organizationId: ORG }
728
+ expect(
729
+ billingSettingsUpdateSchema.parse({ ...base, numberMasks: { invoice: 'FV/{YYYY}/{SEQUENCE_NUM_YEAR:5}' } }).numberMasks,
730
+ ).toEqual({ invoice: 'FV/{YYYY}/{SEQUENCE_NUM_YEAR:5}' })
731
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, numberMasks: { invoice: 'FV/{SEQUENCE_NUM_MONTH}' } })).toThrow(
732
+ 'mask_month_scope_needs_year_and_month',
733
+ )
734
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, numberMasks: { bogus: 'X{SEQUENCE_NUM}' } })).toThrow()
735
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, topupTaxRate: 120 })).toThrow()
736
+ })
737
+ })
738
+
739
+ describe('Spec B validators', () => {
740
+ const base = { tenantId: TENANT, organizationId: ORG }
741
+ const item = {
742
+ ...base,
743
+ billAccountId: ACCOUNT,
744
+ type: 'recurring' as const,
745
+ billStartDate: '2026-11-14',
746
+ description: 'Internet 300',
747
+ rateJson: { unit_price: 79 },
748
+ }
749
+
750
+ it('item taxRate is optional on create (the command fills the default) and bounded 0–100', () => {
751
+ expect(billingItemCreateSchema.parse(item)).not.toHaveProperty('taxRate')
752
+ expect(billingItemCreateSchema.parse({ ...item, taxRate: '8' }).taxRate).toBe(8)
753
+ expect(() => billingItemCreateSchema.parse({ ...item, taxRate: -1 })).toThrow()
754
+ expect(() => billingItemCreateSchema.parse({ ...item, taxRate: 101 })).toThrow()
755
+ })
756
+
757
+ it('normalizes and checksum-validates the seller IBAN; empty clears it', () => {
758
+ expect(billingSettingsUpdateSchema.parse({ ...base, iban: 'pl61 1090 1014 0000 0712 1981 2874' }).iban).toBe(
759
+ 'PL61109010140000071219812874',
760
+ )
761
+ expect(billingSettingsUpdateSchema.parse({ ...base, iban: '' }).iban).toBeNull()
762
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, iban: 'PL61109010140000071219812875' })).toThrow(
763
+ 'billing.settings.error.iban_invalid',
764
+ )
765
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, bic: 'XX' })).toThrow('billing.settings.error.bic_invalid')
766
+ })
767
+
768
+ it('validates seller address, terms and default rate', () => {
769
+ const parsed = billingSettingsUpdateSchema.parse({
770
+ ...base,
771
+ legalName: ' Seller ',
772
+ taxId: '',
773
+ sellerAddress: { line1: 'ul. A 1', city: 'Kraków', postal_code: '30-001', country: 'PL' },
774
+ defaultPaymentTermsDays: '30',
775
+ defaultTaxRate: 23,
776
+ })
777
+ expect(parsed).toMatchObject({ legalName: 'Seller', taxId: null, defaultPaymentTermsDays: 30, defaultTaxRate: 23 })
778
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, sellerAddress: { line1: 'x' } })).toThrow()
779
+ expect(() => billingSettingsUpdateSchema.parse({ ...base, defaultPaymentTermsDays: 400 })).toThrow()
780
+ })
781
+
782
+ it('accepts overdue / due-date filters on the invoice list', () => {
783
+ const parsed = billingInvoiceListQuerySchema.parse({ overdue: 'true', dueFrom: '2026-11-01', dueTo: '2026-11-30' })
784
+ expect(parsed).toMatchObject({ overdue: true, dueFrom: '2026-11-01', dueTo: '2026-11-30' })
785
+ expect(() => billingInvoiceListQuerySchema.parse({ dueFrom: '01.11.2026' })).toThrow()
786
+ })
787
+ })
788
+
@@ -8,9 +8,18 @@ export const features = [
8
8
  { id: 'billing.run.trigger', title: 'Trigger Bill Run', module: 'billing' },
9
9
  { id: 'billing.run.dry_run', title: 'Trigger Bill Run (dry-run)', module: 'billing' },
10
10
  { id: 'billing.run.view', title: 'View Bill Run History', module: 'billing' },
11
+ // Spec F — delete test / dry runs (real runs are never deleted)
12
+ { id: 'billing.run.delete', title: 'Delete Test / Dry Bill Runs', module: 'billing' },
11
13
  { id: 'billing.invoice.post', title: 'Post Draft Invoice', module: 'billing' },
12
14
  { id: 'billing.invoice.edit_draft', title: 'Edit Draft Invoice', module: 'billing' },
13
15
  { id: 'billing.invoice.view', title: 'View Billing Invoices', module: 'billing' },
16
+ { id: 'billing.invoice.send', title: 'Email Billing Invoices', module: 'billing' },
17
+ // Spec D — corrective documents
18
+ { id: 'billing.invoice.correct', title: 'Create Credit / Debit Memos', module: 'billing' },
19
+ // Spec C — payments
20
+ { id: 'billing.payment.view', title: 'View Billing Payments', module: 'billing' },
21
+ { id: 'billing.payment.manage', title: 'Manage Billing Payments (assign, allocate, ignore, convert)', module: 'billing' },
22
+ { id: 'billing.payment.import', title: 'Import Bank Payments (CSV)', module: 'billing' },
14
23
  // ─── Prepaid balance billing (SPEC-002) ──────────────────────
15
24
  { id: 'billing.balance.view', title: 'View Balance & Transactions', module: 'billing' },
16
25
  { id: 'billing.balance.adjust', title: 'Adjust Balance (manual credit/debit)', module: 'billing' },
@@ -19,6 +28,9 @@ export const features = [
19
28
  { id: 'billing.statement.view', title: 'View Consumption Statements', module: 'billing' },
20
29
  { id: 'billing.statement.generate', title: 'Generate Consumption Statement', module: 'billing' },
21
30
  { id: 'billing.credit.view', title: 'View Account Credit Status', module: 'billing' },
31
+ // ─── Billing settings (Spec 0) ───────────────────────────────
32
+ { id: 'billing.settings.view', title: 'View Billing Settings', module: 'billing' },
33
+ { id: 'billing.settings.manage', title: 'Manage Billing Settings', module: 'billing' },
22
34
  ] as const
23
35
 
24
36
  export default features
@@ -0,0 +1,62 @@
1
+ import { NextResponse } from 'next/server'
2
+ import type { EntityManager } from '@mikro-orm/postgresql'
3
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
+ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
5
+ import { BillingAccount } from '../../../../data/entities'
6
+ import { getAccountWorkspaceSummary } from '../../../../lib/accountSummary'
7
+
8
+ /**
9
+ * `GET /api/billing/accounts/[id]/summary` — what the customer owes (Spec B
10
+ * AR summary; Spec E extends the same endpoint for the account workspace).
11
+ * One aggregate query; see `lib/accountSummary.ts`.
12
+ */
13
+
14
+ export const metadata = {
15
+ GET: { requireAuth: true, requireFeatures: ['billing.account.view'] },
16
+ }
17
+
18
+ export async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) {
19
+ try {
20
+ const container = await createRequestContainer()
21
+ const auth = await getAuthFromRequest(req)
22
+ if (!auth || !auth.tenantId) {
23
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
24
+ }
25
+ const organizationId = (auth as { orgId?: string }).orgId ?? null
26
+ if (!organizationId) {
27
+ return NextResponse.json({ error: 'Organization scope required' }, { status: 403 })
28
+ }
29
+ const { id: accountId } = await params
30
+ const em = (container.resolve('em') as EntityManager).fork()
31
+ const account = await em.findOne(BillingAccount, {
32
+ id: accountId,
33
+ tenantId: auth.tenantId,
34
+ organizationId,
35
+ deletedAt: null,
36
+ })
37
+ if (!account) {
38
+ return NextResponse.json({ error: 'Account not found' }, { status: 404 })
39
+ }
40
+ return NextResponse.json(await getAccountWorkspaceSummary(em, account))
41
+ } catch (err) {
42
+ console.error('[billing/accounts/summary.GET]', err)
43
+ return NextResponse.json({ error: 'Internal error' }, { status: 500 })
44
+ }
45
+ }
46
+
47
+ export const openApi = {
48
+ methods: {
49
+ GET: {
50
+ tags: ['Billing'],
51
+ summary: 'Get a billing account receivables summary',
52
+ parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string', format: 'uuid' } }],
53
+ description:
54
+ 'Returns `{ bill_account_id, currency_code, open_amount, overdue_amount, overdue_count, ' +
55
+ 'credit_amount }` over posted / partially paid invoices and debit memos (test runs excluded). ' +
56
+ 'Overdue = past due date with outstanding > 0. `credit_amount` = unallocated payments + open credit memos. ' +
57
+ 'Spec F (account workspace) adds `billing_mode`, `bill_cycle`, `next_bill_date`, `last_invoice` ' +
58
+ '(`{ id, number, issue_date, total_gross }` or null) and, for prepaid accounts, `prepaid { balance, ' +
59
+ 'balance_status, credit_limit, last_statement }` (null for postpaid).',
60
+ },
61
+ },
62
+ }
@@ -2,8 +2,15 @@ import { z } from 'zod'
2
2
  import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
3
3
  import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'
4
4
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
5
+ import type { EntityManager } from '@mikro-orm/postgresql'
6
+ import type { AwilixContainer } from 'awilix'
5
7
  import { BillingAccount } from '../../data/entities'
8
+ import { fetchAccountFinancials, fetchOverdueAccountIds, financialsOrZero } from '../../lib/accountFinancials'
9
+
10
+ /** A uuid no row has — narrows an `$in` filter to nothing. */
11
+ const NO_MATCH_ID = '00000000-0000-4000-8000-000000000000'
6
12
  import { billingEntityIds } from '../../data/entityIds'
13
+ import { DEFAULT_INVOICE_LANGUAGE, INVOICE_LANGUAGE_CODES } from '../../lib/invoiceLanguages'
7
14
  import {
8
15
  billingAccountCreateSchema,
9
16
  billingAccountListQuerySchema,
@@ -33,6 +40,7 @@ export const metadata = routeMetadata
33
40
  const billingAccountListItemSchema = z.object({
34
41
  id: z.string().uuid(),
35
42
  customer_id: z.string(),
43
+ customer_kind: z.enum(['company', 'person']),
36
44
  name: z.string(),
37
45
  currency_code: z.string(),
38
46
  bill_cycle: z.string(),
@@ -45,6 +53,11 @@ const billingAccountListItemSchema = z.object({
45
53
  last_bill_date: z.string().nullable(),
46
54
  billing_mode: z.string(),
47
55
  credit_limit: z.string(),
56
+ payment_terms_days: z.number().int().nullable(),
57
+ auto_send_invoice: z.boolean(),
58
+ /** Spec F (F8): Σ outstanding of open receivables and its overdue subset (batched per page). */
59
+ balance_due: z.string(),
60
+ overdue_amount: z.string(),
48
61
  is_active: z.boolean(),
49
62
  organization_id: z.string().uuid(),
50
63
  tenant_id: z.string().uuid(),
@@ -71,6 +84,7 @@ const crud = makeCrudRoute({
71
84
  fields: [
72
85
  'id',
73
86
  'customer_id',
87
+ 'customer_kind',
74
88
  'name',
75
89
  'currency_code',
76
90
  'bill_cycle',
@@ -83,6 +97,8 @@ const crud = makeCrudRoute({
83
97
  'last_bill_date',
84
98
  'billing_mode',
85
99
  'credit_limit',
100
+ 'payment_terms_days',
101
+ 'auto_send_invoice',
86
102
  'is_active',
87
103
  'organization_id',
88
104
  'tenant_id',
@@ -95,16 +111,28 @@ const crud = makeCrudRoute({
95
111
  updatedAt: 'updated_at',
96
112
  nextBillDate: 'next_bill_date',
97
113
  },
98
- buildFilters: async (query) => {
114
+ buildFilters: async (query, ctx) => {
99
115
  const filters: Record<string, unknown> = {}
116
+ // Spec F (F8): accounts with an overdue receivable — one indexed
117
+ // DISTINCT over billing_invoices, intersected with any `id` filter.
118
+ if (query.hasOverdue === true && ctx.auth?.tenantId) {
119
+ const organizationIds = ctx.organizationIds ?? (ctx.selectedOrganizationId ? [ctx.selectedOrganizationId] : [])
120
+ const em = ctx.container.resolve<EntityManager>('em')
121
+ const overdueIds = await fetchOverdueAccountIds(em, { tenantId: ctx.auth.tenantId, organizationIds })
122
+ filters.id = { $in: overdueIds.length > 0 ? overdueIds : [NO_MATCH_ID] }
123
+ }
100
124
  // `?id=<uuid>` narrows the list to one row — the detail page
101
125
  // reads a single account through this filter.
102
126
  if (typeof query.id === 'string' && query.id) {
103
- filters.id = { $eq: query.id }
127
+ const current = filters.id as { $in?: string[] } | undefined
128
+ filters.id = current?.$in ? { $in: current.$in.includes(query.id) ? [query.id] : [NO_MATCH_ID] } : { $eq: query.id }
104
129
  }
105
130
  if (typeof query.customerId === 'string' && query.customerId) {
106
131
  filters.customer_id = { $eq: query.customerId }
107
132
  }
133
+ if (typeof query.customerKind === 'string' && query.customerKind) {
134
+ filters.customer_kind = { $eq: query.customerKind }
135
+ }
108
136
  if (typeof query.currencyCode === 'string' && query.currencyCode) {
109
137
  filters.currency_code = { $eq: query.currencyCode.toUpperCase() }
110
138
  }
@@ -124,6 +152,30 @@ const crud = makeCrudRoute({
124
152
  return filters
125
153
  },
126
154
  },
155
+ hooks: {
156
+ // Spec F (F8): balance due / overdue per row — one GROUP BY for the page.
157
+ afterList: async (payload: unknown, ctx: unknown) => {
158
+ const items = ((payload as { items?: unknown[] } | null)?.items ?? []) as Array<Record<string, unknown>>
159
+ if (items.length === 0) return
160
+ const first = items[0]
161
+ const tenantId = typeof first.tenant_id === 'string' ? first.tenant_id : null
162
+ const organizationId = typeof first.organization_id === 'string' ? first.organization_id : null
163
+ const ids = items.map((row) => row.id).filter((id): id is string => typeof id === 'string')
164
+ const financials =
165
+ tenantId && organizationId
166
+ ? await fetchAccountFinancials(
167
+ (ctx as { container: AwilixContainer }).container.resolve<EntityManager>('em'),
168
+ { tenantId, organizationId },
169
+ ids,
170
+ )
171
+ : new Map()
172
+ for (const row of items) {
173
+ const values = financialsOrZero(financials, String(row.id))
174
+ row.balance_due = values.balance_due
175
+ row.overdue_amount = values.overdue_amount
176
+ }
177
+ },
178
+ },
127
179
  actions: {
128
180
  create: {
129
181
  commandId: 'billing.accounts.create',
@@ -190,12 +242,15 @@ export const openApi = createBillingCrudOpenApi({
190
242
  create: {
191
243
  schema: billingAccountCreateSchema,
192
244
  responseSchema: defaultCreateResponseSchema,
193
- description: 'Creates a new billing account for a customer.',
245
+ description:
246
+ 'Creates a new billing account for a customer — a company or a person (`customerKind`, default `company`). ' +
247
+ `\`invoiceLanguage\` must be a language supported by the invoice template (${INVOICE_LANGUAGE_CODES.map((c) => `\`${c}\``).join(', ')}; default \`${DEFAULT_INVOICE_LANGUAGE}\`).`,
194
248
  },
195
249
  update: {
196
250
  schema: billingAccountUpdateSchema,
197
251
  responseSchema: defaultOkResponseSchema,
198
- description: 'Updates a billing account. `currencyCode` and `customerId` are immutable.',
252
+ description:
253
+ 'Updates a billing account. `currencyCode`, `customerId` and `customerKind` are immutable.',
199
254
  },
200
255
  del: {
201
256
  schema: z.object({ id: z.string().uuid() }),
@@ -23,8 +23,7 @@ import {
23
23
  * - Every active + soft-deleted `BillingItem` for the account.
24
24
  * - Every `BillingAccountUsage` record.
25
25
  * - Every `BillingRunOutcome` row referencing the account.
26
- * - Every `core/sales` invoice the engine emitted for the account
27
- * (matched via `metadata->>'bill_account_id'`).
26
+ * - Every billing document (`billing_invoices`) of the account.
28
27
  * - Every `BillingDraftInvoiceEdit` audit row for those invoices.
29
28
  *
30
29
  * Scope: the caller's auth tenant/organization is the authority — a
@@ -154,18 +153,18 @@ export async function GET(
154
153
  ),
155
154
  ])
156
155
 
157
- // Invoices created in the window. The `metadata->>'bill_account_id'`
158
- // predicate keeps non-billing core/sales invoices out.
156
+ // Billing documents created in the window (Spec 0: billing_invoices).
159
157
  const invoiceRows = (await em.execute(
160
- `SELECT id, invoice_number, status, status_entry_id, issue_date, due_date,
161
- currency_code, subtotal_net_amount, grand_total_net_amount,
162
- grand_total_gross_amount, paid_total_amount, outstanding_amount,
163
- metadata, created_at, updated_at, deleted_at
164
- FROM sales_invoices
158
+ `SELECT id, number, document_type, series, status, test_run, bill_run_id, bill_date,
159
+ period_start, period_end, issue_date, due_date, posted_at, currency_code,
160
+ subtotal_net, tax_total, total_gross, paid_total, credited_total, outstanding,
161
+ corrects_invoice_id, correction_reason, topup_id, buyer_snapshot, seller_snapshot,
162
+ metadata, created_at, updated_at
163
+ FROM billing_invoices
165
164
  WHERE tenant_id = ?
166
165
  AND organization_id = ?
167
166
  AND deleted_at IS NULL
168
- AND metadata->>'bill_account_id' = ?
167
+ AND bill_account_id = ?
169
168
  AND created_at >= ?
170
169
  AND created_at <= ?
171
170
  ORDER BY created_at DESC
@@ -190,7 +189,10 @@ export async function GET(
190
189
  return NextResponse.json({
191
190
  exportedAt: new Date().toISOString(),
192
191
  // v2 adds prepaid balance / transactions / top-ups / statements (SPEC-002).
193
- schemaVersion: 2,
192
+ // v3 (Spec 0): invoices come from billing_invoices with billing field names.
193
+ // v4 (Spec B): items carry taxRate; the account carries paymentTermsDays /
194
+ // autoSendInvoice; invoice metadata may carry draft_number / deliveries.
195
+ schemaVersion: 4,
194
196
  tenantId,
195
197
  organizationId,
196
198
  window: {
@@ -0,0 +1,63 @@
1
+ import { z } from 'zod'
2
+ import { readRequestBody, runCommandRoute } from '../../../../lib/commandRoute'
3
+
4
+ /**
5
+ * `POST /api/billing/invoices/[id]/memos` — create a DRAFT credit or debit
6
+ * memo correcting a posted billing invoice (Spec D). Post it with
7
+ * `POST /api/billing/invoices/post`.
8
+ */
9
+
10
+ export const metadata = {
11
+ POST: { requireAuth: true, requireFeatures: ['billing.invoice.correct'] },
12
+ }
13
+
14
+ const lineSchema = z.object({
15
+ correctsLineId: z.string().uuid().optional(),
16
+ description: z.string().trim().min(1).max(500),
17
+ quantity: z.coerce.number().positive(),
18
+ unitPriceNet: z.coerce.number().nonnegative(),
19
+ taxRate: z.coerce.number().min(0).max(100).optional(),
20
+ })
21
+
22
+ const bodySchema = z.object({
23
+ invoiceId: z.string().uuid(),
24
+ type: z.enum(['credit_memo', 'debit_memo']),
25
+ reason: z.string().trim().min(1).max(1000),
26
+ lines: z.array(lineSchema).max(200).optional(),
27
+ })
28
+
29
+ export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
30
+ const { id } = await params
31
+ const raw = (await readRequestBody(req)) as Record<string, unknown>
32
+ return runCommandRoute(
33
+ req,
34
+ {
35
+ commandId: 'billing.invoices.create_memo',
36
+ bodySchema,
37
+ resourceKind: 'billing.invoice',
38
+ resourceId: (body) => body.invoiceId,
39
+ logLabel: 'billing/invoices/[id]/memos.POST',
40
+ },
41
+ { ...(raw && typeof raw === 'object' ? raw : {}), invoiceId: id },
42
+ )
43
+ }
44
+
45
+ export const openApi = {
46
+ methods: {
47
+ POST: {
48
+ tags: ['Billing'],
49
+ summary: 'Create a credit or debit memo',
50
+ description:
51
+ 'Creates a draft memo for a posted / partially paid / paid invoice (a fully credited invoice ' +
52
+ 'accepts debit memos only). `reason` is required and printed. Credit memo without `lines` = full ' +
53
+ 'credit of every original line; lines with `correctsLineId` keep the original VAT rate; new lines ' +
54
+ 'default to the organization rate. Amounts are positive — the document type gives the sign.',
55
+ requestBody: { schema: bodySchema.omit({ invoiceId: true }) },
56
+ responses: [{ status: 200, description: '`{ memoId, number, documentType, totalGross }`' }],
57
+ errors: [
58
+ { status: 409, description: '`billing.memo.invalid_original` / `billing.memo.exceeds_invoice`' },
59
+ { status: 400, description: '`billing.memo.invalid_line`' },
60
+ ],
61
+ },
62
+ },
63
+ }