@dainamite/billing 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +14 -0
  3. package/dist/modules/billing/acl.js +13 -1
  4. package/dist/modules/billing/acl.js.map +2 -2
  5. package/dist/modules/billing/api/accounts/[id]/summary/route.js +52 -0
  6. package/dist/modules/billing/api/accounts/[id]/summary/route.js.map +7 -0
  7. package/dist/modules/billing/api/accounts/route.js +46 -4
  8. package/dist/modules/billing/api/accounts/route.js.map +2 -2
  9. package/dist/modules/billing/api/export/account/[id]/route.js +16 -12
  10. package/dist/modules/billing/api/export/account/[id]/route.js.map +2 -2
  11. package/dist/modules/billing/api/invoices/[id]/memos/route.js +54 -0
  12. package/dist/modules/billing/api/invoices/[id]/memos/route.js.map +7 -0
  13. package/dist/modules/billing/api/invoices/[id]/pdf/route.js +69 -0
  14. package/dist/modules/billing/api/invoices/[id]/pdf/route.js.map +7 -0
  15. package/dist/modules/billing/api/invoices/[id]/route.js +44 -24
  16. package/dist/modules/billing/api/invoices/[id]/route.js.map +2 -2
  17. package/dist/modules/billing/api/invoices/[id]/send/route.js +107 -0
  18. package/dist/modules/billing/api/invoices/[id]/send/route.js.map +7 -0
  19. package/dist/modules/billing/api/invoices/add-line/route.js +3 -3
  20. package/dist/modules/billing/api/invoices/add-line/route.js.map +2 -2
  21. package/dist/modules/billing/api/invoices/delete-draft/route.js +33 -0
  22. package/dist/modules/billing/api/invoices/delete-draft/route.js.map +7 -0
  23. package/dist/modules/billing/api/invoices/edit-line/route.js +3 -3
  24. package/dist/modules/billing/api/invoices/edit-line/route.js.map +2 -2
  25. package/dist/modules/billing/api/invoices/post/route.js +2 -2
  26. package/dist/modules/billing/api/invoices/post/route.js.map +2 -2
  27. package/dist/modules/billing/api/invoices/remove-line/route.js +3 -3
  28. package/dist/modules/billing/api/invoices/remove-line/route.js.map +2 -2
  29. package/dist/modules/billing/api/invoices/route.js +45 -46
  30. package/dist/modules/billing/api/invoices/route.js.map +2 -2
  31. package/dist/modules/billing/api/items/bulk/route.js +1 -1
  32. package/dist/modules/billing/api/items/bulk/route.js.map +2 -2
  33. package/dist/modules/billing/api/items/change-price/route.js +44 -0
  34. package/dist/modules/billing/api/items/change-price/route.js.map +7 -0
  35. package/dist/modules/billing/api/items/route.js +19 -7
  36. package/dist/modules/billing/api/items/route.js.map +2 -2
  37. package/dist/modules/billing/api/payment-imports/[id]/route.js +49 -0
  38. package/dist/modules/billing/api/payment-imports/[id]/route.js.map +7 -0
  39. package/dist/modules/billing/api/payment-imports/route.js +57 -0
  40. package/dist/modules/billing/api/payment-imports/route.js.map +7 -0
  41. package/dist/modules/billing/api/payments/[id]/route.js +60 -0
  42. package/dist/modules/billing/api/payments/[id]/route.js.map +7 -0
  43. package/dist/modules/billing/api/payments/allocate/route.js +35 -0
  44. package/dist/modules/billing/api/payments/allocate/route.js.map +7 -0
  45. package/dist/modules/billing/api/payments/assign/route.js +36 -0
  46. package/dist/modules/billing/api/payments/assign/route.js.map +7 -0
  47. package/dist/modules/billing/api/payments/convert-to-topup/route.js +35 -0
  48. package/dist/modules/billing/api/payments/convert-to-topup/route.js.map +7 -0
  49. package/dist/modules/billing/api/payments/ignore/route.js +35 -0
  50. package/dist/modules/billing/api/payments/ignore/route.js.map +7 -0
  51. package/dist/modules/billing/api/payments/import/route.js +63 -0
  52. package/dist/modules/billing/api/payments/import/route.js.map +7 -0
  53. package/dist/modules/billing/api/payments/restore/route.js +35 -0
  54. package/dist/modules/billing/api/payments/restore/route.js.map +7 -0
  55. package/dist/modules/billing/api/payments/route.js +114 -0
  56. package/dist/modules/billing/api/payments/route.js.map +7 -0
  57. package/dist/modules/billing/api/payments/unallocate/route.js +35 -0
  58. package/dist/modules/billing/api/payments/unallocate/route.js.map +7 -0
  59. package/dist/modules/billing/api/payments/unassign/route.js +35 -0
  60. package/dist/modules/billing/api/payments/unassign/route.js.map +7 -0
  61. package/dist/modules/billing/api/run-outcomes/route.js +44 -7
  62. package/dist/modules/billing/api/run-outcomes/route.js.map +2 -2
  63. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js +61 -0
  64. package/dist/modules/billing/api/runs/[id]/post-drafts/route.js.map +7 -0
  65. package/dist/modules/billing/api/runs/[id]/route.js +53 -0
  66. package/dist/modules/billing/api/runs/[id]/route.js.map +7 -0
  67. package/dist/modules/billing/api/runs/retry-failed/route.js +3 -3
  68. package/dist/modules/billing/api/runs/retry-failed/route.js.map +2 -2
  69. package/dist/modules/billing/api/runs/route.js +11 -5
  70. package/dist/modules/billing/api/runs/route.js.map +2 -2
  71. package/dist/modules/billing/api/settings/number-preview/route.js +42 -0
  72. package/dist/modules/billing/api/settings/number-preview/route.js.map +7 -0
  73. package/dist/modules/billing/api/settings/route.js +92 -0
  74. package/dist/modules/billing/api/settings/route.js.map +7 -0
  75. package/dist/modules/billing/api/statements/route.js +3 -0
  76. package/dist/modules/billing/api/statements/route.js.map +2 -2
  77. package/dist/modules/billing/api/test-invoices/wipe/route.js +2 -2
  78. package/dist/modules/billing/api/test-invoices/wipe/route.js.map +2 -2
  79. package/dist/modules/billing/backend/billing/accounts/[id]/page.js +121 -232
  80. package/dist/modules/billing/backend/billing/accounts/[id]/page.js.map +2 -2
  81. package/dist/modules/billing/backend/billing/accounts/create/page.js +6 -0
  82. package/dist/modules/billing/backend/billing/accounts/create/page.js.map +2 -2
  83. package/dist/modules/billing/backend/billing/accounts/page.js +63 -4
  84. package/dist/modules/billing/backend/billing/accounts/page.js.map +2 -2
  85. package/dist/modules/billing/backend/billing/invoices/[id]/page.js +297 -65
  86. package/dist/modules/billing/backend/billing/invoices/[id]/page.js.map +3 -3
  87. package/dist/modules/billing/backend/billing/invoices/page.js +6 -172
  88. package/dist/modules/billing/backend/billing/invoices/page.js.map +2 -2
  89. package/dist/modules/billing/backend/billing/items/[id]/page.js +51 -7
  90. package/dist/modules/billing/backend/billing/items/[id]/page.js.map +2 -2
  91. package/dist/modules/billing/backend/billing/items/create/page.js +9 -6
  92. package/dist/modules/billing/backend/billing/items/create/page.js.map +2 -2
  93. package/dist/modules/billing/backend/billing/items/page.js +8 -2
  94. package/dist/modules/billing/backend/billing/items/page.js.map +2 -2
  95. package/dist/modules/billing/backend/billing/payments/[id]/page.js +297 -0
  96. package/dist/modules/billing/backend/billing/payments/[id]/page.js.map +7 -0
  97. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js +21 -0
  98. package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js.map +7 -0
  99. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js +74 -0
  100. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js.map +7 -0
  101. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js +21 -0
  102. package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js.map +7 -0
  103. package/dist/modules/billing/backend/billing/payments/page.js +58 -0
  104. package/dist/modules/billing/backend/billing/payments/page.js.map +7 -0
  105. package/dist/modules/billing/backend/billing/payments/page.meta.js +18 -0
  106. package/dist/modules/billing/backend/billing/payments/page.meta.js.map +7 -0
  107. package/dist/modules/billing/backend/billing/runs/[id]/page.js +49 -14
  108. package/dist/modules/billing/backend/billing/runs/[id]/page.js.map +2 -2
  109. package/dist/modules/billing/backend/billing/runs/page.js +58 -7
  110. package/dist/modules/billing/backend/billing/runs/page.js.map +2 -2
  111. package/dist/modules/billing/backend/billing/statements/[id]/page.js +61 -6
  112. package/dist/modules/billing/backend/billing/statements/[id]/page.js.map +2 -2
  113. package/dist/modules/billing/backend/billing/statements/page.js +1 -1
  114. package/dist/modules/billing/backend/billing/statements/page.js.map +2 -2
  115. package/dist/modules/billing/backend/billing/topups/page.js +1 -1
  116. package/dist/modules/billing/backend/billing/topups/page.js.map +2 -2
  117. package/dist/modules/billing/backend/billing/transactions/page.js +1 -1
  118. package/dist/modules/billing/backend/billing/transactions/page.js.map +2 -2
  119. package/dist/modules/billing/backend/billing/usage/create/page.js +3 -2
  120. package/dist/modules/billing/backend/billing/usage/create/page.js.map +2 -2
  121. package/dist/modules/billing/backend/config/billing/page.js +472 -0
  122. package/dist/modules/billing/backend/config/billing/page.js.map +7 -0
  123. package/dist/modules/billing/backend/config/billing/page.meta.js +19 -0
  124. package/dist/modules/billing/backend/config/billing/page.meta.js.map +7 -0
  125. package/dist/modules/billing/ce.js.map +2 -2
  126. package/dist/modules/billing/cli.js +22 -1
  127. package/dist/modules/billing/cli.js.map +2 -2
  128. package/dist/modules/billing/commands/accounts.js +6 -0
  129. package/dist/modules/billing/commands/accounts.js.map +2 -2
  130. package/dist/modules/billing/commands/index.js +3 -0
  131. package/dist/modules/billing/commands/index.js.map +2 -2
  132. package/dist/modules/billing/commands/invoices.js +272 -170
  133. package/dist/modules/billing/commands/invoices.js.map +2 -2
  134. package/dist/modules/billing/commands/items.js +108 -0
  135. package/dist/modules/billing/commands/items.js.map +2 -2
  136. package/dist/modules/billing/commands/memos.js +179 -0
  137. package/dist/modules/billing/commands/memos.js.map +7 -0
  138. package/dist/modules/billing/commands/payments.js +379 -0
  139. package/dist/modules/billing/commands/payments.js.map +7 -0
  140. package/dist/modules/billing/commands/runs.js +154 -7
  141. package/dist/modules/billing/commands/runs.js.map +2 -2
  142. package/dist/modules/billing/commands/settings.js +59 -0
  143. package/dist/modules/billing/commands/settings.js.map +7 -0
  144. package/dist/modules/billing/commands/topups.js +9 -2
  145. package/dist/modules/billing/commands/topups.js.map +2 -2
  146. package/dist/modules/billing/commands/transactions.js +2 -2
  147. package/dist/modules/billing/commands/transactions.js.map +2 -2
  148. package/dist/modules/billing/components/AccountForm.js +149 -42
  149. package/dist/modules/billing/components/AccountForm.js.map +2 -2
  150. package/dist/modules/billing/components/AccountInvoicesSection.js +64 -0
  151. package/dist/modules/billing/components/AccountInvoicesSection.js.map +7 -0
  152. package/dist/modules/billing/components/AccountPaymentsSection.js +43 -0
  153. package/dist/modules/billing/components/AccountPaymentsSection.js.map +7 -0
  154. package/dist/modules/billing/components/AccountPicker.js +56 -0
  155. package/dist/modules/billing/components/AccountPicker.js.map +7 -0
  156. package/dist/modules/billing/components/AllocatePaymentDialog.js +134 -0
  157. package/dist/modules/billing/components/AllocatePaymentDialog.js.map +7 -0
  158. package/dist/modules/billing/components/BillingDataTable.js +21 -0
  159. package/dist/modules/billing/components/BillingDataTable.js.map +7 -0
  160. package/dist/modules/billing/components/BillingSettingsLink.js +19 -0
  161. package/dist/modules/billing/components/BillingSettingsLink.js.map +7 -0
  162. package/dist/modules/billing/components/ChangeItemPriceDialog.js +158 -0
  163. package/dist/modules/billing/components/ChangeItemPriceDialog.js.map +7 -0
  164. package/dist/modules/billing/components/CreateMemoDialog.js +200 -0
  165. package/dist/modules/billing/components/CreateMemoDialog.js.map +7 -0
  166. package/dist/modules/billing/components/CustomerLabel.js +33 -0
  167. package/dist/modules/billing/components/CustomerLabel.js.map +7 -0
  168. package/dist/modules/billing/components/InvoicesTable.js +270 -0
  169. package/dist/modules/billing/components/InvoicesTable.js.map +7 -0
  170. package/dist/modules/billing/components/ItemForm.js +176 -44
  171. package/dist/modules/billing/components/ItemForm.js.map +2 -2
  172. package/dist/modules/billing/components/ItemPriceField.js +46 -0
  173. package/dist/modules/billing/components/ItemPriceField.js.map +7 -0
  174. package/dist/modules/billing/components/LineFormDialog.js +25 -2
  175. package/dist/modules/billing/components/LineFormDialog.js.map +2 -2
  176. package/dist/modules/billing/components/ManualPaymentDialog.js +122 -0
  177. package/dist/modules/billing/components/ManualPaymentDialog.js.map +7 -0
  178. package/dist/modules/billing/components/MoneyInput.js +14 -0
  179. package/dist/modules/billing/components/MoneyInput.js.map +7 -0
  180. package/dist/modules/billing/components/PaymentUploadDialog.js +115 -0
  181. package/dist/modules/billing/components/PaymentUploadDialog.js.map +7 -0
  182. package/dist/modules/billing/components/PaymentsTable.js +171 -0
  183. package/dist/modules/billing/components/PaymentsTable.js.map +7 -0
  184. package/dist/modules/billing/components/PostRunDraftsButton.js +105 -0
  185. package/dist/modules/billing/components/PostRunDraftsButton.js.map +7 -0
  186. package/dist/modules/billing/components/PrepaidPanel.js +14 -4
  187. package/dist/modules/billing/components/PrepaidPanel.js.map +2 -2
  188. package/dist/modules/billing/components/RunCyclesSection.js +209 -0
  189. package/dist/modules/billing/components/RunCyclesSection.js.map +7 -0
  190. package/dist/modules/billing/components/TestRunActions.js +127 -0
  191. package/dist/modules/billing/components/TestRunActions.js.map +7 -0
  192. package/dist/modules/billing/components/account/AccountItemsTab.js +157 -0
  193. package/dist/modules/billing/components/account/AccountItemsTab.js.map +7 -0
  194. package/dist/modules/billing/components/account/AccountRunBillingDialog.js +122 -0
  195. package/dist/modules/billing/components/account/AccountRunBillingDialog.js.map +7 -0
  196. package/dist/modules/billing/components/account/AccountRunsTab.js +152 -0
  197. package/dist/modules/billing/components/account/AccountRunsTab.js.map +7 -0
  198. package/dist/modules/billing/components/account/AccountStatementsTab.js +98 -0
  199. package/dist/modules/billing/components/account/AccountStatementsTab.js.map +7 -0
  200. package/dist/modules/billing/components/account/AccountSummaryCards.js +125 -0
  201. package/dist/modules/billing/components/account/AccountSummaryCards.js.map +7 -0
  202. package/dist/modules/billing/components/account/AccountUsageTab.js +91 -0
  203. package/dist/modules/billing/components/account/AccountUsageTab.js.map +7 -0
  204. package/dist/modules/billing/components/account/AccountView.js +73 -0
  205. package/dist/modules/billing/components/account/AccountView.js.map +7 -0
  206. package/dist/modules/billing/components/account/accountRow.js +39 -0
  207. package/dist/modules/billing/components/account/accountRow.js.map +7 -0
  208. package/dist/modules/billing/components/customerNames.js +42 -0
  209. package/dist/modules/billing/components/customerNames.js.map +7 -0
  210. package/dist/modules/billing/data/entities.js +615 -59
  211. package/dist/modules/billing/data/entities.js.map +2 -2
  212. package/dist/modules/billing/data/entityIds.js +10 -1
  213. package/dist/modules/billing/data/entityIds.js.map +2 -2
  214. package/dist/modules/billing/data/validators.js +269 -15
  215. package/dist/modules/billing/data/validators.js.map +2 -2
  216. package/dist/modules/billing/events.js +70 -0
  217. package/dist/modules/billing/events.js.map +2 -2
  218. package/dist/modules/billing/i18n/en.json +457 -21
  219. package/dist/modules/billing/i18n/pl.json +457 -21
  220. package/dist/modules/billing/index.js +6 -2
  221. package/dist/modules/billing/index.js.map +2 -2
  222. package/dist/modules/billing/lib/accountFinancials.js +58 -0
  223. package/dist/modules/billing/lib/accountFinancials.js.map +7 -0
  224. package/dist/modules/billing/lib/accountLock.js +14 -0
  225. package/dist/modules/billing/lib/accountLock.js.map +7 -0
  226. package/dist/modules/billing/lib/accountStatus.js +9 -7
  227. package/dist/modules/billing/lib/accountStatus.js.map +2 -2
  228. package/dist/modules/billing/lib/accountSummary.js +106 -0
  229. package/dist/modules/billing/lib/accountSummary.js.map +7 -0
  230. package/dist/modules/billing/lib/allocation.js +356 -0
  231. package/dist/modules/billing/lib/allocation.js.map +7 -0
  232. package/dist/modules/billing/lib/allocationEvents.js +22 -0
  233. package/dist/modules/billing/lib/allocationEvents.js.map +7 -0
  234. package/dist/modules/billing/lib/billPeriod.js +15 -1
  235. package/dist/modules/billing/lib/billPeriod.js.map +2 -2
  236. package/dist/modules/billing/lib/billRunEngine.js +241 -106
  237. package/dist/modules/billing/lib/billRunEngine.js.map +2 -2
  238. package/dist/modules/billing/lib/billRunLabel.js.map +1 -1
  239. package/dist/modules/billing/lib/billingSettings.js +116 -0
  240. package/dist/modules/billing/lib/billingSettings.js.map +7 -0
  241. package/dist/modules/billing/lib/commandRoute.js +81 -0
  242. package/dist/modules/billing/lib/commandRoute.js.map +7 -0
  243. package/dist/modules/billing/lib/customerLookup.js +97 -0
  244. package/dist/modules/billing/lib/customerLookup.js.map +7 -0
  245. package/dist/modules/billing/lib/dateOnly.js +13 -0
  246. package/dist/modules/billing/lib/dateOnly.js.map +7 -0
  247. package/dist/modules/billing/lib/documentParties.js +16 -0
  248. package/dist/modules/billing/lib/documentParties.js.map +7 -0
  249. package/dist/modules/billing/lib/documentTypes.js +27 -0
  250. package/dist/modules/billing/lib/documentTypes.js.map +7 -0
  251. package/dist/modules/billing/lib/dueDate.js +18 -0
  252. package/dist/modules/billing/lib/dueDate.js.map +7 -0
  253. package/dist/modules/billing/lib/iban.js +29 -0
  254. package/dist/modules/billing/lib/iban.js.map +7 -0
  255. package/dist/modules/billing/lib/invoiceDelivery.js +131 -0
  256. package/dist/modules/billing/lib/invoiceDelivery.js.map +7 -0
  257. package/dist/modules/billing/lib/invoiceLanguages.js +16 -0
  258. package/dist/modules/billing/lib/invoiceLanguages.js.map +7 -0
  259. package/dist/modules/billing/lib/invoiceWriter.js +107 -99
  260. package/dist/modules/billing/lib/invoiceWriter.js.map +2 -2
  261. package/dist/modules/billing/lib/itemBillingState.js +27 -0
  262. package/dist/modules/billing/lib/itemBillingState.js.map +7 -0
  263. package/dist/modules/billing/lib/itemPriceChange.js +18 -0
  264. package/dist/modules/billing/lib/itemPriceChange.js.map +7 -0
  265. package/dist/modules/billing/lib/itemSelector.js.map +2 -2
  266. package/dist/modules/billing/lib/lineAmounts.js +32 -0
  267. package/dist/modules/billing/lib/lineAmounts.js.map +7 -0
  268. package/dist/modules/billing/lib/memoGuards.js +25 -0
  269. package/dist/modules/billing/lib/memoGuards.js.map +7 -0
  270. package/dist/modules/billing/lib/navigation.js +48 -0
  271. package/dist/modules/billing/lib/navigation.js.map +7 -0
  272. package/dist/modules/billing/lib/numbering.js +120 -0
  273. package/dist/modules/billing/lib/numbering.js.map +7 -0
  274. package/dist/modules/billing/lib/overdue.js +36 -0
  275. package/dist/modules/billing/lib/overdue.js.map +7 -0
  276. package/dist/modules/billing/lib/paymentCsv.js +125 -0
  277. package/dist/modules/billing/lib/paymentCsv.js.map +7 -0
  278. package/dist/modules/billing/lib/paymentGateway.js +15 -0
  279. package/dist/modules/billing/lib/paymentGateway.js.map +7 -0
  280. package/dist/modules/billing/lib/paymentImport.js +164 -0
  281. package/dist/modules/billing/lib/paymentImport.js.map +7 -0
  282. package/dist/modules/billing/lib/paymentMatcher.js +36 -0
  283. package/dist/modules/billing/lib/paymentMatcher.js.map +7 -0
  284. package/dist/modules/billing/lib/pdf/attachmentStore.js +46 -0
  285. package/dist/modules/billing/lib/pdf/attachmentStore.js.map +7 -0
  286. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js +7 -0
  287. package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js.map +7 -0
  288. package/dist/modules/billing/lib/pdf/invoiceModel.js +194 -0
  289. package/dist/modules/billing/lib/pdf/invoiceModel.js.map +7 -0
  290. package/dist/modules/billing/lib/pdf/invoicePdf.js +165 -0
  291. package/dist/modules/billing/lib/pdf/invoicePdf.js.map +7 -0
  292. package/dist/modules/billing/lib/pdf/invoiceTemplate.js +274 -0
  293. package/dist/modules/billing/lib/pdf/invoiceTemplate.js.map +7 -0
  294. package/dist/modules/billing/lib/prepaidConfig.js +17 -25
  295. package/dist/modules/billing/lib/prepaidConfig.js.map +2 -2
  296. package/dist/modules/billing/lib/prepaidConsume.js +26 -7
  297. package/dist/modules/billing/lib/prepaidConsume.js.map +2 -2
  298. package/dist/modules/billing/lib/prepaidPeriodClose.js +277 -158
  299. package/dist/modules/billing/lib/prepaidPeriodClose.js.map +2 -2
  300. package/dist/modules/billing/lib/prepaidTaxPoint.js +37 -0
  301. package/dist/modules/billing/lib/prepaidTaxPoint.js.map +7 -0
  302. package/dist/modules/billing/lib/seeds/demo.js +51 -3
  303. package/dist/modules/billing/lib/seeds/demo.js.map +2 -2
  304. package/dist/modules/billing/lib/seeds/paymentsSample.js +93 -0
  305. package/dist/modules/billing/lib/seeds/paymentsSample.js.map +7 -0
  306. package/dist/modules/billing/lib/seeds/sellerSettings.js +41 -0
  307. package/dist/modules/billing/lib/seeds/sellerSettings.js.map +7 -0
  308. package/dist/modules/billing/lib/servicePeriods.js +121 -0
  309. package/dist/modules/billing/lib/servicePeriods.js.map +7 -0
  310. package/dist/modules/billing/lib/tenantLock.js.map +1 -1
  311. package/dist/modules/billing/lib/testRunCleanup.js +24 -0
  312. package/dist/modules/billing/lib/testRunCleanup.js.map +7 -0
  313. package/dist/modules/billing/lib/topupCapture.js +2 -2
  314. package/dist/modules/billing/lib/topupCapture.js.map +2 -2
  315. package/dist/modules/billing/lib/topupReceipt.js +58 -79
  316. package/dist/modules/billing/lib/topupReceipt.js.map +2 -2
  317. package/dist/modules/billing/lib/usageRater.js.map +1 -1
  318. package/dist/modules/billing/lib/usageRunner.js +14 -6
  319. package/dist/modules/billing/lib/usageRunner.js.map +2 -2
  320. package/dist/modules/billing/lib/vat.js +39 -0
  321. package/dist/modules/billing/lib/vat.js.map +7 -0
  322. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js +15 -0
  323. package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js.map +7 -0
  324. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js +25 -0
  325. package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js.map +7 -0
  326. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js +115 -0
  327. package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js.map +7 -0
  328. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js +47 -0
  329. package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js.map +7 -0
  330. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js +89 -0
  331. package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js.map +7 -0
  332. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js +17 -0
  333. package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js.map +7 -0
  334. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js +27 -0
  335. package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js.map +7 -0
  336. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js +29 -0
  337. package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js.map +7 -0
  338. package/dist/modules/billing/setup.js +7 -184
  339. package/dist/modules/billing/setup.js.map +2 -2
  340. package/dist/modules/billing/subscribers/credit-memo-auto-send.js +16 -0
  341. package/dist/modules/billing/subscribers/credit-memo-auto-send.js.map +7 -0
  342. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js +16 -0
  343. package/dist/modules/billing/subscribers/debit-memo-apply-credit.js.map +7 -0
  344. package/dist/modules/billing/subscribers/debit-memo-auto-send.js +16 -0
  345. package/dist/modules/billing/subscribers/debit-memo-auto-send.js.map +7 -0
  346. package/dist/modules/billing/subscribers/invoice-apply-credit.js +34 -0
  347. package/dist/modules/billing/subscribers/invoice-apply-credit.js.map +7 -0
  348. package/dist/modules/billing/subscribers/invoice-auto-send.js +30 -0
  349. package/dist/modules/billing/subscribers/invoice-auto-send.js.map +7 -0
  350. package/dist/modules/billing/subscribers/payment-captured-to-paid.js +69 -33
  351. package/dist/modules/billing/subscribers/payment-captured-to-paid.js.map +2 -2
  352. package/dist/modules/billing/subscribers/prepaid-topup-captured.js +4 -6
  353. package/dist/modules/billing/subscribers/prepaid-topup-captured.js.map +2 -2
  354. package/dist/modules/billing/workers/reap-stale-bill-runs.js +2 -2
  355. package/dist/modules/billing/workers/reap-stale-bill-runs.js.map +2 -2
  356. package/generated/entities/billing_account/index.ts +26 -0
  357. package/generated/entities/billing_account_balance/index.ts +13 -0
  358. package/generated/entities/billing_account_transaction/index.ts +21 -0
  359. package/generated/entities/billing_account_usage/index.ts +18 -0
  360. package/generated/entities/billing_allocation/index.ts +18 -0
  361. package/generated/entities/billing_document_sequence/index.ts +11 -0
  362. package/generated/entities/billing_draft_invoice_edit/index.ts +14 -0
  363. package/generated/entities/billing_invoice/index.ts +38 -0
  364. package/generated/entities/billing_invoice_line/index.ts +24 -0
  365. package/generated/entities/billing_item/index.ts +26 -0
  366. package/generated/entities/billing_payment/index.ts +25 -0
  367. package/generated/entities/billing_payment_import/index.ts +14 -0
  368. package/generated/entities/billing_run/index.ts +20 -0
  369. package/generated/entities/billing_run_outcome/index.ts +18 -0
  370. package/generated/entities/billing_settings/index.ts +26 -0
  371. package/generated/entities/billing_statement/index.ts +22 -0
  372. package/generated/entities/billing_topup/index.ts +20 -0
  373. package/generated/entities.ids.generated.ts +35 -0
  374. package/package.json +15 -10
  375. package/src/modules/billing/__integration__/TC-BILL-004.spec.ts +170 -0
  376. package/src/modules/billing/__integration__/TC-BILL-005.spec.ts +134 -0
  377. package/src/modules/billing/__integration__/TC-BILL-006.spec.ts +101 -0
  378. package/src/modules/billing/__integration__/TC-BILL-007.spec.ts +140 -0
  379. package/src/modules/billing/__integration__/TC-BILL-008.spec.ts +108 -0
  380. package/src/modules/billing/__integration__/TC-BILL-009.spec.ts +113 -0
  381. package/src/modules/billing/__integration__/TC-BILL-010.spec.ts +118 -0
  382. package/src/modules/billing/__integration__/TC-BILL-011.spec.ts +142 -0
  383. package/src/modules/billing/__integration__/TC-BILL-012.spec.ts +115 -0
  384. package/src/modules/billing/__integration__/TC-BILL-013.spec.ts +118 -0
  385. package/src/modules/billing/__integration__/sellerSettings.ts +24 -0
  386. package/src/modules/billing/__tests__/commands/invoices.test.ts +437 -355
  387. package/src/modules/billing/__tests__/commands/itemsBulk.test.ts +33 -0
  388. package/src/modules/billing/__tests__/commands/memos.test.ts +205 -0
  389. package/src/modules/billing/__tests__/commands/payments.test.ts +241 -0
  390. package/src/modules/billing/__tests__/commands/runsDelete.test.ts +146 -0
  391. package/src/modules/billing/__tests__/commands/runsPostDrafts.test.ts +106 -0
  392. package/src/modules/billing/__tests__/commands/topups.test.ts +11 -0
  393. package/src/modules/billing/__tests__/entityRegistry.test.ts +326 -0
  394. package/src/modules/billing/__tests__/events.test.ts +142 -0
  395. package/src/modules/billing/__tests__/helpers/prepaidMockEm.ts +28 -11
  396. package/src/modules/billing/__tests__/lib/accountFinancials.test.ts +53 -0
  397. package/src/modules/billing/__tests__/lib/accountSummary.test.ts +97 -0
  398. package/src/modules/billing/__tests__/lib/allocation.test.ts +319 -0
  399. package/src/modules/billing/__tests__/lib/billRunEngine.test.ts +231 -20
  400. package/src/modules/billing/__tests__/lib/billingSettings.test.ts +109 -0
  401. package/src/modules/billing/__tests__/lib/customerLookup.test.ts +156 -0
  402. package/src/modules/billing/__tests__/lib/dueDate.test.ts +35 -0
  403. package/src/modules/billing/__tests__/lib/iban.test.ts +38 -0
  404. package/src/modules/billing/__tests__/lib/invoiceDelivery.test.ts +189 -0
  405. package/src/modules/billing/__tests__/lib/invoiceWriter.test.ts +212 -10
  406. package/src/modules/billing/__tests__/lib/itemBillingState.test.ts +42 -0
  407. package/src/modules/billing/__tests__/lib/itemPriceChange.test.ts +165 -0
  408. package/src/modules/billing/__tests__/lib/lineAmounts.test.ts +86 -0
  409. package/src/modules/billing/__tests__/lib/navigation.test.ts +71 -0
  410. package/src/modules/billing/__tests__/lib/numbering.test.ts +91 -0
  411. package/src/modules/billing/__tests__/lib/overdue.test.ts +36 -0
  412. package/src/modules/billing/__tests__/lib/paymentCsv.test.ts +148 -0
  413. package/src/modules/billing/__tests__/lib/paymentImport.test.ts +113 -0
  414. package/src/modules/billing/__tests__/lib/paymentsSample.test.ts +73 -0
  415. package/src/modules/billing/__tests__/lib/pdf/invoicePdf.test.ts +199 -0
  416. package/src/modules/billing/__tests__/lib/pdf/invoicePdfService.test.ts +147 -0
  417. package/src/modules/billing/__tests__/lib/prepaidPeriodClose.test.ts +374 -98
  418. package/src/modules/billing/__tests__/lib/prepaidTaxPoint.test.ts +118 -0
  419. package/src/modules/billing/__tests__/lib/seedsDemo.test.ts +53 -2
  420. package/src/modules/billing/__tests__/lib/sellerSettings.test.ts +28 -0
  421. package/src/modules/billing/__tests__/lib/servicePeriods.test.ts +190 -0
  422. package/src/modules/billing/__tests__/lib/topupCapture.test.ts +6 -28
  423. package/src/modules/billing/__tests__/lib/topupReceipt.test.ts +21 -52
  424. package/src/modules/billing/__tests__/lib/vat.test.ts +51 -0
  425. package/src/modules/billing/__tests__/package-isolation.test.ts +22 -8
  426. package/src/modules/billing/__tests__/setup.test.ts +13 -4
  427. package/src/modules/billing/__tests__/validators.test.ts +193 -3
  428. package/src/modules/billing/acl.ts +12 -0
  429. package/src/modules/billing/api/accounts/[id]/summary/route.ts +62 -0
  430. package/src/modules/billing/api/accounts/route.ts +58 -4
  431. package/src/modules/billing/api/export/account/[id]/route.ts +20 -18
  432. package/src/modules/billing/api/invoices/[id]/memos/route.ts +63 -0
  433. package/src/modules/billing/api/invoices/[id]/pdf/route.ts +79 -0
  434. package/src/modules/billing/api/invoices/[id]/route.ts +57 -70
  435. package/src/modules/billing/api/invoices/[id]/send/route.ts +127 -0
  436. package/src/modules/billing/api/invoices/add-line/route.ts +3 -3
  437. package/src/modules/billing/api/invoices/delete-draft/route.ts +33 -0
  438. package/src/modules/billing/api/invoices/edit-line/route.ts +4 -4
  439. package/src/modules/billing/api/invoices/post/route.ts +7 -6
  440. package/src/modules/billing/api/invoices/remove-line/route.ts +3 -3
  441. package/src/modules/billing/api/invoices/route.ts +81 -86
  442. package/src/modules/billing/api/items/bulk/route.ts +2 -1
  443. package/src/modules/billing/api/items/change-price/route.ts +54 -0
  444. package/src/modules/billing/api/items/route.ts +23 -7
  445. package/src/modules/billing/api/payment-imports/[id]/route.ts +49 -0
  446. package/src/modules/billing/api/payment-imports/route.ts +57 -0
  447. package/src/modules/billing/api/payments/[id]/route.ts +63 -0
  448. package/src/modules/billing/api/payments/allocate/route.ts +35 -0
  449. package/src/modules/billing/api/payments/assign/route.ts +36 -0
  450. package/src/modules/billing/api/payments/convert-to-topup/route.ts +35 -0
  451. package/src/modules/billing/api/payments/ignore/route.ts +35 -0
  452. package/src/modules/billing/api/payments/import/route.ts +72 -0
  453. package/src/modules/billing/api/payments/restore/route.ts +35 -0
  454. package/src/modules/billing/api/payments/route.ts +147 -0
  455. package/src/modules/billing/api/payments/unallocate/route.ts +35 -0
  456. package/src/modules/billing/api/payments/unassign/route.ts +35 -0
  457. package/src/modules/billing/api/run-outcomes/route.ts +50 -7
  458. package/src/modules/billing/api/runs/[id]/post-drafts/route.ts +71 -0
  459. package/src/modules/billing/api/runs/[id]/route.ts +59 -0
  460. package/src/modules/billing/api/runs/retry-failed/route.ts +4 -3
  461. package/src/modules/billing/api/runs/route.ts +17 -9
  462. package/src/modules/billing/api/settings/number-preview/route.ts +46 -0
  463. package/src/modules/billing/api/settings/route.ts +116 -0
  464. package/src/modules/billing/api/statements/route.ts +5 -0
  465. package/src/modules/billing/api/test-invoices/wipe/route.ts +2 -2
  466. package/src/modules/billing/backend/billing/accounts/[id]/page.tsx +151 -372
  467. package/src/modules/billing/backend/billing/accounts/create/page.tsx +6 -0
  468. package/src/modules/billing/backend/billing/accounts/page.tsx +71 -5
  469. package/src/modules/billing/backend/billing/invoices/[id]/page.tsx +445 -96
  470. package/src/modules/billing/backend/billing/invoices/page.tsx +8 -227
  471. package/src/modules/billing/backend/billing/items/[id]/page.tsx +75 -6
  472. package/src/modules/billing/backend/billing/items/create/page.tsx +13 -8
  473. package/src/modules/billing/backend/billing/items/page.tsx +19 -3
  474. package/src/modules/billing/backend/billing/payments/[id]/page.meta.ts +19 -0
  475. package/src/modules/billing/backend/billing/payments/[id]/page.tsx +415 -0
  476. package/src/modules/billing/backend/billing/payments/imports/[id]/page.meta.ts +19 -0
  477. package/src/modules/billing/backend/billing/payments/imports/[id]/page.tsx +106 -0
  478. package/src/modules/billing/backend/billing/payments/page.meta.ts +16 -0
  479. package/src/modules/billing/backend/billing/payments/page.tsx +56 -0
  480. package/src/modules/billing/backend/billing/runs/[id]/page.tsx +50 -19
  481. package/src/modules/billing/backend/billing/runs/page.tsx +60 -9
  482. package/src/modules/billing/backend/billing/statements/[id]/page.tsx +87 -6
  483. package/src/modules/billing/backend/billing/statements/page.tsx +2 -2
  484. package/src/modules/billing/backend/billing/topups/page.tsx +2 -2
  485. package/src/modules/billing/backend/billing/transactions/page.tsx +2 -2
  486. package/src/modules/billing/backend/billing/usage/create/page.tsx +3 -2
  487. package/src/modules/billing/backend/config/billing/page.meta.ts +21 -0
  488. package/src/modules/billing/backend/config/billing/page.tsx +549 -0
  489. package/src/modules/billing/ce.ts +8 -7
  490. package/src/modules/billing/cli.ts +31 -1
  491. package/src/modules/billing/commands/accounts.ts +6 -0
  492. package/src/modules/billing/commands/index.ts +3 -0
  493. package/src/modules/billing/commands/invoices.ts +371 -238
  494. package/src/modules/billing/commands/items.ts +143 -0
  495. package/src/modules/billing/commands/memos.ts +218 -0
  496. package/src/modules/billing/commands/payments.ts +428 -0
  497. package/src/modules/billing/commands/runs.ts +208 -6
  498. package/src/modules/billing/commands/settings.ts +77 -0
  499. package/src/modules/billing/commands/topups.ts +12 -3
  500. package/src/modules/billing/commands/transactions.ts +2 -2
  501. package/src/modules/billing/components/AccountForm.tsx +199 -53
  502. package/src/modules/billing/components/AccountInvoicesSection.tsx +75 -0
  503. package/src/modules/billing/components/AccountPaymentsSection.tsx +42 -0
  504. package/src/modules/billing/components/AccountPicker.tsx +70 -0
  505. package/src/modules/billing/components/AllocatePaymentDialog.tsx +167 -0
  506. package/src/modules/billing/components/BillingDataTable.tsx +34 -0
  507. package/src/modules/billing/components/BillingSettingsLink.tsx +25 -0
  508. package/src/modules/billing/components/ChangeItemPriceDialog.tsx +180 -0
  509. package/src/modules/billing/components/CreateMemoDialog.tsx +232 -0
  510. package/src/modules/billing/components/CustomerLabel.tsx +53 -0
  511. package/src/modules/billing/components/InvoicesTable.tsx +344 -0
  512. package/src/modules/billing/components/ItemForm.tsx +233 -44
  513. package/src/modules/billing/components/ItemPriceField.tsx +81 -0
  514. package/src/modules/billing/components/LineFormDialog.tsx +25 -1
  515. package/src/modules/billing/components/ManualPaymentDialog.tsx +140 -0
  516. package/src/modules/billing/components/MoneyInput.tsx +26 -0
  517. package/src/modules/billing/components/PaymentUploadDialog.tsx +148 -0
  518. package/src/modules/billing/components/PaymentsTable.tsx +213 -0
  519. package/src/modules/billing/components/PostRunDraftsButton.tsx +129 -0
  520. package/src/modules/billing/components/PrepaidPanel.tsx +20 -7
  521. package/src/modules/billing/components/RunCyclesSection.tsx +298 -0
  522. package/src/modules/billing/components/TestRunActions.tsx +152 -0
  523. package/src/modules/billing/components/account/AccountItemsTab.tsx +192 -0
  524. package/src/modules/billing/components/account/AccountRunBillingDialog.tsx +147 -0
  525. package/src/modules/billing/components/account/AccountRunsTab.tsx +201 -0
  526. package/src/modules/billing/components/account/AccountStatementsTab.tsx +120 -0
  527. package/src/modules/billing/components/account/AccountSummaryCards.tsx +153 -0
  528. package/src/modules/billing/components/account/AccountUsageTab.tsx +122 -0
  529. package/src/modules/billing/components/account/AccountView.tsx +101 -0
  530. package/src/modules/billing/components/account/accountRow.ts +70 -0
  531. package/src/modules/billing/components/customerNames.ts +62 -0
  532. package/src/modules/billing/data/entities.ts +685 -15
  533. package/src/modules/billing/data/entityIds.ts +25 -11
  534. package/src/modules/billing/data/validators.ts +388 -8
  535. package/src/modules/billing/events.ts +82 -3
  536. package/src/modules/billing/i18n/en.json +457 -21
  537. package/src/modules/billing/i18n/pl.json +457 -21
  538. package/src/modules/billing/index.ts +6 -2
  539. package/src/modules/billing/lib/accountFinancials.ts +84 -0
  540. package/src/modules/billing/lib/accountLock.ts +32 -0
  541. package/src/modules/billing/lib/accountStatus.ts +11 -9
  542. package/src/modules/billing/lib/accountSummary.ts +172 -0
  543. package/src/modules/billing/lib/allocation.ts +515 -0
  544. package/src/modules/billing/lib/allocationEvents.ts +26 -0
  545. package/src/modules/billing/lib/billPeriod.ts +19 -0
  546. package/src/modules/billing/lib/billRunEngine.ts +362 -162
  547. package/src/modules/billing/lib/billRunLabel.ts +1 -1
  548. package/src/modules/billing/lib/billingSettings.ts +145 -0
  549. package/src/modules/billing/lib/commandRoute.ts +112 -0
  550. package/src/modules/billing/lib/customerLookup.ts +157 -0
  551. package/src/modules/billing/lib/dateOnly.ts +22 -0
  552. package/src/modules/billing/lib/documentParties.ts +23 -0
  553. package/src/modules/billing/lib/documentTypes.ts +37 -0
  554. package/src/modules/billing/lib/dueDate.ts +26 -0
  555. package/src/modules/billing/lib/iban.ts +36 -0
  556. package/src/modules/billing/lib/invoiceDelivery.ts +197 -0
  557. package/src/modules/billing/lib/invoiceLanguages.ts +34 -0
  558. package/src/modules/billing/lib/invoiceWriter.ts +162 -148
  559. package/src/modules/billing/lib/itemBillingState.ts +67 -0
  560. package/src/modules/billing/lib/itemPriceChange.ts +56 -0
  561. package/src/modules/billing/lib/itemSelector.ts +4 -1
  562. package/src/modules/billing/lib/lineAmounts.ts +61 -0
  563. package/src/modules/billing/lib/memoGuards.ts +41 -0
  564. package/src/modules/billing/lib/navigation.ts +64 -0
  565. package/src/modules/billing/lib/numbering.ts +174 -0
  566. package/src/modules/billing/lib/overdue.ts +60 -0
  567. package/src/modules/billing/lib/paymentCsv.ts +171 -0
  568. package/src/modules/billing/lib/paymentGateway.ts +52 -0
  569. package/src/modules/billing/lib/paymentImport.ts +228 -0
  570. package/src/modules/billing/lib/paymentMatcher.ts +88 -0
  571. package/src/modules/billing/lib/pdf/attachmentStore.ts +60 -0
  572. package/src/modules/billing/lib/pdf/fonts/NotoSans-Bold.ttf +0 -0
  573. package/src/modules/billing/lib/pdf/fonts/NotoSans-Regular.ttf +0 -0
  574. package/src/modules/billing/lib/pdf/fonts/OFL.txt +93 -0
  575. package/src/modules/billing/lib/pdf/fonts/embeddedFonts.ts +9 -0
  576. package/src/modules/billing/lib/pdf/invoiceModel.ts +328 -0
  577. package/src/modules/billing/lib/pdf/invoicePdf.ts +216 -0
  578. package/src/modules/billing/lib/pdf/invoiceTemplate.ts +338 -0
  579. package/src/modules/billing/lib/prepaidConfig.ts +27 -36
  580. package/src/modules/billing/lib/prepaidConsume.ts +29 -6
  581. package/src/modules/billing/lib/prepaidPeriodClose.ts +410 -242
  582. package/src/modules/billing/lib/prepaidTaxPoint.ts +76 -0
  583. package/src/modules/billing/lib/seeds/demo.ts +79 -6
  584. package/src/modules/billing/lib/seeds/paymentsSample.ts +136 -0
  585. package/src/modules/billing/lib/seeds/sellerSettings.ts +78 -0
  586. package/src/modules/billing/lib/servicePeriods.ts +226 -0
  587. package/src/modules/billing/lib/tenantLock.ts +1 -1
  588. package/src/modules/billing/lib/testRunCleanup.ts +42 -0
  589. package/src/modules/billing/lib/topupCapture.ts +3 -4
  590. package/src/modules/billing/lib/topupReceipt.ts +70 -103
  591. package/src/modules/billing/lib/usageRater.ts +1 -1
  592. package/src/modules/billing/lib/usageRunner.ts +17 -5
  593. package/src/modules/billing/lib/vat.ts +56 -0
  594. package/src/modules/billing/migrations/Migration20261114000000_billing_customer_kind.ts +25 -0
  595. package/src/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.ts +37 -0
  596. package/src/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.ts +132 -0
  597. package/src/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.ts +58 -0
  598. package/src/modules/billing/migrations/Migration20261117000000_billing_payments.ts +97 -0
  599. package/src/modules/billing/migrations/Migration20261118000000_billing_memos.ts +21 -0
  600. package/src/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.ts +39 -0
  601. package/src/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.ts +35 -0
  602. package/src/modules/billing/setup.ts +11 -237
  603. package/src/modules/billing/subscribers/credit-memo-auto-send.ts +15 -0
  604. package/src/modules/billing/subscribers/debit-memo-apply-credit.ts +15 -0
  605. package/src/modules/billing/subscribers/debit-memo-auto-send.ts +15 -0
  606. package/src/modules/billing/subscribers/invoice-apply-credit.ts +39 -0
  607. package/src/modules/billing/subscribers/invoice-auto-send.ts +46 -0
  608. package/src/modules/billing/subscribers/payment-captured-to-paid.ts +84 -62
  609. package/src/modules/billing/subscribers/prepaid-topup-captured.ts +4 -8
  610. package/src/modules/billing/workers/reap-stale-bill-runs.ts +4 -4
  611. package/dist/modules/billing/lib/invoiceStatus.js +0 -38
  612. package/dist/modules/billing/lib/invoiceStatus.js.map +0 -7
  613. package/src/modules/billing/__tests__/lib/invoiceStatus.test.ts +0 -97
  614. package/src/modules/billing/lib/invoiceStatus.ts +0 -61
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/billing/api/items/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { BillingAccount, BillingItem } from '../../data/entities'\nimport { billingEntityIds } from '../../data/entityIds'\nimport {\n billingItemCreateSchema,\n billingItemListQuerySchema,\n billingItemUpdateSchema,\n} from '../../data/validators'\nimport {\n createBillingCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\n\n// \u2500\u2500\u2500 Auth / RBAC \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['billing.item.view'] },\n POST: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n}\n\nexport const metadata = routeMetadata\n\n// The list endpoint projects raw column names \u2014 snake_case.\nconst billingItemListItemSchema = z.object({\n id: z.string().uuid(),\n bill_account_id: z.string().uuid(),\n bill_account_name: z.string().nullable(),\n type: z.string(),\n bill_start_date: z.string(),\n bill_end_date: z.string().nullable(),\n description: z.string(),\n rate_json: z.record(z.string(), z.unknown()),\n uom_code: z.string().nullable(),\n subscription_id: z.string().nullable(),\n subscription_item_id: z.string().nullable(),\n source_ref: z.string().nullable(),\n currency_mismatch: z.boolean(),\n billed_to_date: z.string().nullable(),\n is_active: z.boolean(),\n organization_id: z.string().uuid(),\n tenant_id: z.string().uuid(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\n// Response for create includes `deduplicated` so integrators can tell\n// whether their POST resulted in a new row or hit the idempotency\n// short-circuit on `source_ref`.\nconst itemCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n deduplicated: z.boolean(),\n})\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: BillingItem,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n list: {\n schema: billingItemListQuerySchema,\n entityId: billingEntityIds.item,\n fields: [\n 'id',\n 'bill_account_id',\n 'type',\n 'bill_start_date',\n 'bill_end_date',\n 'description',\n 'rate_json',\n 'uom_code',\n 'subscription_id',\n 'subscription_item_id',\n 'source_ref',\n 'currency_mismatch',\n 'billed_to_date',\n 'is_active',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n ],\n sortFieldMap: {\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n billStartDate: 'bill_start_date',\n billEndDate: 'bill_end_date',\n },\n buildFilters: async (query) => {\n const filters: Record<string, unknown> = {}\n // `?id=<uuid>` narrows the list to one row \u2014 the detail page\n // reads a single item through this filter.\n if (typeof query.id === 'string' && query.id) {\n filters.id = { $eq: query.id }\n }\n if (typeof query.search === 'string' && query.search.trim()) {\n const pattern = `%${query.search.trim().replace(/[%_]/g, (m) => `\\\\${m}`)}%`\n filters.description = { $ilike: pattern }\n }\n if (typeof query.billAccountId === 'string' && query.billAccountId) {\n filters.bill_account_id = { $eq: query.billAccountId }\n }\n if (typeof query.type === 'string' && query.type) {\n filters.type = { $eq: query.type }\n }\n if (typeof query.subscriptionId === 'string' && query.subscriptionId) {\n filters.subscription_id = { $eq: query.subscriptionId }\n }\n if (typeof query.isActive === 'boolean') {\n filters.is_active = { $eq: query.isActive }\n }\n // `activeAt=<date>` returns items whose validity window covers\n // the supplied date (Bill Run engine uses the same predicate\n // shape internally \u2014 see spec \"Mid-cycle recurring items\").\n if (query.activeAt instanceof Date) {\n filters.bill_start_date = { $lte: query.activeAt }\n filters.$or = [\n { bill_end_date: null },\n { bill_end_date: { $gte: query.activeAt } },\n ]\n }\n return filters\n },\n },\n actions: {\n create: {\n commandId: 'billing.items.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n return billingItemCreateSchema.parse(scoped)\n },\n response: ({ result }) => ({\n id: result?.id ?? null,\n deduplicated: Boolean(result?.deduplicated),\n }),\n // Idempotent create returns 200 (vs 201). The spec mandates\n // duplicate POST returns the existing row, never creates a\n // duplicate \u2014 keeping the success status consistent makes\n // client-side handling trivial.\n status: 200,\n },\n update: {\n commandId: 'billing.items.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n return billingItemUpdateSchema.parse(scoped)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'billing.items.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n // The factory hands delete a `{ body, query }` envelope \u2014 the\n // id may arrive in either, depending on the caller.\n const envelope = (raw ?? {}) as {\n body?: Record<string, unknown>\n query?: Record<string, unknown>\n }\n const body = envelope.body ?? {}\n const query = envelope.query ?? {}\n const scoped = withScopedPayload(body, ctx, translate)\n const id =\n (typeof body.id === 'string' && body.id) ||\n (typeof query.id === 'string' && query.id) ||\n null\n if (!id) {\n throw new Error('id is required')\n }\n return {\n id,\n tenantId: (scoped as { tenantId?: string }).tenantId,\n organizationId: (scoped as { organizationId?: string }).organizationId,\n }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n // Items reference their account by FK id only; the list + detail UI\n // wants the human-readable account name. One bounded query\n // (\u2264 pageSize ids) resolves it after the page is fetched.\n afterList: async (payload: unknown, ctx: unknown) => {\n const items = ((payload as { items?: unknown[] } | null)?.items ?? []) as Array<\n Record<string, unknown>\n >\n const accountIds = Array.from(\n new Set(\n items\n .map((row) => row.bill_account_id)\n .filter((v): v is string => typeof v === 'string' && v.length > 0),\n ),\n )\n if (accountIds.length === 0) return\n const em = (ctx as { container: AwilixContainer }).container.resolve<EntityManager>('em')\n const accounts = await em.find(BillingAccount, { id: { $in: accountIds } })\n const nameById = new Map(\n accounts.map((a) => [String(a.id), a.name] as [string, unknown]),\n )\n for (const row of items) {\n row.bill_account_name = nameById.get(String(row.bill_account_id)) ?? null\n }\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nexport const openApi = createBillingCrudOpenApi({\n resourceName: 'BillingItem',\n pluralName: 'BillingItems',\n querySchema: billingItemListQuerySchema,\n listResponseSchema: createPagedListResponseSchema(billingItemListItemSchema),\n create: {\n schema: billingItemCreateSchema,\n responseSchema: itemCreateResponseSchema,\n description:\n 'Creates a billing item. Idempotent via `sourceRef`: re-POSTing the same ' +\n '`(tenantId, billAccountId, sourceRef)` returns the existing row with ' +\n '`deduplicated: true` instead of creating a duplicate. The unique index ' +\n 'on `(tenant_id, bill_account_id, source_ref)` is the correctness gate.',\n },\n update: {\n schema: billingItemUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description:\n 'Updates a billing item. `type` and `sourceRef` are immutable \u2014 to change ' +\n 'either, soft-delete the item and create a new one.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Soft-deletes a billing item.',\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { BillingAccount, BillingItem } from '../../data/entities'\nimport { billingEntityIds } from '../../data/entityIds'\nimport {\n billingItemCreateSchema,\n billingItemListQuerySchema,\n billingItemUpdateSchema,\n} from '../../data/validators'\nimport {\n createBillingCrudOpenApi,\n createPagedListResponseSchema,\n defaultOkResponseSchema,\n} from '../openapi'\n\n// \u2500\u2500\u2500 Auth / RBAC \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['billing.item.view'] },\n POST: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['billing.item.manage'] },\n}\n\nexport const metadata = routeMetadata\n\n// The list endpoint projects raw column names \u2014 snake_case.\nconst billingItemListItemSchema = z.object({\n id: z.string().uuid(),\n bill_account_id: z.string().uuid(),\n bill_account_name: z.string().nullable(),\n /** Spec F (F2): the owning account's currency and mode, for the form. */\n bill_account_currency: z.string().nullable(),\n bill_account_mode: z.enum(['postpaid', 'prepaid']).nullable(),\n type: z.string(),\n bill_start_date: z.string(),\n bill_end_date: z.string().nullable(),\n description: z.string(),\n rate_json: z.record(z.string(), z.unknown()),\n uom_code: z.string().nullable(),\n subscription_id: z.string().nullable(),\n subscription_item_id: z.string().nullable(),\n source_ref: z.string().nullable(),\n currency_mismatch: z.boolean(),\n billed_to_date: z.string().nullable(),\n charge_timing: z.enum(['in_advance', 'in_arrears']),\n prorate: z.boolean(),\n tax_rate: z.union([z.string(), z.number()]),\n price_basis: z.enum(['net', 'gross']),\n is_active: z.boolean(),\n organization_id: z.string().uuid(),\n tenant_id: z.string().uuid(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\n// Response for create includes `deduplicated` so integrators can tell\n// whether their POST resulted in a new row or hit the idempotency\n// short-circuit on `source_ref`.\nconst itemCreateResponseSchema = z.object({\n id: z.string().uuid().nullable(),\n deduplicated: z.boolean(),\n})\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: BillingItem,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n list: {\n schema: billingItemListQuerySchema,\n entityId: billingEntityIds.item,\n fields: [\n 'id',\n 'bill_account_id',\n 'type',\n 'bill_start_date',\n 'bill_end_date',\n 'description',\n 'rate_json',\n 'uom_code',\n 'subscription_id',\n 'subscription_item_id',\n 'source_ref',\n 'currency_mismatch',\n 'billed_to_date',\n 'charge_timing',\n 'prorate',\n 'tax_rate',\n 'price_basis',\n 'is_active',\n 'organization_id',\n 'tenant_id',\n 'created_at',\n 'updated_at',\n ],\n sortFieldMap: {\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n billStartDate: 'bill_start_date',\n billEndDate: 'bill_end_date',\n },\n buildFilters: async (query) => {\n const filters: Record<string, unknown> = {}\n // `?id=<uuid>` narrows the list to one row \u2014 the detail page\n // reads a single item through this filter.\n if (typeof query.id === 'string' && query.id) {\n filters.id = { $eq: query.id }\n }\n if (typeof query.search === 'string' && query.search.trim()) {\n const pattern = `%${query.search.trim().replace(/[%_]/g, (m) => `\\\\${m}`)}%`\n filters.description = { $ilike: pattern }\n }\n if (typeof query.billAccountId === 'string' && query.billAccountId) {\n filters.bill_account_id = { $eq: query.billAccountId }\n }\n if (typeof query.type === 'string' && query.type) {\n filters.type = { $eq: query.type }\n }\n if (typeof query.subscriptionId === 'string' && query.subscriptionId) {\n filters.subscription_id = { $eq: query.subscriptionId }\n }\n if (typeof query.isActive === 'boolean') {\n filters.is_active = { $eq: query.isActive }\n }\n // `activeAt=<date>` returns items whose validity window covers\n // the supplied date (Bill Run engine uses the same predicate\n // shape internally \u2014 see spec \"Mid-cycle recurring items\").\n if (query.activeAt instanceof Date) {\n filters.bill_start_date = { $lte: query.activeAt }\n filters.$or = [\n { bill_end_date: null },\n { bill_end_date: { $gte: query.activeAt } },\n ]\n }\n return filters\n },\n },\n actions: {\n create: {\n commandId: 'billing.items.create',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n return billingItemCreateSchema.parse(scoped)\n },\n response: ({ result }) => ({\n id: result?.id ?? null,\n deduplicated: Boolean(result?.deduplicated),\n }),\n // Idempotent create returns 200 (vs 201). The spec mandates\n // duplicate POST returns the existing row, never creates a\n // duplicate \u2014 keeping the success status consistent makes\n // client-side handling trivial.\n status: 200,\n },\n update: {\n commandId: 'billing.items.update',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const scoped = withScopedPayload(raw ?? {}, ctx, translate)\n return billingItemUpdateSchema.parse(scoped)\n },\n response: () => ({ ok: true }),\n },\n delete: {\n commandId: 'billing.items.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n // The factory hands delete a `{ body, query }` envelope \u2014 the\n // id may arrive in either, depending on the caller.\n const envelope = (raw ?? {}) as {\n body?: Record<string, unknown>\n query?: Record<string, unknown>\n }\n const body = envelope.body ?? {}\n const query = envelope.query ?? {}\n const scoped = withScopedPayload(body, ctx, translate)\n const id =\n (typeof body.id === 'string' && body.id) ||\n (typeof query.id === 'string' && query.id) ||\n null\n if (!id) {\n throw new Error('id is required')\n }\n return {\n id,\n tenantId: (scoped as { tenantId?: string }).tenantId,\n organizationId: (scoped as { organizationId?: string }).organizationId,\n }\n },\n response: () => ({ ok: true }),\n },\n },\n hooks: {\n // Items reference their account by FK id only; the list + detail UI\n // wants the account name, currency and mode. One bounded query\n // (\u2264 pageSize ids) resolves it after the page is fetched.\n afterList: async (payload: unknown, ctx: unknown) => {\n const items = ((payload as { items?: unknown[] } | null)?.items ?? []) as Array<\n Record<string, unknown>\n >\n const accountIds = Array.from(\n new Set(\n items\n .map((row) => row.bill_account_id)\n .filter((v): v is string => typeof v === 'string' && v.length > 0),\n ),\n )\n if (accountIds.length === 0) return\n const em = (ctx as { container: AwilixContainer }).container.resolve<EntityManager>('em')\n const accounts = await em.find(BillingAccount, { id: { $in: accountIds } })\n const byId = new Map(accounts.map((a) => [String(a.id), a] as const))\n for (const row of items) {\n const account = byId.get(String(row.bill_account_id))\n row.bill_account_name = account?.name ?? null\n row.bill_account_currency = account?.currencyCode ?? null\n row.bill_account_mode = account?.billingMode ?? null\n }\n },\n },\n})\n\nconst { POST, PUT, DELETE } = crud\nexport { POST, PUT, DELETE }\nexport const GET = crud.GET\n\nexport const openApi = createBillingCrudOpenApi({\n resourceName: 'BillingItem',\n pluralName: 'BillingItems',\n querySchema: billingItemListQuerySchema,\n listResponseSchema: createPagedListResponseSchema(billingItemListItemSchema),\n create: {\n schema: billingItemCreateSchema,\n responseSchema: itemCreateResponseSchema,\n description:\n 'Creates a billing item. Idempotent via `sourceRef`: re-POSTing the same ' +\n '`(tenantId, billAccountId, sourceRef)` returns the existing row with ' +\n '`deduplicated: true` instead of creating a duplicate. The unique index ' +\n 'on `(tenant_id, bill_account_id, source_ref)` is the correctness gate. ' +\n 'Recurring items accept `chargeTiming` (`in_advance` default | `in_arrears`) and ' +\n '`prorate` (default true); other types reject non-default values (400).',\n },\n update: {\n schema: billingItemUpdateSchema,\n responseSchema: defaultOkResponseSchema,\n description:\n 'Updates a billing item. `type` and `sourceRef` are immutable \u2014 to change ' +\n 'either, soft-delete the item and create a new one. `chargeTiming` / `prorate` ' +\n 'may change at any time on recurring items \u2014 billing resumes from `billed_to_date`, ' +\n 'so no day is billed twice.',\n },\n del: {\n schema: z.object({ id: z.string().uuid() }),\n responseSchema: defaultOkResponseSchema,\n description: 'Soft-deletes a billing item.',\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,49 @@
1
+ import { NextResponse } from "next/server";
2
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import {
5
+ organizationScopeRequiredResponse,
6
+ resolveActiveOrganizationId
7
+ } from "@open-mercato/shared/lib/auth/organizationScope";
8
+ const metadata = {
9
+ GET: { requireAuth: true, requireFeatures: ["billing.payment.view"] }
10
+ };
11
+ async function GET(req, { params }) {
12
+ try {
13
+ const container = await createRequestContainer();
14
+ const auth = await getAuthFromRequest(req);
15
+ if (!auth || !auth.tenantId) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
16
+ const organizationId = resolveActiveOrganizationId(auth);
17
+ if (!organizationId) return organizationScopeRequiredResponse();
18
+ const { id } = await params;
19
+ const em = container.resolve("em").fork();
20
+ const rows = await em.execute(
21
+ `SELECT id, file_name, row_count, counts, errors, user_id, created_at
22
+ FROM billing_payment_imports
23
+ WHERE id = ? AND tenant_id = ? AND organization_id = ? AND deleted_at IS NULL`,
24
+ [id, auth.tenantId, organizationId]
25
+ );
26
+ if (!rows?.length) return NextResponse.json({ error: "Import not found" }, { status: 404 });
27
+ return NextResponse.json({ import: rows[0] });
28
+ } catch (err) {
29
+ console.error("[billing/payment-imports/[id].GET]", err);
30
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
31
+ }
32
+ }
33
+ const openApi = {
34
+ methods: {
35
+ GET: {
36
+ tags: ["Billing"],
37
+ summary: "Get a payment import batch",
38
+ description: "Counts per outcome and the row errors (line number + message, capped at 200).",
39
+ responses: [{ status: 200, description: "`{ import }`" }],
40
+ errors: [{ status: 404, description: "Import not found" }]
41
+ }
42
+ }
43
+ };
44
+ export {
45
+ GET,
46
+ metadata,
47
+ openApi
48
+ };
49
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payment-imports/%5Bid%5D/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport {\n organizationScopeRequiredResponse,\n resolveActiveOrganizationId,\n} from '@open-mercato/shared/lib/auth/organizationScope'\n\n/** `GET /api/billing/payment-imports/[id]` \u2014 one upload batch with its row errors (Spec C). */\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['billing.payment.view'] },\n}\n\nexport async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) {\n try {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) return organizationScopeRequiredResponse()\n const { id } = await params\n const em = (container.resolve('em') as EntityManager).fork()\n const rows = (await em.execute(\n `SELECT id, file_name, row_count, counts, errors, user_id, created_at\n FROM billing_payment_imports\n WHERE id = ? AND tenant_id = ? AND organization_id = ? AND deleted_at IS NULL`,\n [id, auth.tenantId, organizationId],\n )) as unknown as Array<Record<string, unknown>>\n if (!rows?.length) return NextResponse.json({ error: 'Import not found' }, { status: 404 })\n return NextResponse.json({ import: rows[0] })\n } catch (err) {\n console.error('[billing/payment-imports/[id].GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport const openApi = {\n methods: {\n GET: {\n tags: ['Billing'],\n summary: 'Get a payment import batch',\n description: 'Counts per outcome and the row errors (line number + message, capped at 200).',\n responses: [{ status: 200, description: '`{ import }`' }],\n errors: [{ status: 404, description: 'Import not found' }],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAIA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,sBAAsB,EAAE;AACtE;AAEA,eAAsB,IAAI,KAAc,EAAE,OAAO,GAAwC;AACvF,MAAI;AACF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,QAAI,CAAC,QAAQ,CAAC,KAAK,SAAU,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAChG,UAAM,iBAAiB,4BAA4B,IAAI;AACvD,QAAI,CAAC,eAAgB,QAAO,kCAAkC;AAC9D,UAAM,EAAE,GAAG,IAAI,MAAM;AACrB,UAAM,KAAM,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC3D,UAAM,OAAQ,MAAM,GAAG;AAAA,MACrB;AAAA;AAAA;AAAA,MAGA,CAAC,IAAI,KAAK,UAAU,cAAc;AAAA,IACpC;AACA,QAAI,CAAC,MAAM,OAAQ,QAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAC1F,WAAO,aAAa,KAAK,EAAE,QAAQ,KAAK,CAAC,EAAE,CAAC;AAAA,EAC9C,SAAS,KAAK;AACZ,YAAQ,MAAM,sCAAsC,GAAG;AACvD,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,KAAK;AAAA,MACH,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,eAAe,CAAC;AAAA,MACxD,QAAQ,CAAC,EAAE,QAAQ,KAAK,aAAa,mBAAmB,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,57 @@
1
+ import { NextResponse } from "next/server";
2
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import {
5
+ organizationScopeRequiredResponse,
6
+ resolveActiveOrganizationId
7
+ } from "@open-mercato/shared/lib/auth/organizationScope";
8
+ import { buildQueryParams } from "@open-mercato/shared/lib/crud/query-params";
9
+ import { billingPaymentImportListQuerySchema } from "../../data/validators.js";
10
+ const metadata = {
11
+ GET: { requireAuth: true, requireFeatures: ["billing.payment.view"] }
12
+ };
13
+ async function GET(req) {
14
+ try {
15
+ const container = await createRequestContainer();
16
+ const auth = await getAuthFromRequest(req);
17
+ if (!auth || !auth.tenantId) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
18
+ const organizationId = resolveActiveOrganizationId(auth);
19
+ if (!organizationId) return organizationScopeRequiredResponse();
20
+ const query = billingPaymentImportListQuerySchema.parse(buildQueryParams(new URL(req.url).searchParams));
21
+ const em = container.resolve("em").fork();
22
+ const where = ["tenant_id = ?", "organization_id = ?", "deleted_at IS NULL"];
23
+ const params = [auth.tenantId, organizationId];
24
+ if (query.id) {
25
+ where.push("id = ?");
26
+ params.push(query.id);
27
+ }
28
+ const totalRows = await em.execute(`SELECT COUNT(*)::int AS total FROM billing_payment_imports WHERE ${where.join(" AND ")}`, params);
29
+ const total = totalRows?.[0]?.total ?? 0;
30
+ const items = await em.execute(
31
+ `SELECT id, file_name, row_count, counts, user_id, created_at
32
+ FROM billing_payment_imports WHERE ${where.join(" AND ")}
33
+ ORDER BY created_at DESC LIMIT ? OFFSET ?`,
34
+ [...params, query.pageSize, (query.page - 1) * query.pageSize]
35
+ );
36
+ return NextResponse.json({ items, total, page: query.page, pageSize: query.pageSize, totalPages: total === 0 ? 1 : Math.ceil(total / query.pageSize) });
37
+ } catch (err) {
38
+ console.error("[billing/payment-imports.GET]", err);
39
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
40
+ }
41
+ }
42
+ const openApi = {
43
+ methods: {
44
+ GET: {
45
+ tags: ["Billing"],
46
+ summary: "List payment import batches",
47
+ description: "CSV uploads with counts per outcome (allocated, partially_allocated, matched, unmatched, duplicate, rejected).",
48
+ query: billingPaymentImportListQuerySchema
49
+ }
50
+ }
51
+ };
52
+ export {
53
+ GET,
54
+ metadata,
55
+ openApi
56
+ };
57
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/billing/api/payment-imports/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport {\n organizationScopeRequiredResponse,\n resolveActiveOrganizationId,\n} from '@open-mercato/shared/lib/auth/organizationScope'\nimport { buildQueryParams } from '@open-mercato/shared/lib/crud/query-params'\nimport { billingPaymentImportListQuerySchema } from '../../data/validators'\n\n/** `GET /api/billing/payment-imports` \u2014 CSV upload batches, newest first (Spec C, C-D4). */\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['billing.payment.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) return organizationScopeRequiredResponse()\n const query = billingPaymentImportListQuerySchema.parse(buildQueryParams(new URL(req.url).searchParams))\n const em = (container.resolve('em') as EntityManager).fork()\n const where = ['tenant_id = ?', 'organization_id = ?', 'deleted_at IS NULL']\n const params: unknown[] = [auth.tenantId, organizationId]\n if (query.id) {\n where.push('id = ?')\n params.push(query.id)\n }\n const totalRows = (await em.execute(`SELECT COUNT(*)::int AS total FROM billing_payment_imports WHERE ${where.join(' AND ')}`, params)) as unknown as Array<{ total: number }>\n const total = totalRows?.[0]?.total ?? 0\n const items = await em.execute(\n `SELECT id, file_name, row_count, counts, user_id, created_at\n FROM billing_payment_imports WHERE ${where.join(' AND ')}\n ORDER BY created_at DESC LIMIT ? OFFSET ?`,\n [...params, query.pageSize, (query.page - 1) * query.pageSize],\n )\n return NextResponse.json({ items, total, page: query.page, pageSize: query.pageSize, totalPages: total === 0 ? 1 : Math.ceil(total / query.pageSize) })\n } catch (err) {\n console.error('[billing/payment-imports.GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport const openApi = {\n methods: {\n GET: {\n tags: ['Billing'],\n summary: 'List payment import batches',\n description: 'CSV uploads with counts per outcome (allocated, partially_allocated, matched, unmatched, duplicate, rejected).',\n query: billingPaymentImportListQuerySchema,\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;AACjC,SAAS,2CAA2C;AAI7C,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,sBAAsB,EAAE;AACtE;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,QAAI,CAAC,QAAQ,CAAC,KAAK,SAAU,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAChG,UAAM,iBAAiB,4BAA4B,IAAI;AACvD,QAAI,CAAC,eAAgB,QAAO,kCAAkC;AAC9D,UAAM,QAAQ,oCAAoC,MAAM,iBAAiB,IAAI,IAAI,IAAI,GAAG,EAAE,YAAY,CAAC;AACvG,UAAM,KAAM,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC3D,UAAM,QAAQ,CAAC,iBAAiB,uBAAuB,oBAAoB;AAC3E,UAAM,SAAoB,CAAC,KAAK,UAAU,cAAc;AACxD,QAAI,MAAM,IAAI;AACZ,YAAM,KAAK,QAAQ;AACnB,aAAO,KAAK,MAAM,EAAE;AAAA,IACtB;AACA,UAAM,YAAa,MAAM,GAAG,QAAQ,oEAAoE,MAAM,KAAK,OAAO,CAAC,IAAI,MAAM;AACrI,UAAM,QAAQ,YAAY,CAAC,GAAG,SAAS;AACvC,UAAM,QAAQ,MAAM,GAAG;AAAA,MACrB;AAAA,8CACwC,MAAM,KAAK,OAAO,CAAC;AAAA;AAAA,MAE3D,CAAC,GAAG,QAAQ,MAAM,WAAW,MAAM,OAAO,KAAK,MAAM,QAAQ;AAAA,IAC/D;AACA,WAAO,aAAa,KAAK,EAAE,OAAO,OAAO,MAAM,MAAM,MAAM,UAAU,MAAM,UAAU,YAAY,UAAU,IAAI,IAAI,KAAK,KAAK,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAAA,EACxJ,SAAS,KAAK;AACZ,YAAQ,MAAM,iCAAiC,GAAG;AAClD,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,KAAK;AAAA,MACH,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO;AAAA,IACT;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,60 @@
1
+ import { NextResponse } from "next/server";
2
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import {
5
+ organizationScopeRequiredResponse,
6
+ resolveActiveOrganizationId
7
+ } from "@open-mercato/shared/lib/auth/organizationScope";
8
+ const metadata = {
9
+ GET: { requireAuth: true, requireFeatures: ["billing.payment.view"] }
10
+ };
11
+ async function GET(req, { params }) {
12
+ try {
13
+ const container = await createRequestContainer();
14
+ const auth = await getAuthFromRequest(req);
15
+ if (!auth || !auth.tenantId) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
16
+ const organizationId = resolveActiveOrganizationId(auth);
17
+ if (!organizationId) return organizationScopeRequiredResponse();
18
+ const { id } = await params;
19
+ const em = container.resolve("em").fork();
20
+ const rows = await em.execute(
21
+ `SELECT p.*, a.name AS bill_account_name, a.billing_mode AS bill_account_mode
22
+ FROM billing_payments p
23
+ LEFT JOIN billing_accounts a ON a.id = p.bill_account_id AND a.tenant_id = p.tenant_id
24
+ WHERE p.id = ? AND p.tenant_id = ? AND p.organization_id = ? AND p.deleted_at IS NULL`,
25
+ [id, auth.tenantId, organizationId]
26
+ );
27
+ if (!rows?.length) return NextResponse.json({ error: "Payment not found" }, { status: 404 });
28
+ const allocations = await em.execute(
29
+ `SELECT al.id, al.invoice_id, i.number AS invoice_number, i.document_type, i.status AS invoice_status,
30
+ al.amount, al.currency_code, al.allocated_by, al.user_id, al.created_at
31
+ FROM billing_allocations al
32
+ LEFT JOIN billing_invoices i ON i.id = al.invoice_id
33
+ WHERE al.source_type = 'payment' AND al.source_id = ? AND al.tenant_id = ? AND al.organization_id = ?
34
+ AND al.deleted_at IS NULL
35
+ ORDER BY al.created_at ASC`,
36
+ [id, auth.tenantId, organizationId]
37
+ );
38
+ return NextResponse.json({ payment: rows[0], allocations });
39
+ } catch (err) {
40
+ console.error("[billing/payments/[id].GET]", err);
41
+ return NextResponse.json({ error: "Internal error" }, { status: 500 });
42
+ }
43
+ }
44
+ const openApi = {
45
+ methods: {
46
+ GET: {
47
+ tags: ["Billing"],
48
+ summary: "Get a billing payment",
49
+ description: "The payment (incl. match reason, account, top-up link) and its active allocations.",
50
+ responses: [{ status: 200, description: "`{ payment, allocations[] }`" }],
51
+ errors: [{ status: 404, description: "Payment not found in this organization" }]
52
+ }
53
+ }
54
+ };
55
+ export {
56
+ GET,
57
+ metadata,
58
+ openApi
59
+ };
60
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/%5Bid%5D/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport {\n organizationScopeRequiredResponse,\n resolveActiveOrganizationId,\n} from '@open-mercato/shared/lib/auth/organizationScope'\n\n/**\n * `GET /api/billing/payments/[id]` \u2014 one payment with its active\n * allocations (invoice number, amount, who / how allocated) \u2014 Spec C.\n */\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['billing.payment.view'] },\n}\n\nexport async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) {\n try {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) return organizationScopeRequiredResponse()\n const { id } = await params\n const em = (container.resolve('em') as EntityManager).fork()\n const rows = (await em.execute(\n `SELECT p.*, a.name AS bill_account_name, a.billing_mode AS bill_account_mode\n FROM billing_payments p\n LEFT JOIN billing_accounts a ON a.id = p.bill_account_id AND a.tenant_id = p.tenant_id\n WHERE p.id = ? AND p.tenant_id = ? AND p.organization_id = ? AND p.deleted_at IS NULL`,\n [id, auth.tenantId, organizationId],\n )) as unknown as Array<Record<string, unknown>>\n if (!rows?.length) return NextResponse.json({ error: 'Payment not found' }, { status: 404 })\n const allocations = await em.execute(\n `SELECT al.id, al.invoice_id, i.number AS invoice_number, i.document_type, i.status AS invoice_status,\n al.amount, al.currency_code, al.allocated_by, al.user_id, al.created_at\n FROM billing_allocations al\n LEFT JOIN billing_invoices i ON i.id = al.invoice_id\n WHERE al.source_type = 'payment' AND al.source_id = ? AND al.tenant_id = ? AND al.organization_id = ?\n AND al.deleted_at IS NULL\n ORDER BY al.created_at ASC`,\n [id, auth.tenantId, organizationId],\n )\n return NextResponse.json({ payment: rows[0], allocations })\n } catch (err) {\n console.error('[billing/payments/[id].GET]', err)\n return NextResponse.json({ error: 'Internal error' }, { status: 500 })\n }\n}\n\nexport const openApi = {\n methods: {\n GET: {\n tags: ['Billing'],\n summary: 'Get a billing payment',\n description: 'The payment (incl. match reason, account, top-up link) and its active allocations.',\n responses: [{ status: 200, description: '`{ payment, allocations[] }`' }],\n errors: [{ status: 404, description: 'Payment not found in this organization' }],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,8BAA8B;AACvC,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAOA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,sBAAsB,EAAE;AACtE;AAEA,eAAsB,IAAI,KAAc,EAAE,OAAO,GAAwC;AACvF,MAAI;AACF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,QAAI,CAAC,QAAQ,CAAC,KAAK,SAAU,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAChG,UAAM,iBAAiB,4BAA4B,IAAI;AACvD,QAAI,CAAC,eAAgB,QAAO,kCAAkC;AAC9D,UAAM,EAAE,GAAG,IAAI,MAAM;AACrB,UAAM,KAAM,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC3D,UAAM,OAAQ,MAAM,GAAG;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA,MAIA,CAAC,IAAI,KAAK,UAAU,cAAc;AAAA,IACpC;AACA,QAAI,CAAC,MAAM,OAAQ,QAAO,aAAa,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAC3F,UAAM,cAAc,MAAM,GAAG;AAAA,MAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,CAAC,IAAI,KAAK,UAAU,cAAc;AAAA,IACpC;AACA,WAAO,aAAa,KAAK,EAAE,SAAS,KAAK,CAAC,GAAG,YAAY,CAAC;AAAA,EAC5D,SAAS,KAAK;AACZ,YAAQ,MAAM,+BAA+B,GAAG;AAChD,WAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvE;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,KAAK;AAAA,MACH,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,+BAA+B,CAAC;AAAA,MACxE,QAAQ,CAAC,EAAE,QAAQ,KAAK,aAAa,yCAAyC,CAAC;AAAA,IACjF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { runCommandRoute } from "../../../lib/commandRoute.js";
3
+ const metadata = {
4
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.manage"] }
5
+ };
6
+ const bodySchema = z.object({ paymentId: z.string().uuid(), allocations: z.array(z.object({ invoiceId: z.string().uuid(), amount: z.coerce.number().positive() })).min(1).max(100) });
7
+ async function POST(req) {
8
+ return runCommandRoute(req, {
9
+ commandId: "billing.payments.allocate",
10
+ bodySchema,
11
+ resourceKind: "billing.payment",
12
+ resourceId: (body) => body.paymentId,
13
+ logLabel: "billing/payments/allocate.POST"
14
+ });
15
+ }
16
+ const openApi = {
17
+ methods: {
18
+ POST: {
19
+ tags: ["Billing"],
20
+ summary: "Allocate a payment to invoices",
21
+ description: "Allocates amounts of a payment to open invoices / debit memos of its account. Invoice paid / outstanding / status are recomputed from allocations.",
22
+ requestBody: { schema: bodySchema },
23
+ responses: [{ status: 200, description: "Updated payment state" }],
24
+ errors: [
25
+ { status: 409, description: "`billing.allocation.exceeds_outstanding` / `insufficient_unallocated` / `account_mismatch` / `currency_mismatch` / `invoice_not_open`" }
26
+ ]
27
+ }
28
+ }
29
+ };
30
+ export {
31
+ POST,
32
+ metadata,
33
+ openApi
34
+ };
35
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/allocate/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { runCommandRoute } from '../../../lib/commandRoute'\n\n/** `POST /api/billing/payments/allocate` \u2014 allocate a payment to invoices (Spec C). */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.manage'] },\n}\n\nconst bodySchema = z.object({ paymentId: z.string().uuid(), allocations: z.array(z.object({ invoiceId: z.string().uuid(), amount: z.coerce.number().positive() })).min(1).max(100) })\n\nexport async function POST(req: Request) {\n return runCommandRoute(req, {\n commandId: 'billing.payments.allocate',\n bodySchema,\n resourceKind: 'billing.payment',\n resourceId: (body) => body.paymentId,\n logLabel: 'billing/payments/allocate.POST',\n })\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Allocate a payment to invoices',\n description: 'Allocates amounts of a payment to open invoices / debit memos of its account. Invoice paid / outstanding / status are recomputed from allocations.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: 'Updated payment state' }],\n errors: [\n { status: 409, description: '`billing.allocation.exceeds_outstanding` / `insufficient_unallocated` / `account_mismatch` / `currency_mismatch` / `invoice_not_open`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAIzB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AACzE;AAEA,MAAM,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,GAAG,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,GAAG,QAAQ,EAAE,OAAO,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC;AAEpL,eAAsB,KAAK,KAAc;AACvC,SAAO,gBAAgB,KAAK;AAAA,IAC1B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd,YAAY,CAAC,SAAS,KAAK;AAAA,IAC3B,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,CAAC;AAAA,MACjE,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,wIAAwI;AAAA,MACtK;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { runCommandRoute } from "../../../lib/commandRoute.js";
3
+ const metadata = {
4
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.manage"] }
5
+ };
6
+ const bodySchema = z.object({ paymentId: z.string().uuid(), billAccountId: z.string().uuid() });
7
+ async function POST(req) {
8
+ return runCommandRoute(req, {
9
+ commandId: "billing.payments.assign",
10
+ bodySchema,
11
+ resourceKind: "billing.payment",
12
+ resourceId: (body) => body.paymentId,
13
+ logLabel: "billing/payments/assign.POST"
14
+ });
15
+ }
16
+ const openApi = {
17
+ methods: {
18
+ POST: {
19
+ tags: ["Billing"],
20
+ summary: "Assign a payment to a billing account",
21
+ description: "Assigns an unmatched payment to a postpaid account (status \u2192 matched) and applies it as credit to the account's open invoices, oldest due first.",
22
+ requestBody: { schema: bodySchema },
23
+ responses: [{ status: 200, description: "Updated payment state" }],
24
+ errors: [
25
+ { status: 404, description: "Payment or account not found" },
26
+ { status: 409, description: "`billing.payment.not_unmatched` / `prepaid_account` / `currency_mismatch`" }
27
+ ]
28
+ }
29
+ }
30
+ };
31
+ export {
32
+ POST,
33
+ metadata,
34
+ openApi
35
+ };
36
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/assign/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { runCommandRoute } from '../../../lib/commandRoute'\n\n/** `POST /api/billing/payments/assign` \u2014 assign a payment to a billing account (Spec C). */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.manage'] },\n}\n\nconst bodySchema = z.object({ paymentId: z.string().uuid(), billAccountId: z.string().uuid() })\n\nexport async function POST(req: Request) {\n return runCommandRoute(req, {\n commandId: 'billing.payments.assign',\n bodySchema,\n resourceKind: 'billing.payment',\n resourceId: (body) => body.paymentId,\n logLabel: 'billing/payments/assign.POST',\n })\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Assign a payment to a billing account',\n description: 'Assigns an unmatched payment to a postpaid account (status \u2192 matched) and applies it as credit to the account\\'s open invoices, oldest due first.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: 'Updated payment state' }],\n errors: [\n { status: 404, description: 'Payment or account not found' },\n { status: 409, description: '`billing.payment.not_unmatched` / `prepaid_account` / `currency_mismatch`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAIzB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AACzE;AAEA,MAAM,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,GAAG,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAE9F,eAAsB,KAAK,KAAc;AACvC,SAAO,gBAAgB,KAAK;AAAA,IAC1B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd,YAAY,CAAC,SAAS,KAAK;AAAA,IAC3B,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,CAAC;AAAA,MACjE,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,+BAA+B;AAAA,QAC3D,EAAE,QAAQ,KAAK,aAAa,4EAA4E;AAAA,MAC1G;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { runCommandRoute } from "../../../lib/commandRoute.js";
3
+ const metadata = {
4
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.manage", "billing.topup.create"] }
5
+ };
6
+ const bodySchema = z.object({ paymentId: z.string().uuid(), billAccountId: z.string().uuid() });
7
+ async function POST(req) {
8
+ return runCommandRoute(req, {
9
+ commandId: "billing.payments.convert_to_topup",
10
+ bodySchema,
11
+ resourceKind: "billing.payment",
12
+ resourceId: (body) => body.paymentId,
13
+ logLabel: "billing/payments/convert-to-topup.POST"
14
+ });
15
+ }
16
+ const openApi = {
17
+ methods: {
18
+ POST: {
19
+ tags: ["Billing"],
20
+ summary: "Convert a payment into a prepaid top-up",
21
+ description: "Turns an unmatched payment into a captured top-up of a prepaid account (balance credit, transaction and VAT receipt). Terminal; idempotent per payment.",
22
+ requestBody: { schema: bodySchema },
23
+ responses: [{ status: 200, description: "Updated payment state" }],
24
+ errors: [
25
+ { status: 409, description: "`billing.payment.not_prepaid` / `currency_mismatch` / `not_convertible`" }
26
+ ]
27
+ }
28
+ }
29
+ };
30
+ export {
31
+ POST,
32
+ metadata,
33
+ openApi
34
+ };
35
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/convert-to-topup/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { runCommandRoute } from '../../../lib/commandRoute'\n\n/** `POST /api/billing/payments/convert-to-topup` \u2014 convert a payment into a prepaid top-up (Spec C). */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.manage', 'billing.topup.create'] },\n}\n\nconst bodySchema = z.object({ paymentId: z.string().uuid(), billAccountId: z.string().uuid() })\n\nexport async function POST(req: Request) {\n return runCommandRoute(req, {\n commandId: 'billing.payments.convert_to_topup',\n bodySchema,\n resourceKind: 'billing.payment',\n resourceId: (body) => body.paymentId,\n logLabel: 'billing/payments/convert-to-topup.POST',\n })\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Convert a payment into a prepaid top-up',\n description: 'Turns an unmatched payment into a captured top-up of a prepaid account (balance credit, transaction and VAT receipt). Terminal; idempotent per payment.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: 'Updated payment state' }],\n errors: [\n { status: 409, description: '`billing.payment.not_prepaid` / `currency_mismatch` / `not_convertible`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAIzB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,0BAA0B,sBAAsB,EAAE;AACjG;AAEA,MAAM,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,GAAG,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAE9F,eAAsB,KAAK,KAAc;AACvC,SAAO,gBAAgB,KAAK;AAAA,IAC1B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd,YAAY,CAAC,SAAS,KAAK;AAAA,IAC3B,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,CAAC;AAAA,MACjE,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,0EAA0E;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { runCommandRoute } from "../../../lib/commandRoute.js";
3
+ const metadata = {
4
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.manage"] }
5
+ };
6
+ const bodySchema = z.object({ paymentId: z.string().uuid() });
7
+ async function POST(req) {
8
+ return runCommandRoute(req, {
9
+ commandId: "billing.payments.ignore",
10
+ bodySchema,
11
+ resourceKind: "billing.payment",
12
+ resourceId: (body) => body.paymentId,
13
+ logLabel: "billing/payments/ignore.POST"
14
+ });
15
+ }
16
+ const openApi = {
17
+ methods: {
18
+ POST: {
19
+ tags: ["Billing"],
20
+ summary: "Ignore a payment",
21
+ description: "Excludes an unallocated payment from matching and credit (fees, misdirected transfers). Reversible with restore.",
22
+ requestBody: { schema: bodySchema },
23
+ responses: [{ status: 200, description: "Updated payment state" }],
24
+ errors: [
25
+ { status: 409, description: "`billing.payment.has_allocations`" }
26
+ ]
27
+ }
28
+ }
29
+ };
30
+ export {
31
+ POST,
32
+ metadata,
33
+ openApi
34
+ };
35
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/ignore/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { runCommandRoute } from '../../../lib/commandRoute'\n\n/** `POST /api/billing/payments/ignore` \u2014 ignore a payment (Spec C). */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.manage'] },\n}\n\nconst bodySchema = z.object({ paymentId: z.string().uuid() })\n\nexport async function POST(req: Request) {\n return runCommandRoute(req, {\n commandId: 'billing.payments.ignore',\n bodySchema,\n resourceKind: 'billing.payment',\n resourceId: (body) => body.paymentId,\n logLabel: 'billing/payments/ignore.POST',\n })\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Ignore a payment',\n description: 'Excludes an unallocated payment from matching and credit (fees, misdirected transfers). Reversible with restore.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: 'Updated payment state' }],\n errors: [\n { status: 409, description: '`billing.payment.has_allocations`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAIzB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AACzE;AAEA,MAAM,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAE5D,eAAsB,KAAK,KAAc;AACvC,SAAO,gBAAgB,KAAK;AAAA,IAC1B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd,YAAY,CAAC,SAAS,KAAK;AAAA,IAC3B,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,CAAC;AAAA,MACjE,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,oCAAoC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,63 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { PAYMENT_IMPORT_MAX_BYTES } from "../../../data/validators.js";
4
+ import { readRequestBody, runCommandRoute } from "../../../lib/commandRoute.js";
5
+ const metadata = {
6
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.import"] }
7
+ };
8
+ const bodySchema = z.object({
9
+ fileName: z.string().trim().min(1).max(255),
10
+ content: z.string().max(PAYMENT_IMPORT_MAX_BYTES)
11
+ });
12
+ async function readUpload(req) {
13
+ const declared = Number(req.headers.get("content-length") ?? "0");
14
+ if (declared > PAYMENT_IMPORT_MAX_BYTES + 64 * 1024) {
15
+ return NextResponse.json({ error: "The file is larger than 2 MB", code: "billing.payment_import.too_large" }, { status: 413 });
16
+ }
17
+ if ((req.headers.get("content-type") ?? "").includes("multipart/form-data")) {
18
+ const form = await req.formData();
19
+ const file = form.get("file");
20
+ if (!file || typeof file === "string") return { fileName: "", content: "" };
21
+ if (file.size > PAYMENT_IMPORT_MAX_BYTES) {
22
+ return NextResponse.json({ error: "The file is larger than 2 MB", code: "billing.payment_import.too_large" }, { status: 413 });
23
+ }
24
+ return { fileName: file.name || "payments.csv", content: await file.text() };
25
+ }
26
+ return readRequestBody(req);
27
+ }
28
+ async function POST(req) {
29
+ const body = await readUpload(req.clone());
30
+ if (body instanceof Response) return body;
31
+ return runCommandRoute(
32
+ req,
33
+ {
34
+ commandId: "billing.payments.import",
35
+ bodySchema,
36
+ resourceKind: "billing.payment_import",
37
+ resourceId: () => null,
38
+ logLabel: "billing/payments/import.POST"
39
+ },
40
+ body
41
+ );
42
+ }
43
+ const openApi = {
44
+ methods: {
45
+ POST: {
46
+ tags: ["Billing"],
47
+ summary: "Import bank payments from CSV",
48
+ description: 'CSV header `date,amount,currency,reference,payer_name,payer_account` (UTF-8, comma separated, "." decimals, amount > 0, \u2264 5,000 rows, \u2264 2 MB). Each new row becomes a payment, matched by the invoice number in `reference`; re-uploaded lines are counted as duplicates. Send multipart `file` or JSON `{ fileName, content }`.',
49
+ requestBody: { schema: bodySchema },
50
+ responses: [{ status: 200, description: "`{ importId, fileName, rowCount, counts, errors[] }`" }],
51
+ errors: [
52
+ { status: 400, description: "`billing.payment_import.invalid_file` (header / empty / too many rows)" },
53
+ { status: 413, description: "`billing.payment_import.too_large`" }
54
+ ]
55
+ }
56
+ }
57
+ };
58
+ export {
59
+ POST,
60
+ metadata,
61
+ openApi
62
+ };
63
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/import/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { PAYMENT_IMPORT_MAX_BYTES } from '../../../data/validators'\nimport { readRequestBody, runCommandRoute } from '../../../lib/commandRoute'\n\n/**\n * `POST /api/billing/payments/import` \u2014 bank CSV upload (Spec C, C-D4).\n * Accepts `multipart/form-data` (`file`) or JSON `{ fileName, content }`.\n * 413 over 2 MB. Returns the import summary (counts per outcome + row errors).\n */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.import'] },\n}\n\nconst bodySchema = z.object({\n fileName: z.string().trim().min(1).max(255),\n content: z.string().max(PAYMENT_IMPORT_MAX_BYTES),\n})\n\nasync function readUpload(req: Request): Promise<unknown | Response> {\n const declared = Number(req.headers.get('content-length') ?? '0')\n if (declared > PAYMENT_IMPORT_MAX_BYTES + 64 * 1024) {\n return NextResponse.json({ error: 'The file is larger than 2 MB', code: 'billing.payment_import.too_large' }, { status: 413 })\n }\n if ((req.headers.get('content-type') ?? '').includes('multipart/form-data')) {\n const form = await req.formData()\n const file = form.get('file')\n if (!file || typeof file === 'string') return { fileName: '', content: '' }\n if (file.size > PAYMENT_IMPORT_MAX_BYTES) {\n return NextResponse.json({ error: 'The file is larger than 2 MB', code: 'billing.payment_import.too_large' }, { status: 413 })\n }\n return { fileName: file.name || 'payments.csv', content: await file.text() }\n }\n return readRequestBody(req)\n}\n\nexport async function POST(req: Request) {\n const body = await readUpload(req.clone())\n if (body instanceof Response) return body\n return runCommandRoute(\n req,\n {\n commandId: 'billing.payments.import',\n bodySchema,\n resourceKind: 'billing.payment_import',\n resourceId: () => null,\n logLabel: 'billing/payments/import.POST',\n },\n body,\n )\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Import bank payments from CSV',\n description:\n 'CSV header `date,amount,currency,reference,payer_name,payer_account` (UTF-8, comma separated, ' +\n '\".\" decimals, amount > 0, \u2264 5,000 rows, \u2264 2 MB). Each new row becomes a payment, matched by the ' +\n 'invoice number in `reference`; re-uploaded lines are counted as duplicates. Send multipart `file` or ' +\n 'JSON `{ fileName, content }`.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: '`{ importId, fileName, rowCount, counts, errors[] }`' }],\n errors: [\n { status: 400, description: '`billing.payment_import.invalid_file` (header / empty / too many rows)' },\n { status: 413, description: '`billing.payment_import.too_large`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,gCAAgC;AACzC,SAAS,iBAAiB,uBAAuB;AAQ1C,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AACzE;AAEA,MAAM,aAAa,EAAE,OAAO;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC1C,SAAS,EAAE,OAAO,EAAE,IAAI,wBAAwB;AAClD,CAAC;AAED,eAAe,WAAW,KAA2C;AACnE,QAAM,WAAW,OAAO,IAAI,QAAQ,IAAI,gBAAgB,KAAK,GAAG;AAChE,MAAI,WAAW,2BAA2B,KAAK,MAAM;AACnD,WAAO,aAAa,KAAK,EAAE,OAAO,gCAAgC,MAAM,mCAAmC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/H;AACA,OAAK,IAAI,QAAQ,IAAI,cAAc,KAAK,IAAI,SAAS,qBAAqB,GAAG;AAC3E,UAAM,OAAO,MAAM,IAAI,SAAS;AAChC,UAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO,EAAE,UAAU,IAAI,SAAS,GAAG;AAC1E,QAAI,KAAK,OAAO,0BAA0B;AACxC,aAAO,aAAa,KAAK,EAAE,OAAO,gCAAgC,MAAM,mCAAmC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/H;AACA,WAAO,EAAE,UAAU,KAAK,QAAQ,gBAAgB,SAAS,MAAM,KAAK,KAAK,EAAE;AAAA,EAC7E;AACA,SAAO,gBAAgB,GAAG;AAC5B;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,OAAO,MAAM,WAAW,IAAI,MAAM,CAAC;AACzC,MAAI,gBAAgB,SAAU,QAAO;AACrC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,WAAW;AAAA,MACX;AAAA,MACA,cAAc;AAAA,MACd,YAAY,MAAM;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aACE;AAAA,MAIF,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,uDAAuD,CAAC;AAAA,MAChG,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,yEAAyE;AAAA,QACrG,EAAE,QAAQ,KAAK,aAAa,qCAAqC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { runCommandRoute } from "../../../lib/commandRoute.js";
3
+ const metadata = {
4
+ POST: { requireAuth: true, requireFeatures: ["billing.payment.manage"] }
5
+ };
6
+ const bodySchema = z.object({ paymentId: z.string().uuid() });
7
+ async function POST(req) {
8
+ return runCommandRoute(req, {
9
+ commandId: "billing.payments.restore",
10
+ bodySchema,
11
+ resourceKind: "billing.payment",
12
+ resourceId: (body) => body.paymentId,
13
+ logLabel: "billing/payments/restore.POST"
14
+ });
15
+ }
16
+ const openApi = {
17
+ methods: {
18
+ POST: {
19
+ tags: ["Billing"],
20
+ summary: "Restore an ignored payment",
21
+ description: "Restores an ignored payment to matched (credit applied again) or unmatched.",
22
+ requestBody: { schema: bodySchema },
23
+ responses: [{ status: 200, description: "Updated payment state" }],
24
+ errors: [
25
+ { status: 409, description: "`billing.payment.not_ignored`" }
26
+ ]
27
+ }
28
+ }
29
+ };
30
+ export {
31
+ POST,
32
+ metadata,
33
+ openApi
34
+ };
35
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/billing/api/payments/restore/route.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { runCommandRoute } from '../../../lib/commandRoute'\n\n/** `POST /api/billing/payments/restore` \u2014 restore an ignored payment (Spec C). */\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['billing.payment.manage'] },\n}\n\nconst bodySchema = z.object({ paymentId: z.string().uuid() })\n\nexport async function POST(req: Request) {\n return runCommandRoute(req, {\n commandId: 'billing.payments.restore',\n bodySchema,\n resourceKind: 'billing.payment',\n resourceId: (body) => body.paymentId,\n logLabel: 'billing/payments/restore.POST',\n })\n}\n\nexport const openApi = {\n methods: {\n POST: {\n tags: ['Billing'],\n summary: 'Restore an ignored payment',\n description: 'Restores an ignored payment to matched (credit applied again) or unmatched.',\n requestBody: { schema: bodySchema },\n responses: [{ status: 200, description: 'Updated payment state' }],\n errors: [\n { status: 409, description: '`billing.payment.not_ignored`' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAIzB,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,wBAAwB,EAAE;AACzE;AAEA,MAAM,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAE5D,eAAsB,KAAK,KAAc;AACvC,SAAO,gBAAgB,KAAK;AAAA,IAC1B,WAAW;AAAA,IACX;AAAA,IACA,cAAc;AAAA,IACd,YAAY,CAAC,SAAS,KAAK;AAAA,IAC3B,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,MAAM,UAAU;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,QAAQ,WAAW;AAAA,MAClC,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,CAAC;AAAA,MACjE,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,gCAAgC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }