@baruk/core 0.3.1 → 0.4.2

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 (696) hide show
  1. package/.baruk-provenance.json +10 -0
  2. package/CHANGELOG.md +85 -0
  3. package/dist/auth/password-reset.d.ts +30 -1
  4. package/dist/auth/password-reset.d.ts.map +1 -1
  5. package/dist/auth/password-reset.js +139 -11
  6. package/dist/auth/password-reset.js.map +1 -1
  7. package/dist/auth/service.d.ts +39 -2
  8. package/dist/auth/service.d.ts.map +1 -1
  9. package/dist/auth/service.js +75 -10
  10. package/dist/auth/service.js.map +1 -1
  11. package/dist/billing/ar-repository.d.ts +334 -0
  12. package/dist/billing/ar-repository.d.ts.map +1 -0
  13. package/dist/billing/ar-repository.js +707 -0
  14. package/dist/billing/ar-repository.js.map +1 -0
  15. package/dist/billing/auto-generation.d.ts +87 -0
  16. package/dist/billing/auto-generation.d.ts.map +1 -0
  17. package/dist/billing/auto-generation.js +181 -0
  18. package/dist/billing/auto-generation.js.map +1 -0
  19. package/dist/billing/live-guard.d.ts +64 -0
  20. package/dist/billing/live-guard.d.ts.map +1 -0
  21. package/dist/billing/live-guard.js +68 -0
  22. package/dist/billing/live-guard.js.map +1 -0
  23. package/dist/billing/payment-means-catalog.d.ts +17 -0
  24. package/dist/billing/payment-means-catalog.d.ts.map +1 -0
  25. package/dist/billing/payment-means-catalog.js +21 -0
  26. package/dist/billing/payment-means-catalog.js.map +1 -0
  27. package/dist/billing/payment-means.d.ts +38 -0
  28. package/dist/billing/payment-means.d.ts.map +1 -0
  29. package/dist/billing/payment-means.js +29 -0
  30. package/dist/billing/payment-means.js.map +1 -0
  31. package/dist/billing/payment-rail.d.ts +118 -0
  32. package/dist/billing/payment-rail.d.ts.map +1 -0
  33. package/dist/billing/payment-rail.js +295 -0
  34. package/dist/billing/payment-rail.js.map +1 -0
  35. package/dist/billing/provider/asaas.d.ts +46 -1
  36. package/dist/billing/provider/asaas.d.ts.map +1 -1
  37. package/dist/billing/provider/asaas.js +194 -14
  38. package/dist/billing/provider/asaas.js.map +1 -1
  39. package/dist/billing/provider/manual.js +1 -1
  40. package/dist/billing/provider/manual.js.map +1 -1
  41. package/dist/billing/provider/types.d.ts +115 -8
  42. package/dist/billing/provider/types.d.ts.map +1 -1
  43. package/dist/billing/provider-account.d.ts +89 -0
  44. package/dist/billing/provider-account.d.ts.map +1 -0
  45. package/dist/billing/provider-account.js +161 -0
  46. package/dist/billing/provider-account.js.map +1 -0
  47. package/dist/billing/provider-onboarding.d.ts +67 -0
  48. package/dist/billing/provider-onboarding.d.ts.map +1 -0
  49. package/dist/billing/provider-onboarding.js +234 -0
  50. package/dist/billing/provider-onboarding.js.map +1 -0
  51. package/dist/billing/receivable.d.ts +5 -1
  52. package/dist/billing/receivable.d.ts.map +1 -1
  53. package/dist/billing/reconcile.d.ts +58 -0
  54. package/dist/billing/reconcile.d.ts.map +1 -0
  55. package/dist/billing/reconcile.js +138 -0
  56. package/dist/billing/reconcile.js.map +1 -0
  57. package/dist/billing/repository.d.ts +90 -1
  58. package/dist/billing/repository.d.ts.map +1 -1
  59. package/dist/billing/repository.js +148 -19
  60. package/dist/billing/repository.js.map +1 -1
  61. package/dist/cjs/auth/password-reset.js +141 -11
  62. package/dist/cjs/auth/password-reset.js.map +1 -1
  63. package/dist/cjs/auth/service.js +75 -9
  64. package/dist/cjs/auth/service.js.map +1 -1
  65. package/dist/cjs/billing/ar-repository.js +728 -0
  66. package/dist/cjs/billing/ar-repository.js.map +1 -0
  67. package/dist/cjs/billing/auto-generation.js +186 -0
  68. package/dist/cjs/billing/auto-generation.js.map +1 -0
  69. package/dist/cjs/billing/live-guard.js +72 -0
  70. package/dist/cjs/billing/live-guard.js.map +1 -0
  71. package/dist/cjs/billing/payment-means-catalog.js +25 -0
  72. package/dist/cjs/billing/payment-means-catalog.js.map +1 -0
  73. package/dist/cjs/billing/payment-means.js +33 -0
  74. package/dist/cjs/billing/payment-means.js.map +1 -0
  75. package/dist/cjs/billing/payment-rail.js +301 -0
  76. package/dist/cjs/billing/payment-rail.js.map +1 -0
  77. package/dist/cjs/billing/provider/asaas.js +194 -14
  78. package/dist/cjs/billing/provider/asaas.js.map +1 -1
  79. package/dist/cjs/billing/provider/manual.js +1 -1
  80. package/dist/cjs/billing/provider/manual.js.map +1 -1
  81. package/dist/cjs/billing/provider-account.js +170 -0
  82. package/dist/cjs/billing/provider-account.js.map +1 -0
  83. package/dist/cjs/billing/provider-onboarding.js +239 -0
  84. package/dist/cjs/billing/provider-onboarding.js.map +1 -0
  85. package/dist/cjs/billing/reconcile.js +143 -0
  86. package/dist/cjs/billing/reconcile.js.map +1 -0
  87. package/dist/cjs/billing/repository.js +150 -18
  88. package/dist/cjs/billing/repository.js.map +1 -1
  89. package/dist/cjs/clients/repository.js +96 -20
  90. package/dist/cjs/clients/repository.js.map +1 -1
  91. package/dist/cjs/collection/branding.js +140 -0
  92. package/dist/cjs/collection/branding.js.map +1 -0
  93. package/dist/cjs/collection/channel-accounts.js +137 -0
  94. package/dist/cjs/collection/channel-accounts.js.map +1 -0
  95. package/dist/cjs/collection/channel.js +17 -0
  96. package/dist/cjs/collection/channel.js.map +1 -0
  97. package/dist/cjs/collection/communication-bridge.js +140 -0
  98. package/dist/cjs/collection/communication-bridge.js.map +1 -0
  99. package/dist/cjs/collection/communication-runtime.js +193 -0
  100. package/dist/cjs/collection/communication-runtime.js.map +1 -0
  101. package/dist/cjs/collection/consent-repository.js +84 -0
  102. package/dist/cjs/collection/consent-repository.js.map +1 -0
  103. package/dist/cjs/collection/copy.js +125 -0
  104. package/dist/cjs/collection/copy.js.map +1 -0
  105. package/dist/cjs/collection/delivery-callback.js +151 -0
  106. package/dist/cjs/collection/delivery-callback.js.map +1 -0
  107. package/dist/cjs/collection/email-layout.js +252 -0
  108. package/dist/cjs/collection/email-layout.js.map +1 -0
  109. package/dist/cjs/collection/engine.js +414 -0
  110. package/dist/cjs/collection/engine.js.map +1 -0
  111. package/dist/cjs/collection/format.js +76 -0
  112. package/dist/cjs/collection/format.js.map +1 -0
  113. package/dist/cjs/collection/payment-block.js +3 -0
  114. package/dist/cjs/collection/payment-block.js.map +1 -0
  115. package/dist/cjs/collection/policy.js +147 -0
  116. package/dist/cjs/collection/policy.js.map +1 -0
  117. package/dist/cjs/collection/repository.js +260 -0
  118. package/dist/cjs/collection/repository.js.map +1 -0
  119. package/dist/cjs/collection/subject.js +104 -0
  120. package/dist/cjs/collection/subject.js.map +1 -0
  121. package/dist/cjs/collection/template-catalog.js +165 -0
  122. package/dist/cjs/collection/template-catalog.js.map +1 -0
  123. package/dist/cjs/collection/template.js +78 -0
  124. package/dist/cjs/collection/template.js.map +1 -0
  125. package/dist/cjs/communication/adapters/email.js +132 -0
  126. package/dist/cjs/communication/adapters/email.js.map +1 -0
  127. package/dist/cjs/communication/adapters/sms.js +127 -0
  128. package/dist/cjs/communication/adapters/sms.js.map +1 -0
  129. package/dist/cjs/communication/adapters/whatsapp-language.js +39 -0
  130. package/dist/cjs/communication/adapters/whatsapp-language.js.map +1 -0
  131. package/dist/cjs/communication/adapters/whatsapp-templates.js +100 -0
  132. package/dist/cjs/communication/adapters/whatsapp-templates.js.map +1 -0
  133. package/dist/cjs/communication/adapters/whatsapp.js +213 -0
  134. package/dist/cjs/communication/adapters/whatsapp.js.map +1 -0
  135. package/dist/cjs/communication/audit.js +61 -0
  136. package/dist/cjs/communication/audit.js.map +1 -0
  137. package/dist/cjs/communication/capabilities.js +76 -0
  138. package/dist/cjs/communication/capabilities.js.map +1 -0
  139. package/dist/cjs/communication/channel.js +53 -0
  140. package/dist/cjs/communication/channel.js.map +1 -0
  141. package/dist/cjs/communication/claim.js +228 -0
  142. package/dist/cjs/communication/claim.js.map +1 -0
  143. package/dist/cjs/communication/consent.js +43 -0
  144. package/dist/cjs/communication/consent.js.map +1 -0
  145. package/dist/cjs/communication/context.js +45 -0
  146. package/dist/cjs/communication/context.js.map +1 -0
  147. package/dist/cjs/communication/credentials.js +121 -0
  148. package/dist/cjs/communication/credentials.js.map +1 -0
  149. package/dist/cjs/communication/dry-run-scenario.js +161 -0
  150. package/dist/cjs/communication/dry-run-scenario.js.map +1 -0
  151. package/dist/cjs/communication/dry-run.js +97 -0
  152. package/dist/cjs/communication/dry-run.js.map +1 -0
  153. package/dist/cjs/communication/engine.js +483 -0
  154. package/dist/cjs/communication/engine.js.map +1 -0
  155. package/dist/cjs/communication/graph.js +50 -0
  156. package/dist/cjs/communication/graph.js.map +1 -0
  157. package/dist/cjs/communication/idempotency.js +26 -0
  158. package/dist/cjs/communication/idempotency.js.map +1 -0
  159. package/dist/cjs/communication/identity.js +110 -0
  160. package/dist/cjs/communication/identity.js.map +1 -0
  161. package/dist/cjs/communication/index.js +135 -0
  162. package/dist/cjs/communication/index.js.map +1 -0
  163. package/dist/cjs/communication/onboarding.js +297 -0
  164. package/dist/cjs/communication/onboarding.js.map +1 -0
  165. package/dist/cjs/communication/policy.js +16 -0
  166. package/dist/cjs/communication/policy.js.map +1 -0
  167. package/dist/cjs/communication/routing.js +77 -0
  168. package/dist/cjs/communication/routing.js.map +1 -0
  169. package/dist/cjs/communication/sender-profile.js +128 -0
  170. package/dist/cjs/communication/sender-profile.js.map +1 -0
  171. package/dist/cjs/communication/status.js +86 -0
  172. package/dist/cjs/communication/status.js.map +1 -0
  173. package/dist/cjs/communication/stores/onboarding.js +135 -0
  174. package/dist/cjs/communication/stores/onboarding.js.map +1 -0
  175. package/dist/cjs/communication/stores/postgres.js +458 -0
  176. package/dist/cjs/communication/stores/postgres.js.map +1 -0
  177. package/dist/cjs/communication/stores/routing.js +334 -0
  178. package/dist/cjs/communication/stores/routing.js.map +1 -0
  179. package/dist/cjs/communication/stores/secrets.js +126 -0
  180. package/dist/cjs/communication/stores/secrets.js.map +1 -0
  181. package/dist/cjs/communication/template-provider.js +22 -0
  182. package/dist/cjs/communication/template-provider.js.map +1 -0
  183. package/dist/cjs/communication/template.js +63 -0
  184. package/dist/cjs/communication/template.js.map +1 -0
  185. package/dist/cjs/communication/webhook-subscription.js +258 -0
  186. package/dist/cjs/communication/webhook-subscription.js.map +1 -0
  187. package/dist/cjs/communication/webhook.js +292 -0
  188. package/dist/cjs/communication/webhook.js.map +1 -0
  189. package/dist/cjs/competence/repository.js +309 -0
  190. package/dist/cjs/competence/repository.js.map +1 -0
  191. package/dist/cjs/contacts/phone.js +192 -0
  192. package/dist/cjs/contacts/phone.js.map +1 -0
  193. package/dist/cjs/db/seed-catalog.js +48 -0
  194. package/dist/cjs/db/seed-catalog.js.map +1 -0
  195. package/dist/cjs/db/seed.js +15 -7
  196. package/dist/cjs/db/seed.js.map +1 -1
  197. package/dist/cjs/documents/repository.js +244 -0
  198. package/dist/cjs/documents/repository.js.map +1 -0
  199. package/dist/cjs/documents/requests.js +136 -0
  200. package/dist/cjs/documents/requests.js.map +1 -0
  201. package/dist/cjs/index.js +406 -39
  202. package/dist/cjs/index.js.map +1 -1
  203. package/dist/cjs/legal/documents.js +125 -3
  204. package/dist/cjs/legal/documents.js.map +1 -1
  205. package/dist/cjs/legal/types.js +1 -0
  206. package/dist/cjs/legal/types.js.map +1 -1
  207. package/dist/cjs/mail/auth-templates.js +29 -0
  208. package/dist/cjs/mail/auth-templates.js.map +1 -0
  209. package/dist/cjs/mail/dedup-store.js +12 -51
  210. package/dist/cjs/mail/dedup-store.js.map +1 -1
  211. package/dist/cjs/mail/index.js +16 -4
  212. package/dist/cjs/mail/index.js.map +1 -1
  213. package/dist/cjs/mail/provider.js +12 -247
  214. package/dist/cjs/mail/provider.js.map +1 -1
  215. package/dist/cjs/mail/resend.js +14 -18
  216. package/dist/cjs/mail/resend.js.map +1 -1
  217. package/dist/cjs/mail/sender-resolver.js +12 -11
  218. package/dist/cjs/mail/sender-resolver.js.map +1 -1
  219. package/dist/cjs/mail/template-renderer.js +11 -16
  220. package/dist/cjs/mail/template-renderer.js.map +1 -1
  221. package/dist/cjs/mail/transactional-outbound.js +117 -0
  222. package/dist/cjs/mail/transactional-outbound.js.map +1 -0
  223. package/dist/cjs/mail/types.js +8 -35
  224. package/dist/cjs/mail/types.js.map +1 -1
  225. package/dist/cjs/portal/provisioning.js +144 -0
  226. package/dist/cjs/portal/provisioning.js.map +1 -0
  227. package/dist/cjs/pricing-engine/canonical.js +42 -0
  228. package/dist/cjs/pricing-engine/canonical.js.map +1 -0
  229. package/dist/cjs/pricing-engine/errors.js +6 -1
  230. package/dist/cjs/pricing-engine/errors.js.map +1 -1
  231. package/dist/cjs/pricing-engine/index.js +12 -1
  232. package/dist/cjs/pricing-engine/index.js.map +1 -1
  233. package/dist/cjs/pricing-engine/pipeline.js +200 -26
  234. package/dist/cjs/pricing-engine/pipeline.js.map +1 -1
  235. package/dist/cjs/pricing-engine/shadow-adapter.js +79 -0
  236. package/dist/cjs/pricing-engine/shadow-adapter.js.map +1 -0
  237. package/dist/cjs/pricing-engine/shadow-diff.js +55 -0
  238. package/dist/cjs/pricing-engine/shadow-diff.js.map +1 -0
  239. package/dist/cjs/pricing-engine/shadow-facade.js +85 -0
  240. package/dist/cjs/pricing-engine/shadow-facade.js.map +1 -0
  241. package/dist/cjs/pricing-engine/shadow-legacy-types.js +19 -0
  242. package/dist/cjs/pricing-engine/shadow-legacy-types.js.map +1 -0
  243. package/dist/cjs/pricing-engine/shadow-metrics.js +34 -0
  244. package/dist/cjs/pricing-engine/shadow-metrics.js.map +1 -0
  245. package/dist/cjs/pricing-engine/shadow-normalizer.js +42 -0
  246. package/dist/cjs/pricing-engine/shadow-normalizer.js.map +1 -0
  247. package/dist/cjs/rbac/authorize.js +28 -0
  248. package/dist/cjs/rbac/authorize.js.map +1 -1
  249. package/dist/cjs/rbac/catalog.js +67 -1
  250. package/dist/cjs/rbac/catalog.js.map +1 -1
  251. package/dist/cjs/rbac/workload-provisioning.js +160 -0
  252. package/dist/cjs/rbac/workload-provisioning.js.map +1 -0
  253. package/dist/cjs/rbac/workload.js +191 -0
  254. package/dist/cjs/rbac/workload.js.map +1 -0
  255. package/dist/cjs/storage/checksum.js +15 -0
  256. package/dist/cjs/storage/checksum.js.map +1 -0
  257. package/dist/cjs/storage/key.js +72 -0
  258. package/dist/cjs/storage/key.js.map +1 -0
  259. package/dist/cjs/storage/local.js +100 -0
  260. package/dist/cjs/storage/local.js.map +1 -0
  261. package/dist/cjs/storage/r2.js +181 -0
  262. package/dist/cjs/storage/r2.js.map +1 -0
  263. package/dist/cjs/storage/registry.js +41 -0
  264. package/dist/cjs/storage/registry.js.map +1 -0
  265. package/dist/cjs/storage/types.js +50 -0
  266. package/dist/cjs/storage/types.js.map +1 -0
  267. package/dist/cjs/subscription-billing/provider/asaas.js +32 -7
  268. package/dist/cjs/subscription-billing/provider/asaas.js.map +1 -1
  269. package/dist/cjs/subscription-billing/provider/disabled.js +8 -0
  270. package/dist/cjs/subscription-billing/provider/disabled.js.map +1 -1
  271. package/dist/cjs/subscription-billing/provider/registry.js +17 -0
  272. package/dist/cjs/subscription-billing/provider/registry.js.map +1 -1
  273. package/dist/cjs/subscription-billing/service.js +57 -8
  274. package/dist/cjs/subscription-billing/service.js.map +1 -1
  275. package/dist/cjs/subscription-billing/types.js.map +1 -1
  276. package/dist/cjs/tenancy/provisioning.js +32 -8
  277. package/dist/cjs/tenancy/provisioning.js.map +1 -1
  278. package/dist/cjs/users/repository.js +119 -2
  279. package/dist/cjs/users/repository.js.map +1 -1
  280. package/dist/cjs/vault/repository.js +81 -0
  281. package/dist/cjs/vault/repository.js.map +1 -1
  282. package/dist/clients/repository.d.ts +42 -0
  283. package/dist/clients/repository.d.ts.map +1 -1
  284. package/dist/clients/repository.js +94 -21
  285. package/dist/clients/repository.js.map +1 -1
  286. package/dist/collection/branding.d.ts +72 -0
  287. package/dist/collection/branding.d.ts.map +1 -0
  288. package/dist/collection/branding.js +136 -0
  289. package/dist/collection/branding.js.map +1 -0
  290. package/dist/collection/channel-accounts.d.ts +57 -0
  291. package/dist/collection/channel-accounts.d.ts.map +1 -0
  292. package/dist/collection/channel-accounts.js +133 -0
  293. package/dist/collection/channel-accounts.js.map +1 -0
  294. package/dist/collection/channel.d.ts +24 -0
  295. package/dist/collection/channel.d.ts.map +1 -0
  296. package/dist/collection/channel.js +16 -0
  297. package/dist/collection/channel.js.map +1 -0
  298. package/dist/collection/communication-bridge.d.ts +66 -0
  299. package/dist/collection/communication-bridge.d.ts.map +1 -0
  300. package/dist/collection/communication-bridge.js +134 -0
  301. package/dist/collection/communication-bridge.js.map +1 -0
  302. package/dist/collection/communication-runtime.d.ts +95 -0
  303. package/dist/collection/communication-runtime.d.ts.map +1 -0
  304. package/dist/collection/communication-runtime.js +187 -0
  305. package/dist/collection/communication-runtime.js.map +1 -0
  306. package/dist/collection/consent-repository.d.ts +32 -0
  307. package/dist/collection/consent-repository.d.ts.map +1 -0
  308. package/dist/collection/consent-repository.js +79 -0
  309. package/dist/collection/consent-repository.js.map +1 -0
  310. package/dist/collection/copy.d.ts +50 -0
  311. package/dist/collection/copy.d.ts.map +1 -0
  312. package/dist/collection/copy.js +122 -0
  313. package/dist/collection/copy.js.map +1 -0
  314. package/dist/collection/delivery-callback.d.ts +49 -0
  315. package/dist/collection/delivery-callback.d.ts.map +1 -0
  316. package/dist/collection/delivery-callback.js +147 -0
  317. package/dist/collection/delivery-callback.js.map +1 -0
  318. package/dist/collection/email-layout.d.ts +45 -0
  319. package/dist/collection/email-layout.d.ts.map +1 -0
  320. package/dist/collection/email-layout.js +247 -0
  321. package/dist/collection/email-layout.js.map +1 -0
  322. package/dist/collection/engine.d.ts +177 -0
  323. package/dist/collection/engine.d.ts.map +1 -0
  324. package/dist/collection/engine.js +407 -0
  325. package/dist/collection/engine.js.map +1 -0
  326. package/dist/collection/format.d.ts +32 -0
  327. package/dist/collection/format.d.ts.map +1 -0
  328. package/dist/collection/format.js +70 -0
  329. package/dist/collection/format.js.map +1 -0
  330. package/dist/collection/payment-block.d.ts +24 -0
  331. package/dist/collection/payment-block.d.ts.map +1 -0
  332. package/dist/collection/payment-block.js +2 -0
  333. package/dist/collection/payment-block.js.map +1 -0
  334. package/dist/collection/policy.d.ts +53 -0
  335. package/dist/collection/policy.d.ts.map +1 -0
  336. package/dist/collection/policy.js +141 -0
  337. package/dist/collection/policy.js.map +1 -0
  338. package/dist/collection/repository.d.ts +129 -0
  339. package/dist/collection/repository.d.ts.map +1 -0
  340. package/dist/collection/repository.js +246 -0
  341. package/dist/collection/repository.js.map +1 -0
  342. package/dist/collection/subject.d.ts +66 -0
  343. package/dist/collection/subject.d.ts.map +1 -0
  344. package/dist/collection/subject.js +99 -0
  345. package/dist/collection/subject.js.map +1 -0
  346. package/dist/collection/template-catalog.d.ts +16 -0
  347. package/dist/collection/template-catalog.d.ts.map +1 -0
  348. package/dist/collection/template-catalog.js +162 -0
  349. package/dist/collection/template-catalog.js.map +1 -0
  350. package/dist/collection/template.d.ts +37 -0
  351. package/dist/collection/template.d.ts.map +1 -0
  352. package/dist/collection/template.js +73 -0
  353. package/dist/collection/template.js.map +1 -0
  354. package/dist/communication/adapters/email.d.ts +28 -0
  355. package/dist/communication/adapters/email.d.ts.map +1 -0
  356. package/dist/communication/adapters/email.js +129 -0
  357. package/dist/communication/adapters/email.js.map +1 -0
  358. package/dist/communication/adapters/sms.d.ts +95 -0
  359. package/dist/communication/adapters/sms.d.ts.map +1 -0
  360. package/dist/communication/adapters/sms.js +121 -0
  361. package/dist/communication/adapters/sms.js.map +1 -0
  362. package/dist/communication/adapters/whatsapp-language.d.ts +34 -0
  363. package/dist/communication/adapters/whatsapp-language.d.ts.map +1 -0
  364. package/dist/communication/adapters/whatsapp-language.js +36 -0
  365. package/dist/communication/adapters/whatsapp-language.js.map +1 -0
  366. package/dist/communication/adapters/whatsapp-templates.d.ts +18 -0
  367. package/dist/communication/adapters/whatsapp-templates.d.ts.map +1 -0
  368. package/dist/communication/adapters/whatsapp-templates.js +97 -0
  369. package/dist/communication/adapters/whatsapp-templates.js.map +1 -0
  370. package/dist/communication/adapters/whatsapp.d.ts +29 -0
  371. package/dist/communication/adapters/whatsapp.d.ts.map +1 -0
  372. package/dist/communication/adapters/whatsapp.js +210 -0
  373. package/dist/communication/adapters/whatsapp.js.map +1 -0
  374. package/dist/communication/audit.d.ts +105 -0
  375. package/dist/communication/audit.d.ts.map +1 -0
  376. package/dist/communication/audit.js +56 -0
  377. package/dist/communication/audit.js.map +1 -0
  378. package/dist/communication/capabilities.d.ts +88 -0
  379. package/dist/communication/capabilities.d.ts.map +1 -0
  380. package/dist/communication/capabilities.js +72 -0
  381. package/dist/communication/capabilities.js.map +1 -0
  382. package/dist/communication/channel.d.ts +125 -0
  383. package/dist/communication/channel.d.ts.map +1 -0
  384. package/dist/communication/channel.js +47 -0
  385. package/dist/communication/channel.js.map +1 -0
  386. package/dist/communication/claim.d.ts +368 -0
  387. package/dist/communication/claim.d.ts.map +1 -0
  388. package/dist/communication/claim.js +224 -0
  389. package/dist/communication/claim.js.map +1 -0
  390. package/dist/communication/consent.d.ts +65 -0
  391. package/dist/communication/consent.d.ts.map +1 -0
  392. package/dist/communication/consent.js +40 -0
  393. package/dist/communication/consent.js.map +1 -0
  394. package/dist/communication/context.d.ts +48 -0
  395. package/dist/communication/context.d.ts.map +1 -0
  396. package/dist/communication/context.js +41 -0
  397. package/dist/communication/context.js.map +1 -0
  398. package/dist/communication/credentials.d.ts +74 -0
  399. package/dist/communication/credentials.d.ts.map +1 -0
  400. package/dist/communication/credentials.js +115 -0
  401. package/dist/communication/credentials.js.map +1 -0
  402. package/dist/communication/dry-run-scenario.d.ts +37 -0
  403. package/dist/communication/dry-run-scenario.d.ts.map +1 -0
  404. package/dist/communication/dry-run-scenario.js +158 -0
  405. package/dist/communication/dry-run-scenario.js.map +1 -0
  406. package/dist/communication/dry-run.d.ts +40 -0
  407. package/dist/communication/dry-run.d.ts.map +1 -0
  408. package/dist/communication/dry-run.js +92 -0
  409. package/dist/communication/dry-run.js.map +1 -0
  410. package/dist/communication/engine.d.ts +153 -0
  411. package/dist/communication/engine.d.ts.map +1 -0
  412. package/dist/communication/engine.js +480 -0
  413. package/dist/communication/engine.js.map +1 -0
  414. package/dist/communication/graph.d.ts +38 -0
  415. package/dist/communication/graph.d.ts.map +1 -0
  416. package/dist/communication/graph.js +45 -0
  417. package/dist/communication/graph.js.map +1 -0
  418. package/dist/communication/idempotency.d.ts +33 -0
  419. package/dist/communication/idempotency.d.ts.map +1 -0
  420. package/dist/communication/idempotency.js +23 -0
  421. package/dist/communication/idempotency.js.map +1 -0
  422. package/dist/communication/identity.d.ts +127 -0
  423. package/dist/communication/identity.d.ts.map +1 -0
  424. package/dist/communication/identity.js +105 -0
  425. package/dist/communication/identity.js.map +1 -0
  426. package/dist/communication/index.d.ts +66 -0
  427. package/dist/communication/index.d.ts.map +1 -0
  428. package/dist/communication/index.js +42 -0
  429. package/dist/communication/index.js.map +1 -0
  430. package/dist/communication/onboarding.d.ts +223 -0
  431. package/dist/communication/onboarding.d.ts.map +1 -0
  432. package/dist/communication/onboarding.js +287 -0
  433. package/dist/communication/onboarding.js.map +1 -0
  434. package/dist/communication/policy.d.ts +99 -0
  435. package/dist/communication/policy.d.ts.map +1 -0
  436. package/dist/communication/policy.js +13 -0
  437. package/dist/communication/policy.js.map +1 -0
  438. package/dist/communication/routing.d.ts +99 -0
  439. package/dist/communication/routing.d.ts.map +1 -0
  440. package/dist/communication/routing.js +73 -0
  441. package/dist/communication/routing.js.map +1 -0
  442. package/dist/communication/sender-profile.d.ts +100 -0
  443. package/dist/communication/sender-profile.d.ts.map +1 -0
  444. package/dist/communication/sender-profile.js +123 -0
  445. package/dist/communication/sender-profile.js.map +1 -0
  446. package/dist/communication/status.d.ts +48 -0
  447. package/dist/communication/status.d.ts.map +1 -0
  448. package/dist/communication/status.js +79 -0
  449. package/dist/communication/status.js.map +1 -0
  450. package/dist/communication/stores/onboarding.d.ts +88 -0
  451. package/dist/communication/stores/onboarding.d.ts.map +1 -0
  452. package/dist/communication/stores/onboarding.js +127 -0
  453. package/dist/communication/stores/onboarding.js.map +1 -0
  454. package/dist/communication/stores/postgres.d.ts +81 -0
  455. package/dist/communication/stores/postgres.d.ts.map +1 -0
  456. package/dist/communication/stores/postgres.js +453 -0
  457. package/dist/communication/stores/postgres.js.map +1 -0
  458. package/dist/communication/stores/routing.d.ts +169 -0
  459. package/dist/communication/stores/routing.d.ts.map +1 -0
  460. package/dist/communication/stores/routing.js +324 -0
  461. package/dist/communication/stores/routing.js.map +1 -0
  462. package/dist/communication/stores/secrets.d.ts +89 -0
  463. package/dist/communication/stores/secrets.d.ts.map +1 -0
  464. package/dist/communication/stores/secrets.js +122 -0
  465. package/dist/communication/stores/secrets.js.map +1 -0
  466. package/dist/communication/template-provider.d.ts +85 -0
  467. package/dist/communication/template-provider.d.ts.map +1 -0
  468. package/dist/communication/template-provider.js +21 -0
  469. package/dist/communication/template-provider.js.map +1 -0
  470. package/dist/communication/template.d.ts +87 -0
  471. package/dist/communication/template.d.ts.map +1 -0
  472. package/dist/communication/template.js +59 -0
  473. package/dist/communication/template.js.map +1 -0
  474. package/dist/communication/webhook-subscription.d.ts +156 -0
  475. package/dist/communication/webhook-subscription.d.ts.map +1 -0
  476. package/dist/communication/webhook-subscription.js +252 -0
  477. package/dist/communication/webhook-subscription.js.map +1 -0
  478. package/dist/communication/webhook.d.ts +121 -0
  479. package/dist/communication/webhook.d.ts.map +1 -0
  480. package/dist/communication/webhook.js +283 -0
  481. package/dist/communication/webhook.js.map +1 -0
  482. package/dist/competence/repository.d.ts +147 -0
  483. package/dist/competence/repository.d.ts.map +1 -0
  484. package/dist/competence/repository.js +294 -0
  485. package/dist/competence/repository.js.map +1 -0
  486. package/dist/contacts/phone.d.ts +70 -0
  487. package/dist/contacts/phone.d.ts.map +1 -0
  488. package/dist/contacts/phone.js +186 -0
  489. package/dist/contacts/phone.js.map +1 -0
  490. package/dist/db/migrate.js +17 -11
  491. package/dist/db/migrate.js.map +1 -1
  492. package/dist/db/seed-catalog.d.ts +18 -0
  493. package/dist/db/seed-catalog.d.ts.map +1 -0
  494. package/dist/db/seed-catalog.js +45 -0
  495. package/dist/db/seed-catalog.js.map +1 -0
  496. package/dist/db/seed.js +16 -8
  497. package/dist/db/seed.js.map +1 -1
  498. package/dist/documents/repository.d.ts +97 -0
  499. package/dist/documents/repository.d.ts.map +1 -0
  500. package/dist/documents/repository.js +236 -0
  501. package/dist/documents/repository.js.map +1 -0
  502. package/dist/documents/requests.d.ts +73 -0
  503. package/dist/documents/requests.d.ts.map +1 -0
  504. package/dist/documents/requests.js +127 -0
  505. package/dist/documents/requests.js.map +1 -0
  506. package/dist/index.d.ts +109 -13
  507. package/dist/index.d.ts.map +1 -1
  508. package/dist/index.js +100 -8
  509. package/dist/index.js.map +1 -1
  510. package/dist/legal/documents.d.ts.map +1 -1
  511. package/dist/legal/documents.js +125 -3
  512. package/dist/legal/documents.js.map +1 -1
  513. package/dist/legal/index.d.ts +1 -1
  514. package/dist/legal/index.d.ts.map +1 -1
  515. package/dist/legal/types.d.ts +32 -1
  516. package/dist/legal/types.d.ts.map +1 -1
  517. package/dist/legal/types.js +1 -0
  518. package/dist/legal/types.js.map +1 -1
  519. package/dist/mail/auth-templates.d.ts +15 -0
  520. package/dist/mail/auth-templates.d.ts.map +1 -0
  521. package/dist/mail/auth-templates.js +26 -0
  522. package/dist/mail/auth-templates.js.map +1 -0
  523. package/dist/mail/dedup-store.d.ts +1 -24
  524. package/dist/mail/dedup-store.d.ts.map +1 -1
  525. package/dist/mail/dedup-store.js +9 -48
  526. package/dist/mail/dedup-store.js.map +1 -1
  527. package/dist/mail/index.d.ts +2 -1
  528. package/dist/mail/index.d.ts.map +1 -1
  529. package/dist/mail/index.js +13 -2
  530. package/dist/mail/index.js.map +1 -1
  531. package/dist/mail/provider.d.ts +2 -30
  532. package/dist/mail/provider.d.ts.map +1 -1
  533. package/dist/mail/provider.js +10 -246
  534. package/dist/mail/provider.js.map +1 -1
  535. package/dist/mail/resend.d.ts +2 -12
  536. package/dist/mail/resend.d.ts.map +1 -1
  537. package/dist/mail/resend.js +11 -17
  538. package/dist/mail/resend.js.map +1 -1
  539. package/dist/mail/sender-resolver.d.ts +1 -7
  540. package/dist/mail/sender-resolver.d.ts.map +1 -1
  541. package/dist/mail/sender-resolver.js +11 -10
  542. package/dist/mail/sender-resolver.js.map +1 -1
  543. package/dist/mail/template-renderer.d.ts +1 -9
  544. package/dist/mail/template-renderer.d.ts.map +1 -1
  545. package/dist/mail/template-renderer.js +10 -15
  546. package/dist/mail/template-renderer.js.map +1 -1
  547. package/dist/mail/transactional-outbound.d.ts +115 -0
  548. package/dist/mail/transactional-outbound.d.ts.map +1 -0
  549. package/dist/mail/transactional-outbound.js +113 -0
  550. package/dist/mail/transactional-outbound.js.map +1 -0
  551. package/dist/mail/types.d.ts +2 -142
  552. package/dist/mail/types.d.ts.map +1 -1
  553. package/dist/mail/types.js +1 -33
  554. package/dist/mail/types.js.map +1 -1
  555. package/dist/portal/provisioning.d.ts +58 -0
  556. package/dist/portal/provisioning.d.ts.map +1 -0
  557. package/dist/portal/provisioning.js +139 -0
  558. package/dist/portal/provisioning.js.map +1 -0
  559. package/dist/pricing-engine/canonical.d.ts +14 -0
  560. package/dist/pricing-engine/canonical.d.ts.map +1 -0
  561. package/dist/pricing-engine/canonical.js +39 -0
  562. package/dist/pricing-engine/canonical.js.map +1 -0
  563. package/dist/pricing-engine/errors.d.ts.map +1 -1
  564. package/dist/pricing-engine/errors.js +6 -1
  565. package/dist/pricing-engine/errors.js.map +1 -1
  566. package/dist/pricing-engine/index.d.ts +12 -2
  567. package/dist/pricing-engine/index.d.ts.map +1 -1
  568. package/dist/pricing-engine/index.js +6 -1
  569. package/dist/pricing-engine/index.js.map +1 -1
  570. package/dist/pricing-engine/pipeline.d.ts.map +1 -1
  571. package/dist/pricing-engine/pipeline.js +202 -28
  572. package/dist/pricing-engine/pipeline.js.map +1 -1
  573. package/dist/pricing-engine/shadow-adapter.d.ts +37 -0
  574. package/dist/pricing-engine/shadow-adapter.d.ts.map +1 -0
  575. package/dist/pricing-engine/shadow-adapter.js +75 -0
  576. package/dist/pricing-engine/shadow-adapter.js.map +1 -0
  577. package/dist/pricing-engine/shadow-diff.d.ts +26 -0
  578. package/dist/pricing-engine/shadow-diff.d.ts.map +1 -0
  579. package/dist/pricing-engine/shadow-diff.js +52 -0
  580. package/dist/pricing-engine/shadow-diff.js.map +1 -0
  581. package/dist/pricing-engine/shadow-facade.d.ts +42 -0
  582. package/dist/pricing-engine/shadow-facade.d.ts.map +1 -0
  583. package/dist/pricing-engine/shadow-facade.js +82 -0
  584. package/dist/pricing-engine/shadow-facade.js.map +1 -0
  585. package/dist/pricing-engine/shadow-legacy-types.d.ts +64 -0
  586. package/dist/pricing-engine/shadow-legacy-types.d.ts.map +1 -0
  587. package/dist/pricing-engine/shadow-legacy-types.js +18 -0
  588. package/dist/pricing-engine/shadow-legacy-types.js.map +1 -0
  589. package/dist/pricing-engine/shadow-metrics.d.ts +33 -0
  590. package/dist/pricing-engine/shadow-metrics.d.ts.map +1 -0
  591. package/dist/pricing-engine/shadow-metrics.js +31 -0
  592. package/dist/pricing-engine/shadow-metrics.js.map +1 -0
  593. package/dist/pricing-engine/shadow-normalizer.d.ts +17 -0
  594. package/dist/pricing-engine/shadow-normalizer.d.ts.map +1 -0
  595. package/dist/pricing-engine/shadow-normalizer.js +39 -0
  596. package/dist/pricing-engine/shadow-normalizer.js.map +1 -0
  597. package/dist/pricing-engine/types.d.ts +2 -0
  598. package/dist/pricing-engine/types.d.ts.map +1 -1
  599. package/dist/rbac/authorize.d.ts +12 -0
  600. package/dist/rbac/authorize.d.ts.map +1 -1
  601. package/dist/rbac/authorize.js +27 -0
  602. package/dist/rbac/authorize.js.map +1 -1
  603. package/dist/rbac/catalog.d.ts.map +1 -1
  604. package/dist/rbac/catalog.js +67 -1
  605. package/dist/rbac/catalog.js.map +1 -1
  606. package/dist/rbac/workload-provisioning.d.ts +66 -0
  607. package/dist/rbac/workload-provisioning.d.ts.map +1 -0
  608. package/dist/rbac/workload-provisioning.js +153 -0
  609. package/dist/rbac/workload-provisioning.js.map +1 -0
  610. package/dist/rbac/workload.d.ts +124 -0
  611. package/dist/rbac/workload.d.ts.map +1 -0
  612. package/dist/rbac/workload.js +184 -0
  613. package/dist/rbac/workload.js.map +1 -0
  614. package/dist/storage/checksum.d.ts +9 -0
  615. package/dist/storage/checksum.d.ts.map +1 -0
  616. package/dist/storage/checksum.js +12 -0
  617. package/dist/storage/checksum.js.map +1 -0
  618. package/dist/storage/key.d.ts +37 -0
  619. package/dist/storage/key.d.ts.map +1 -0
  620. package/dist/storage/key.js +67 -0
  621. package/dist/storage/key.js.map +1 -0
  622. package/dist/storage/local.d.ts +40 -0
  623. package/dist/storage/local.d.ts.map +1 -0
  624. package/dist/storage/local.js +96 -0
  625. package/dist/storage/local.js.map +1 -0
  626. package/dist/storage/r2.d.ts +43 -0
  627. package/dist/storage/r2.d.ts.map +1 -0
  628. package/dist/storage/r2.js +177 -0
  629. package/dist/storage/r2.js.map +1 -0
  630. package/dist/storage/registry.d.ts +23 -0
  631. package/dist/storage/registry.d.ts.map +1 -0
  632. package/dist/storage/registry.js +37 -0
  633. package/dist/storage/registry.js.map +1 -0
  634. package/dist/storage/types.d.ts +67 -0
  635. package/dist/storage/types.d.ts.map +1 -0
  636. package/dist/storage/types.js +45 -0
  637. package/dist/storage/types.js.map +1 -0
  638. package/dist/subscription-billing/provider/asaas.d.ts +14 -0
  639. package/dist/subscription-billing/provider/asaas.d.ts.map +1 -1
  640. package/dist/subscription-billing/provider/asaas.js +32 -7
  641. package/dist/subscription-billing/provider/asaas.js.map +1 -1
  642. package/dist/subscription-billing/provider/disabled.d.ts +9 -0
  643. package/dist/subscription-billing/provider/disabled.d.ts.map +1 -1
  644. package/dist/subscription-billing/provider/disabled.js +8 -0
  645. package/dist/subscription-billing/provider/disabled.js.map +1 -1
  646. package/dist/subscription-billing/provider/registry.d.ts +10 -0
  647. package/dist/subscription-billing/provider/registry.d.ts.map +1 -1
  648. package/dist/subscription-billing/provider/registry.js +17 -0
  649. package/dist/subscription-billing/provider/registry.js.map +1 -1
  650. package/dist/subscription-billing/service.d.ts +17 -1
  651. package/dist/subscription-billing/service.d.ts.map +1 -1
  652. package/dist/subscription-billing/service.js +57 -8
  653. package/dist/subscription-billing/service.js.map +1 -1
  654. package/dist/subscription-billing/types.d.ts +13 -0
  655. package/dist/subscription-billing/types.d.ts.map +1 -1
  656. package/dist/subscription-billing/types.js.map +1 -1
  657. package/dist/tenancy/provisioning.d.ts.map +1 -1
  658. package/dist/tenancy/provisioning.js +32 -8
  659. package/dist/tenancy/provisioning.js.map +1 -1
  660. package/dist/users/repository.d.ts +38 -0
  661. package/dist/users/repository.d.ts.map +1 -1
  662. package/dist/users/repository.js +118 -3
  663. package/dist/users/repository.js.map +1 -1
  664. package/dist/vault/repository.d.ts +67 -0
  665. package/dist/vault/repository.d.ts.map +1 -1
  666. package/dist/vault/repository.js +78 -0
  667. package/dist/vault/repository.js.map +1 -1
  668. package/package.json +13 -4
  669. package/src/db/migrations/0023_user_invite_activation.sql +15 -0
  670. package/src/db/migrations/0024_set_user_password_function.sql +32 -0
  671. package/src/db/migrations/0025_revoke_user_session_function.sql +28 -0
  672. package/src/db/migrations/0026_documents_and_competence.sql +353 -0
  673. package/src/db/migrations/0027_receivable_client_isolation.sql +58 -0
  674. package/src/db/migrations/0028_collection_engine.sql +94 -0
  675. package/src/db/migrations/0029_payment_rail.sql +107 -0
  676. package/src/db/migrations/0030_provider_account_uniqueness.sql +22 -0
  677. package/src/db/migrations/0031_provider_account_environment_scope.sql +21 -0
  678. package/src/db/migrations/0032_settlement_reversal.sql +76 -0
  679. package/src/db/migrations/0033_receivable_idempotency.sql +28 -0
  680. package/src/db/migrations/0034_payment_customer_reconcile.sql +30 -0
  681. package/src/db/migrations/0035_payment_account_environments.sql +61 -0
  682. package/src/db/migrations/0036_primary_backfill_under_force_rls.sql +41 -0
  683. package/src/db/migrations/0037_receivable_generation_source.sql +29 -0
  684. package/src/db/migrations/0038_notification_channels.sql +175 -0
  685. package/src/db/migrations/0039_communication_dispatch_claim.sql +193 -0
  686. package/src/db/migrations/0040_communication_unknown_outcome.sql +99 -0
  687. package/src/db/migrations/0041_channel_binding_routing.sql +146 -0
  688. package/src/db/migrations/0042_channel_route_read_isolation.sql +165 -0
  689. package/src/db/migrations/0043_workload_identity.sql +105 -0
  690. package/src/db/migrations/0044_channel_onboarding_session.sql +96 -0
  691. package/dist/cjs/mail/resend-client.js +0 -103
  692. package/dist/cjs/mail/resend-client.js.map +0 -1
  693. package/dist/mail/resend-client.d.ts +0 -16
  694. package/dist/mail/resend-client.d.ts.map +0 -1
  695. package/dist/mail/resend-client.js +0 -100
  696. package/dist/mail/resend-client.js.map +0 -1
@@ -0,0 +1,728 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OPEN_STATUSES = exports.DEFAULT_AGING_BUCKETS = void 0;
4
+ exports.assertCompetence = assertCompetence;
5
+ exports.dueDateFor = dueDateFor;
6
+ exports.checkCompetenceDueDate = checkCompetenceDueDate;
7
+ exports.classifyFeeForCompetence = classifyFeeForCompetence;
8
+ exports.feeAppliesTo = feeAppliesTo;
9
+ exports.generateReceivablesForCompetence = generateReceivablesForCompetence;
10
+ exports.createOneOffReceivable = createOneOffReceivable;
11
+ exports.listReceivables = listReceivables;
12
+ exports.getReceivable = getReceivable;
13
+ exports.listReceivableItems = listReceivableItems;
14
+ exports.listPayments = listPayments;
15
+ exports.registerPayment = registerPayment;
16
+ exports.reverseSettlementForCharge = reverseSettlementForCharge;
17
+ exports.cancelReceivable = cancelReceivable;
18
+ exports.markOverdueReceivables = markOverdueReceivables;
19
+ exports.financialSummary = financialSummary;
20
+ exports.agingBuckets = agingBuckets;
21
+ exports.clientFinancialSummary = clientFinancialSummary;
22
+ const shared_1 = require("@baruk/shared");
23
+ const payment_means_catalog_js_1 = require("./payment-means-catalog.js");
24
+ /**
25
+ * Accounts Receivable — M1 do Merchant Billing Core
26
+ * (RFC-CAPABILITY-MERCHANT-BILLING-CORE-001 §4/§20). O M0 entregou schema e
27
+ * contratos; aqui entram a geração por competência, a máquina de estados e as
28
+ * consultas financeiras.
29
+ *
30
+ * A separação do M0 continua valendo e não pode ser colapsada: `Receivable` é a
31
+ * DÍVIDA do cliente com o escritório; `Charge` é o INSTRUMENTO (boleto/pix) que
32
+ * tenta recebê-la; `Payment` é o dinheiro que chegou. Um mesmo Receivable pode
33
+ * ter vários Charges (reemissão) e vários Payments (parcial).
34
+ *
35
+ * Tenant-scoped por RLS: nenhuma query aqui filtra `tenant_id` na mão — quem
36
+ * garante o recorte é a policy, e o contexto vem de `withContext`.
37
+ */
38
+ // ── Vencido é uma DERIVAÇÃO, não um estado que alguém precisa lembrar de gravar ──
39
+ //
40
+ // Um recebível `open` cuja data passou já está vencido — mesmo que nenhum job
41
+ // tenha rodado. Gravar 'overdue' numa coluna faria o número do dashboard depender
42
+ // de um cron ter executado; quando o cron falha, o escritório vê inadimplência
43
+ // menor do que a real, que é o pior erro possível neste domínio.
44
+ //
45
+ // Então o status efetivo é calculado na leitura. `markOverdueReceivables` existe
46
+ // para MATERIALIZAR a transição — não para descobri-la — porque a régua de
47
+ // cobrança precisa de um instante definido para disparar RECEIVABLE_OVERDUE.
48
+ // `partially_paid` entra junto de `open`: um recebível pago pela metade cujo
49
+ // vencimento passou TEM saldo em atraso. Considerar só `open` fazia o resumo
50
+ // dizer "vencido: R$ 0" enquanto o aging listava o mesmo saldo na faixa de 1-7
51
+ // dias — dois números verdadeiros contando coisas diferentes, e o mais visível
52
+ // deles subestimando a inadimplência.
53
+ const EFFECTIVE_STATUS_SQL = `
54
+ CASE WHEN r.status IN ('open','partially_paid')
55
+ AND r.due_date IS NOT NULL AND r.due_date < CURRENT_DATE
56
+ THEN 'overdue' ELSE r.status END`;
57
+ /** Status que ainda representam dinheiro a receber. */
58
+ const OPEN_STATUSES = ['open', 'partially_paid', 'overdue'];
59
+ exports.OPEN_STATUSES = OPEN_STATUSES;
60
+ const iso = (d) => (d ? d.toISOString().slice(0, 10) : null);
61
+ /** Texto de `metadata`, ou null. Ignora número/objeto: metadata é livre. */
62
+ function metaText(metadata, key) {
63
+ const v = metadata?.[key];
64
+ return typeof v === 'string' && v.trim() ? v.trim() : null;
65
+ }
66
+ function mapReceivable(r) {
67
+ const amount = Number(r.amount);
68
+ const amountPaid = Number(r.amount_paid);
69
+ return {
70
+ id: r.id,
71
+ clientId: r.client_id,
72
+ clientName: r.client_name,
73
+ feeAgreementId: r.fee_agreement_id,
74
+ competence: r.competence,
75
+ amount,
76
+ status: r.status,
77
+ effectiveStatus: r.effective_status,
78
+ dueDate: iso(r.due_date),
79
+ issuedAt: r.issued_at.toISOString(),
80
+ renegotiatedFromId: r.renegotiated_from_id,
81
+ createdAt: r.created_at.toISOString(),
82
+ amountPaid,
83
+ outstandingAmount: Math.max(0, Number((amount - amountPaid).toFixed(2))),
84
+ daysOverdue: r.days_overdue,
85
+ // A origem é o `fee_agreement_id` e nada mais. Derivar da competência —
86
+ // tentador, porque quase todo recorrente tem uma — classificaria como
87
+ // recorrente todo avulso que o operador competenciou, que é justamente o
88
+ // caso em que a distinção importa.
89
+ origin: r.fee_agreement_id ? 'recurring' : 'one_off',
90
+ generatedBy: r.generated_by,
91
+ description: r.description,
92
+ notes: metaText(r.metadata, 'notes'),
93
+ serviceCategory: metaText(r.metadata, 'serviceCategory'),
94
+ activeCharge: r.charge_id
95
+ ? {
96
+ id: r.charge_id,
97
+ status: r.charge_status,
98
+ means: (0, payment_means_catalog_js_1.availableMeansOf)(r.charge_metadata),
99
+ }
100
+ : null,
101
+ };
102
+ }
103
+ /**
104
+ * Descrição do recebível a partir dos seus itens.
105
+ *
106
+ * Hoje tanto a geração por competência quanto o avulso criam exatamente UM
107
+ * item, mas o schema permite vários (RFC §4) — então junta em vez de pegar o
108
+ * primeiro: com dois itens, "Honorários" sozinho esconderia metade da dívida.
109
+ */
110
+ const DESCRIPTION_SQL = `
111
+ (SELECT string_agg(i.description, ' · ' ORDER BY i.created_at, i.id)
112
+ FROM receivable_item i WHERE i.receivable_id = r.id)`;
113
+ const SELECT_RECEIVABLE = `
114
+ SELECT r.id, r.client_id, c.display_name AS client_name, r.fee_agreement_id, r.competence,
115
+ r.amount, r.status, ${EFFECTIVE_STATUS_SQL} AS effective_status, r.generated_by,
116
+ r.due_date, r.issued_at, r.renegotiated_from_id, r.created_at, r.metadata,
117
+ ${DESCRIPTION_SQL} AS description,
118
+ ac.id AS charge_id, ac.status AS charge_status, ac.metadata AS charge_metadata,
119
+ COALESCE((SELECT sum(p.amount) FROM payment p
120
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0) AS amount_paid,
121
+ GREATEST(0, COALESCE(CURRENT_DATE - r.due_date, 0))::int AS days_overdue
122
+ FROM receivable r
123
+ LEFT JOIN client c ON c.id = r.client_id AND c.deleted_at IS NULL
124
+ -- LATERAL, e não uma subquery por coluna: as três colunas da cobrança
125
+ -- precisam vir da MESMA linha. Três subqueries independentes poderiam, com
126
+ -- mais de uma cobrança viva, montar um Frankenstein com o id de uma e os
127
+ -- meios de outra.
128
+ LEFT JOIN LATERAL (
129
+ SELECT ch.id, ch.status, ch.metadata
130
+ FROM charge ch
131
+ WHERE ch.receivable_id = r.id
132
+ AND ch.deleted_at IS NULL
133
+ AND ch.status NOT IN ('canceled', 'refunded')
134
+ ORDER BY ch.created_at DESC
135
+ LIMIT 1
136
+ ) ac ON true`;
137
+ // ── Competência ──────────────────────────────────────────────────────────────
138
+ const COMPETENCE_RE = /^\d{4}-(0[1-9]|1[0-2])$/;
139
+ function assertCompetence(competence) {
140
+ if (!COMPETENCE_RE.test(competence)) {
141
+ throw new shared_1.ValidationError('Competência deve estar no formato YYYY-MM, com mês entre 01 e 12');
142
+ }
143
+ }
144
+ /**
145
+ * Data de vencimento de uma competência, respeitando o `due_day` do honorário.
146
+ *
147
+ * `due_day` é limitado a 28 no schema justamente para não existir "dia 31 de
148
+ * fevereiro"; ainda assim clampamos ao último dia do mês, porque a regra de
149
+ * negócio não pode depender de uma constraint continuar existindo.
150
+ */
151
+ function dueDateFor(competence, dueDay) {
152
+ assertCompetence(competence);
153
+ const [year, month] = competence.split('-').map(Number);
154
+ const lastDay = new Date(Date.UTC(year, month, 0)).getUTCDate();
155
+ const day = Math.min(Math.max(dueDay ?? lastDay, 1), lastDay);
156
+ return `${competence}-${String(day).padStart(2, '0')}`;
157
+ }
158
+ const DUE_DATE_RE = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
159
+ /**
160
+ * Janela tolerada entre a competência e o vencimento de um lançamento avulso.
161
+ *
162
+ * No fluxo por competência não existe folga: `dueDateFor` devolve sempre uma data
163
+ * DENTRO do mês da competência. O avulso relaxa isso de propósito — competência e
164
+ * vencimento são campos independentes do payload — e é justamente aí que um erro
165
+ * de digitação vira "honorários de março/2027 vencendo em agosto/2026" no e-mail
166
+ * que o cliente lê.
167
+ *
168
+ * A folga é assimétrica porque a prática comercial é assimétrica: faturar um mês
169
+ * adiantado acontece; dar três meses de prazo acontece; sete meses de distância,
170
+ * em qualquer direção, não é arranjo comercial — é dedo trocado.
171
+ */
172
+ const DUE_MONTHS_BEFORE_COMPETENCE = 1;
173
+ const DUE_MONTHS_AFTER_COMPETENCE = 3;
174
+ /**
175
+ * A competência e o vencimento informados fazem sentido juntos?
176
+ *
177
+ * Aritmética de mês em inteiros, não em `Date`: o que importa é a distância entre
178
+ * dois meses do calendário, e converter para instante só introduziria fuso onde
179
+ * não há hora nenhuma envolvida.
180
+ */
181
+ function checkCompetenceDueDate(competence, dueDate) {
182
+ assertCompetence(competence);
183
+ if (!DUE_DATE_RE.test(dueDate)) {
184
+ throw new shared_1.ValidationError('Vencimento deve estar no formato YYYY-MM-DD');
185
+ }
186
+ const monthIndex = (year, month) => year * 12 + (month - 1);
187
+ const [cy, cm] = competence.split('-').map(Number);
188
+ const [dy, dm] = dueDate.split('-').map(Number);
189
+ const monthsFromCompetence = monthIndex(dy, dm) - monthIndex(cy, cm);
190
+ const coherent = monthsFromCompetence >= -DUE_MONTHS_BEFORE_COMPETENCE &&
191
+ monthsFromCompetence <= DUE_MONTHS_AFTER_COMPETENCE;
192
+ return { coherent, monthsFromCompetence };
193
+ }
194
+ /**
195
+ * Mensagem do 422. Diz o que veio, qual é a distância e como confirmar — quem lê
196
+ * precisa conseguir decidir entre "corrigi o dedo trocado" e "é isso mesmo".
197
+ */
198
+ function competenceMismatchMessage(competence, dueDate, monthsFromCompetence) {
199
+ const distance = Math.abs(monthsFromCompetence);
200
+ const direction = monthsFromCompetence < 0 ? 'antes' : 'depois';
201
+ const plural = distance === 1 ? 'mês' : 'meses';
202
+ return (`Competência ${competence} com vencimento em ${dueDate}: o vencimento está ` +
203
+ `${distance} ${plural} ${direction} do mês da competência. O esperado é entre ` +
204
+ `${DUE_MONTHS_BEFORE_COMPETENCE} mês antes e ${DUE_MONTHS_AFTER_COMPETENCE} meses ` +
205
+ `depois. Se a combinação está correta, reenvie confirmando explicitamente ` +
206
+ `(competenceMismatchAck).`);
207
+ }
208
+ /** Ver `FeeCompetenceVerdict`. Pura: nenhum I/O, nenhum relógio. */
209
+ function classifyFeeForCompetence(fee, competence) {
210
+ if (fee.status === 'suspended')
211
+ return 'suspended';
212
+ if (fee.status !== 'active')
213
+ return 'canceled';
214
+ const first = `${competence}-01`;
215
+ const [year, month] = competence.split('-').map(Number);
216
+ const last = `${competence}-${String(new Date(Date.UTC(year, month, 0)).getUTCDate()).padStart(2, '0')}`;
217
+ // Vigência: o honorário precisa estar valendo em ALGUM dia da competência.
218
+ if (fee.startsOn && fee.startsOn > last)
219
+ return 'before_term';
220
+ if (fee.endsOn && fee.endsOn < first)
221
+ return 'after_term';
222
+ switch (fee.periodicity) {
223
+ case 'monthly':
224
+ return 'eligible';
225
+ // Trimestral/anual ancoram no mês de início da vigência — sem `startsOn` não
226
+ // há âncora, e gerar todo mês seria cobrar a mais. Fail-safe: não gera.
227
+ case 'quarterly': {
228
+ if (!fee.startsOn)
229
+ return 'no_anchor';
230
+ const anchor = Number(fee.startsOn.slice(5, 7));
231
+ return (month - anchor) % 3 === 0 ? 'eligible' : 'off_cycle';
232
+ }
233
+ case 'yearly': {
234
+ if (!fee.startsOn)
235
+ return 'no_anchor';
236
+ return Number(fee.startsOn.slice(5, 7)) === month ? 'eligible' : 'off_cycle';
237
+ }
238
+ // Avulso nunca é gerado em lote: nasce por lançamento manual.
239
+ case 'one_time':
240
+ return 'one_time';
241
+ default:
242
+ return 'off_cycle';
243
+ }
244
+ }
245
+ /** Um honorário vale para a competência? Considera vigência e periodicidade. */
246
+ function feeAppliesTo(fee, competence) {
247
+ return classifyFeeForCompetence(fee, competence) === 'eligible';
248
+ }
249
+ /**
250
+ * Gera os recebíveis de uma competência a partir dos honorários ativos.
251
+ *
252
+ * Idempotente por construção: o índice único `(tenant_id, fee_agreement_id,
253
+ * competence)` do M0 é a garantia real, e o `ON CONFLICT DO NOTHING` a
254
+ * transforma em "pular" em vez de "explodir". Rodar duas vezes no mesmo mês não
255
+ * duplica cobrança — o que aqui não é detalhe técnico: cobrar o cliente duas
256
+ * vezes é o erro que destrói a confiança no sistema.
257
+ */
258
+ async function generateReceivablesForCompetence(tx, input) {
259
+ assertCompetence(input.competence);
260
+ const source = input.source ?? 'manual';
261
+ const fees = await tx `
262
+ SELECT id, client_id, description, amount, periodicity, due_day, discount, status, starts_on, ends_on
263
+ FROM fee_agreement
264
+ WHERE deleted_at IS NULL
265
+ ${input.feeAgreementIds?.length ? tx `AND id IN ${tx(input.feeAgreementIds)}` : tx ``}
266
+ `;
267
+ const created = [];
268
+ let skipped = 0;
269
+ let notApplicable = 0;
270
+ for (const fee of fees) {
271
+ // A decisão de gerar vem de UM lugar só.
272
+ //
273
+ // Até a fase 2.3 havia duas: um `AND status = 'active'` no SELECT acima e a
274
+ // checagem de status dentro de `feeAppliesTo`. As duas concordavam, e por
275
+ // isso o arranjo parecia inofensivo — mas um teste de mutação mostrou o
276
+ // custo: com a regra do status quebrada dentro da função, o SELECT continuava
277
+ // segurando, e nenhum teste de "suspenso não gera" reprovava. A garantia
278
+ // estava numa cláusula SQL que ninguém estava testando, enquanto o dry-run
279
+ // — que decide se o scheduler pode ser ligado — usava a OUTRA cópia.
280
+ //
281
+ // Duas cópias de uma regra financeira só precisam divergir uma vez.
282
+ const verdict = classifyFeeForCompetence({
283
+ periodicity: fee.periodicity,
284
+ startsOn: iso(fee.starts_on),
285
+ endsOn: iso(fee.ends_on),
286
+ status: fee.status,
287
+ }, input.competence);
288
+ if (verdict !== 'eligible') {
289
+ // Suspenso e encerrado ficam FORA da contagem, e não é descuido: quem lê
290
+ // "3 fora de vigência" na tela está perguntando quantos acordos vigentes o
291
+ // calendário deixou de fora nesta competência. Um acordo cancelado no ano
292
+ // passado não é resposta a essa pergunta, e somá-lo aqui inflaria o número
293
+ // todo mês, para sempre, com o acervo morto do escritório.
294
+ if (verdict !== 'suspended' && verdict !== 'canceled')
295
+ notApplicable += 1;
296
+ continue;
297
+ }
298
+ // O desconto acordado entra no valor do recebível: a dívida é o líquido, e
299
+ // guardar o bruto obrigaria toda leitura a lembrar de subtrair.
300
+ const amount = Math.max(0, Number(fee.amount) - Number(fee.discount));
301
+ const dueDate = dueDateFor(input.competence, fee.due_day);
302
+ const receivableId = (0, shared_1.uuidv7)();
303
+ const rows = await tx `
304
+ INSERT INTO receivable (id, tenant_id, client_id, fee_agreement_id, competence,
305
+ amount, status, due_date, created_by, generated_by)
306
+ VALUES (${receivableId},
307
+ (NULLIF(current_setting('app.current_tenant', true), ''))::uuid,
308
+ ${fee.client_id}, ${fee.id}, ${input.competence},
309
+ ${amount}, 'open', ${dueDate}, ${input.createdBy ?? null}, ${source})
310
+ -- O predicado precisa casar EXATAMENTE com o do índice parcial do M0,
311
+ -- senão o Postgres não reconhece o índice e o INSERT volta a estourar.
312
+ ON CONFLICT (tenant_id, fee_agreement_id, competence)
313
+ WHERE fee_agreement_id IS NOT NULL AND competence IS NOT NULL AND deleted_at IS NULL
314
+ DO NOTHING
315
+ RETURNING id
316
+ `;
317
+ if (!rows[0]) {
318
+ skipped += 1;
319
+ continue;
320
+ }
321
+ await tx `
322
+ INSERT INTO receivable_item (id, tenant_id, receivable_id, description, amount)
323
+ VALUES (${(0, shared_1.uuidv7)()},
324
+ (NULLIF(current_setting('app.current_tenant', true), ''))::uuid,
325
+ ${receivableId}, ${fee.description}, ${amount})
326
+ `;
327
+ const full = await getReceivable(tx, receivableId);
328
+ created.push(full);
329
+ }
330
+ return { competence: input.competence, created, skipped, notApplicable };
331
+ }
332
+ /**
333
+ * Lançamento avulso — serviço extra que não vem de honorário recorrente.
334
+ *
335
+ * A guarda de coerência mora AQUI, e não na rota, porque quem chama o domínio
336
+ * direto (script de importação, backfill, outro serviço) precisa da mesma
337
+ * proteção que o operador tem pela tela. Uma validação só na borda HTTP protege
338
+ * a borda HTTP.
339
+ */
340
+ async function createOneOffReceivable(tx, input) {
341
+ if (input.amount <= 0)
342
+ throw new shared_1.ValidationError('Valor deve ser maior que zero');
343
+ if (input.competence) {
344
+ const check = checkCompetenceDueDate(input.competence, input.dueDate);
345
+ if (!check.coherent && !input.competenceMismatchAck) {
346
+ throw new shared_1.ValidationError(competenceMismatchMessage(input.competence, input.dueDate, check.monthsFromCompetence));
347
+ }
348
+ }
349
+ const id = (0, shared_1.uuidv7)();
350
+ const notes = input.notes?.trim() || null;
351
+ const serviceCategory = input.serviceCategory?.trim() || null;
352
+ const metadata = {};
353
+ if (notes)
354
+ metadata.notes = notes;
355
+ if (serviceCategory)
356
+ metadata.serviceCategory = serviceCategory;
357
+ // `ON CONFLICT DO NOTHING` sobre a chave da tentativa: quem chega primeiro
358
+ // grava, quem repete não insere e é devolvido ao recebível existente. A
359
+ // alternativa — consultar antes e inserir depois — deixa uma janela entre as
360
+ // duas operações, e duplo clique acontece exatamente dentro dela.
361
+ const inserted = await tx `
362
+ INSERT INTO receivable (id, tenant_id, client_id, fee_agreement_id, competence,
363
+ amount, status, due_date, created_by, idempotency_key, metadata)
364
+ VALUES (${id},
365
+ (NULLIF(current_setting('app.current_tenant', true), ''))::uuid,
366
+ ${input.clientId}, NULL, ${input.competence ?? null},
367
+ ${input.amount}, 'open', ${input.dueDate}, ${input.createdBy ?? null},
368
+ ${input.idempotencyKey ?? null}, ${tx.json(metadata)})
369
+ ON CONFLICT (tenant_id, idempotency_key) WHERE idempotency_key IS NOT NULL
370
+ DO NOTHING
371
+ RETURNING id
372
+ `;
373
+ if (!inserted[0]) {
374
+ // Tentativa repetida. Devolve o que a primeira criou — nunca um erro: para
375
+ // quem clicou duas vezes, o lançamento deu certo, e um 409 mandaria a pessoa
376
+ // tentar de novo.
377
+ const existing = await tx `
378
+ SELECT id FROM receivable
379
+ WHERE idempotency_key = ${input.idempotencyKey ?? null} AND deleted_at IS NULL
380
+ `;
381
+ if (!existing[0])
382
+ throw new shared_1.ConflictError('Lançamento avulso em conflito');
383
+ return getReceivable(tx, existing[0].id);
384
+ }
385
+ await tx `
386
+ INSERT INTO receivable_item (id, tenant_id, receivable_id, description, amount)
387
+ VALUES (${(0, shared_1.uuidv7)()},
388
+ (NULLIF(current_setting('app.current_tenant', true), ''))::uuid,
389
+ ${id}, ${input.description}, ${input.amount})
390
+ `;
391
+ return getReceivable(tx, id);
392
+ }
393
+ /**
394
+ * O WHERE compartilhado entre a página e a contagem.
395
+ *
396
+ * Escrito uma vez de propósito: quando a lista e o total repetiam os mesmos
397
+ * predicados lado a lado, bastava acrescentar um filtro num deles para a tela
398
+ * dizer "mostrando 12 de 47" com os dois números medindo carteiras diferentes.
399
+ */
400
+ function receivableWhere(tx, filter) {
401
+ const search = filter.search?.trim();
402
+ return tx `
403
+ r.deleted_at IS NULL
404
+ ${filter.clientId ? tx `AND r.client_id = ${filter.clientId}` : tx ``}
405
+ ${filter.competence ? tx `AND r.competence = ${filter.competence}` : tx ``}
406
+ ${filter.status ? tx `AND ${tx.unsafe(EFFECTIVE_STATUS_SQL)} = ${filter.status}` : tx ``}
407
+ ${filter.openOnly ? tx `AND r.status IN ('open','partially_paid','overdue')` : tx ``}
408
+ ${filter.overdueOnly ? tx `AND ${tx.unsafe(EFFECTIVE_STATUS_SQL)} = 'overdue'` : tx ``}
409
+ ${filter.origin
410
+ ? filter.origin === 'recurring'
411
+ ? tx `AND r.fee_agreement_id IS NOT NULL`
412
+ : tx `AND r.fee_agreement_id IS NULL`
413
+ : tx ``}
414
+ ${filter.dueFrom ? tx `AND r.due_date >= ${filter.dueFrom}::date` : tx ``}
415
+ ${filter.dueTo ? tx `AND r.due_date <= ${filter.dueTo}::date` : tx ``}
416
+ ${search
417
+ ? tx `AND (c.display_name ILIKE ${'%' + search + '%'}
418
+ OR EXISTS (SELECT 1 FROM receivable_item i
419
+ WHERE i.receivable_id = r.id
420
+ AND i.description ILIKE ${'%' + search + '%'}))`
421
+ : tx ``}
422
+ `;
423
+ }
424
+ async function listReceivables(tx, filter = {}) {
425
+ const limit = Math.min(Math.max(filter.limit ?? 50, 1), 200);
426
+ const offset = Math.max(filter.offset ?? 0, 0);
427
+ const where = receivableWhere(tx, filter);
428
+ const rows = await tx `
429
+ ${tx.unsafe(SELECT_RECEIVABLE)}
430
+ WHERE ${where}
431
+ ORDER BY r.due_date NULLS LAST, r.created_at
432
+ LIMIT ${limit} OFFSET ${offset}
433
+ `;
434
+ // O `LEFT JOIN client` acompanha a contagem porque a busca textual alcança o
435
+ // nome do cliente: sem ele, filtrar por nome quebraria o total.
436
+ const totals = await tx `
437
+ SELECT count(*) AS n FROM receivable r
438
+ LEFT JOIN client c ON c.id = r.client_id AND c.deleted_at IS NULL
439
+ WHERE ${where}
440
+ `;
441
+ return { items: rows.map(mapReceivable), total: Number(totals[0]?.n ?? 0) };
442
+ }
443
+ async function getReceivable(tx, id) {
444
+ const rows = await tx `
445
+ ${tx.unsafe(SELECT_RECEIVABLE)} WHERE r.id = ${id} AND r.deleted_at IS NULL
446
+ `;
447
+ const row = rows[0];
448
+ if (!row)
449
+ throw new shared_1.NotFoundError('Recebível não encontrado');
450
+ return mapReceivable(row);
451
+ }
452
+ async function listReceivableItems(tx, receivableId) {
453
+ const rows = await tx `
454
+ SELECT id, receivable_id, description, amount, service_item_ref, created_at
455
+ FROM receivable_item WHERE receivable_id = ${receivableId} ORDER BY created_at
456
+ `;
457
+ return rows.map((r) => ({
458
+ id: r.id,
459
+ receivableId: r.receivable_id,
460
+ description: r.description,
461
+ amount: Number(r.amount),
462
+ serviceItemRef: r.service_item_ref,
463
+ createdAt: r.created_at.toISOString(),
464
+ }));
465
+ }
466
+ async function listPayments(tx, receivableId) {
467
+ const rows = await tx `
468
+ SELECT id, receivable_id, charge_id, amount, method, status, paid_at, created_at
469
+ FROM payment WHERE receivable_id = ${receivableId} ORDER BY paid_at
470
+ `;
471
+ return rows.map((r) => ({
472
+ id: r.id,
473
+ receivableId: r.receivable_id,
474
+ chargeId: r.charge_id,
475
+ amount: Number(r.amount),
476
+ method: r.method,
477
+ status: r.status,
478
+ paidAt: r.paid_at.toISOString(),
479
+ createdAt: r.created_at.toISOString(),
480
+ }));
481
+ }
482
+ /**
483
+ * Registra dinheiro recebido e reavalia o status do recebível.
484
+ *
485
+ * A soma dos pagamentos confirmados é a fonte da verdade do que foi pago — o
486
+ * status é consequência dela, nunca o contrário. Por isso o recálculo lê a soma
487
+ * do banco em vez de somar em memória: dois lançamentos concorrentes não podem
488
+ * produzir um `paid` com saldo em aberto.
489
+ */
490
+ async function registerPayment(tx, input) {
491
+ if (input.amount <= 0)
492
+ throw new shared_1.ValidationError('Valor do pagamento deve ser maior que zero');
493
+ const current = await getReceivable(tx, input.receivableId);
494
+ if (current.status === 'canceled') {
495
+ throw new shared_1.ConflictError('Recebível cancelado não aceita baixa');
496
+ }
497
+ if (input.amount > current.outstandingAmount + 0.001) {
498
+ throw new shared_1.ValidationError(`Valor excede o saldo em aberto (${current.outstandingAmount.toFixed(2)})`);
499
+ }
500
+ await tx `
501
+ INSERT INTO payment (id, tenant_id, receivable_id, charge_id, amount, method, status, paid_at, metadata)
502
+ VALUES (${(0, shared_1.uuidv7)()},
503
+ (NULLIF(current_setting('app.current_tenant', true), ''))::uuid,
504
+ ${input.receivableId}, ${input.chargeId ?? null}, ${input.amount},
505
+ ${input.method ?? 'manual'}, 'confirmed',
506
+ ${input.paidAt ?? new Date().toISOString()},
507
+ ${tx.json({ note: input.note ?? null })})
508
+ `;
509
+ const [totals] = await tx `
510
+ SELECT COALESCE((SELECT sum(p.amount) FROM payment p
511
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0) AS paid,
512
+ r.amount
513
+ FROM receivable r WHERE r.id = ${input.receivableId}
514
+ `;
515
+ const paid = Number(totals.paid);
516
+ const total = Number(totals.amount);
517
+ // Tolerância de um centavo: `numeric(14,2)` não sofre erro de ponto flutuante,
518
+ // mas o valor chega da borda HTTP como number — e 0.1+0.2 continua sendo
519
+ // 0.30000000000000004 em JavaScript.
520
+ const nextStatus = paid + 0.001 >= total ? 'paid' : 'partially_paid';
521
+ await tx `
522
+ UPDATE receivable
523
+ SET status = ${nextStatus},
524
+ updated_at = now(),
525
+ version = version + 1
526
+ WHERE id = ${input.receivableId}
527
+ `;
528
+ return getReceivable(tx, input.receivableId);
529
+ }
530
+ /**
531
+ * Anula a liquidação registrada para uma cobrança — o dinheiro nunca entrou.
532
+ *
533
+ * Não confundir com estorno. No estorno o dinheiro **entrou e saiu**: são dois
534
+ * fatos de caixa, a dívida foi quitada, e reabri-la seria cobrar de novo algo
535
+ * que foi pago. Aqui não há fato novo — há um fato anterior que deixou de valer,
536
+ * e manter o recebível quitado seria o sistema afirmando um recebimento que a
537
+ * própria origem já negou.
538
+ *
539
+ * **Nada é apagado.** A linha de `payment` permanece com valor, método e data em
540
+ * que se acreditou ter recebido; ela sai do saldo e passa a dizer quando e por
541
+ * que foi anulada. `charge.paid_at` também permanece — é o registro de quando a
542
+ * cobrança esteve liquidada.
543
+ *
544
+ * **Idempotente por construção:** o `UPDATE` só alcança pagamentos ainda
545
+ * `confirmed`. Uma segunda reversão do mesmo evento encontra zero linhas, não
546
+ * mexe em nada e devolve `reversedPayments: 0`. Não há contador a decrementar
547
+ * duas vezes.
548
+ *
549
+ * Só toca pagamentos **desta cobrança**. Uma baixa manual que o escritório deu
550
+ * por fora (`charge_id IS NULL`) é outro fato, de outra origem, e o gateway não
551
+ * tem autoridade sobre ela.
552
+ */
553
+ async function reverseSettlementForCharge(tx, chargeId, reason) {
554
+ const reversed = await tx `
555
+ UPDATE payment
556
+ SET status = 'reversed', reversed_at = now(), reversal_reason = ${reason}
557
+ WHERE charge_id = ${chargeId} AND status = 'confirmed'
558
+ RETURNING receivable_id, amount
559
+ `;
560
+ // A cobrança sai de `paid` mesmo quando não havia pagamento a anular: o evento
561
+ // é da origem, e o estado tem de refletir o que ela diz. `reversed` não entra
562
+ // na lista de cobranças mortas — o boleto ou o PIX continuam pagáveis, e esta
563
+ // segue sendo a cobrança viva do recebível.
564
+ await tx `
565
+ UPDATE charge
566
+ SET status = 'reversed', reversed_at = now(), updated_at = now()
567
+ WHERE id = ${chargeId} AND status IN ('paid', 'sent', 'pending', 'overdue')
568
+ `;
569
+ const receivableId = reversed[0]?.receivable_id ?? null;
570
+ const reversedAmount = reversed.reduce((sum, r) => sum + Number(r.amount), 0);
571
+ if (!receivableId) {
572
+ return {
573
+ reversedPayments: reversed.length,
574
+ reversedAmount,
575
+ receivableId: null,
576
+ receivable: null,
577
+ };
578
+ }
579
+ // O status do recebível é recalculado a partir do que SOBROU de confirmado —
580
+ // nunca assumido como `open`. Uma baixa parcial anterior, ou uma baixa manual
581
+ // do escritório, continua valendo e o recebível continua parcialmente pago.
582
+ const [totals] = await tx `
583
+ SELECT COALESCE((SELECT sum(p.amount) FROM payment p
584
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0) AS paid,
585
+ r.amount
586
+ FROM receivable r WHERE r.id = ${receivableId}
587
+ `;
588
+ const paid = Number(totals.paid);
589
+ const total = Number(totals.amount);
590
+ const nextStatus = paid + 0.001 >= total ? 'paid' : paid > 0 ? 'partially_paid' : 'open';
591
+ // `canceled`, `renegotiated` e `written_off` são decisões do escritório sobre
592
+ // a dívida, e um evento de gateway não as revoga.
593
+ await tx `
594
+ UPDATE receivable
595
+ SET status = ${nextStatus}, updated_at = now(), version = version + 1
596
+ WHERE id = ${receivableId}
597
+ AND status IN ('open', 'partially_paid', 'paid', 'overdue')
598
+ `;
599
+ return {
600
+ reversedPayments: reversed.length,
601
+ reversedAmount,
602
+ receivableId,
603
+ receivable: await getReceivable(tx, receivableId),
604
+ };
605
+ }
606
+ async function cancelReceivable(tx, id) {
607
+ const current = await getReceivable(tx, id);
608
+ if (current.amountPaid > 0) {
609
+ throw new shared_1.ConflictError('Recebível com pagamento registrado não pode ser cancelado');
610
+ }
611
+ await tx `
612
+ UPDATE receivable SET status = 'canceled', updated_at = now(), version = version + 1
613
+ WHERE id = ${id} AND deleted_at IS NULL
614
+ `;
615
+ return getReceivable(tx, id);
616
+ }
617
+ /**
618
+ * Materializa a transição para `overdue`.
619
+ *
620
+ * A leitura já deriva o vencido (ver nota no topo) — esta função existe para dar
621
+ * um INSTANTE à transição, que é o que a régua de cobrança precisa para disparar
622
+ * `RECEIVABLE_OVERDUE` uma única vez. Retorna os ids afetados justamente para
623
+ * quem for emitir os eventos na próxima onda.
624
+ */
625
+ async function markOverdueReceivables(tx) {
626
+ const rows = await tx `
627
+ UPDATE receivable
628
+ SET status = 'overdue', updated_at = now(), version = version + 1
629
+ WHERE deleted_at IS NULL
630
+ AND status = 'open'
631
+ AND due_date IS NOT NULL
632
+ AND due_date < CURRENT_DATE
633
+ RETURNING id
634
+ `;
635
+ return rows.map((r) => r.id);
636
+ }
637
+ async function financialSummary(tx) {
638
+ const [r] = await tx `
639
+ WITH base AS (
640
+ SELECT r.*, ${tx.unsafe(EFFECTIVE_STATUS_SQL)} AS eff,
641
+ COALESCE((SELECT sum(p.amount) FROM payment p
642
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0) AS paid
643
+ FROM receivable r WHERE r.deleted_at IS NULL AND r.status <> 'canceled'
644
+ )
645
+ SELECT
646
+ COALESCE(sum(amount), 0) AS total_receivable,
647
+ COALESCE(sum(amount - paid) FILTER (WHERE eff IN ('open','partially_paid','overdue')), 0) AS total_open,
648
+ COALESCE(sum(amount - paid) FILTER (WHERE eff = 'overdue'), 0) AS total_overdue,
649
+ COALESCE(sum(paid), 0) AS total_paid,
650
+ COALESCE(sum(amount - paid) FILTER (
651
+ WHERE eff IN ('open','partially_paid')
652
+ AND due_date BETWEEN CURRENT_DATE AND CURRENT_DATE + 7), 0) AS total_due_soon,
653
+ COALESCE(count(DISTINCT client_id) FILTER (WHERE eff = 'overdue'), 0)::int AS overdue_client_count,
654
+ COALESCE(count(*) FILTER (WHERE eff IN ('open','partially_paid','overdue')), 0)::int AS open_count,
655
+ COALESCE(count(*) FILTER (WHERE eff = 'overdue'), 0)::int AS overdue_count
656
+ FROM base
657
+ `;
658
+ return {
659
+ totalReceivable: Number(r.total_receivable),
660
+ totalOpen: Number(r.total_open),
661
+ totalOverdue: Number(r.total_overdue),
662
+ totalPaid: Number(r.total_paid),
663
+ totalDueSoon: Number(r.total_due_soon),
664
+ overdueClientCount: r.overdue_client_count,
665
+ openCount: r.open_count,
666
+ overdueCount: r.overdue_count,
667
+ };
668
+ }
669
+ /**
670
+ * Faixas de aging. Padrão do produto, **não** política imutável: as faixas são
671
+ * parâmetro justamente para que um escritório possa usar as suas sem alteração
672
+ * de código.
673
+ */
674
+ exports.DEFAULT_AGING_BUCKETS = [
675
+ { label: '1-7', from: 1, to: 7 },
676
+ { label: '8-15', from: 8, to: 15 },
677
+ { label: '16-30', from: 16, to: 30 },
678
+ { label: '31-60', from: 31, to: 60 },
679
+ { label: '61-90', from: 61, to: 90 },
680
+ { label: '90+', from: 91, to: null },
681
+ ];
682
+ async function agingBuckets(tx, buckets = exports.DEFAULT_AGING_BUCKETS) {
683
+ const rows = await tx `
684
+ SELECT (CURRENT_DATE - r.due_date)::int AS days_overdue,
685
+ (r.amount - COALESCE((SELECT sum(p.amount) FROM payment p
686
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0)) AS outstanding,
687
+ r.client_id
688
+ FROM receivable r
689
+ WHERE r.deleted_at IS NULL
690
+ AND r.status IN ('open','partially_paid','overdue')
691
+ AND r.due_date IS NOT NULL
692
+ AND r.due_date < CURRENT_DATE
693
+ `;
694
+ return buckets.map((b) => {
695
+ const inBucket = rows.filter((r) => r.days_overdue >= b.from && (b.to === null || r.days_overdue <= b.to));
696
+ return {
697
+ ...b,
698
+ amount: Number(inBucket.reduce((s, r) => s + Number(r.outstanding), 0).toFixed(2)),
699
+ count: inBucket.length,
700
+ clientCount: new Set(inBucket.map((r) => r.client_id)).size,
701
+ };
702
+ });
703
+ }
704
+ /** Situação financeira de um cliente — usada no console e no portal. */
705
+ async function clientFinancialSummary(tx, clientId) {
706
+ const [r] = await tx `
707
+ WITH base AS (
708
+ SELECT r.*, ${tx.unsafe(EFFECTIVE_STATUS_SQL)} AS eff,
709
+ COALESCE((SELECT sum(p.amount) FROM payment p
710
+ WHERE p.receivable_id = r.id AND p.status = 'confirmed'), 0) AS paid
711
+ FROM receivable r
712
+ WHERE r.deleted_at IS NULL AND r.client_id = ${clientId} AND r.status <> 'canceled'
713
+ )
714
+ SELECT
715
+ COALESCE(sum(amount - paid) FILTER (WHERE eff IN ('open','partially_paid','overdue')), 0) AS open,
716
+ COALESCE(sum(amount - paid) FILTER (WHERE eff = 'overdue'), 0) AS overdue,
717
+ COALESCE(sum(paid), 0) AS paid,
718
+ min(due_date) FILTER (WHERE eff IN ('open','partially_paid')) AS next_due
719
+ FROM base
720
+ `;
721
+ return {
722
+ open: Number(r.open),
723
+ overdue: Number(r.overdue),
724
+ paid: Number(r.paid),
725
+ nextDueDate: iso(r.next_due),
726
+ };
727
+ }
728
+ //# sourceMappingURL=ar-repository.js.map