@voyant-travel/finance 0.119.5

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 (294) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +192 -0
  3. package/dist/action-ledger-drift.d.ts +29 -0
  4. package/dist/action-ledger-drift.d.ts.map +1 -0
  5. package/dist/action-ledger-drift.js +166 -0
  6. package/dist/booking-tax.d.ts +124 -0
  7. package/dist/booking-tax.d.ts.map +1 -0
  8. package/dist/booking-tax.js +264 -0
  9. package/dist/checkout-routes.d.ts +1154 -0
  10. package/dist/checkout-routes.d.ts.map +1 -0
  11. package/dist/checkout-routes.js +116 -0
  12. package/dist/checkout-service-plan.d.ts +137 -0
  13. package/dist/checkout-service-plan.d.ts.map +1 -0
  14. package/dist/checkout-service-plan.js +119 -0
  15. package/dist/checkout-service.d.ts +9 -0
  16. package/dist/checkout-service.d.ts.map +1 -0
  17. package/dist/checkout-service.js +324 -0
  18. package/dist/checkout-validation.d.ts +1682 -0
  19. package/dist/checkout-validation.d.ts.map +1 -0
  20. package/dist/checkout-validation.js +228 -0
  21. package/dist/document-download.d.ts +3 -0
  22. package/dist/document-download.d.ts.map +1 -0
  23. package/dist/document-download.js +1 -0
  24. package/dist/fx-money.d.ts +17 -0
  25. package/dist/fx-money.d.ts.map +1 -0
  26. package/dist/fx-money.js +194 -0
  27. package/dist/index.d.ts +65 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +108 -0
  30. package/dist/invoice-fx.d.ts +134 -0
  31. package/dist/invoice-fx.d.ts.map +1 -0
  32. package/dist/invoice-fx.js +240 -0
  33. package/dist/invoice-number-errors.d.ts +2 -0
  34. package/dist/invoice-number-errors.d.ts.map +1 -0
  35. package/dist/invoice-number-errors.js +58 -0
  36. package/dist/markets-ref.d.ts +149 -0
  37. package/dist/markets-ref.d.ts.map +1 -0
  38. package/dist/markets-ref.js +17 -0
  39. package/dist/payment-link.d.ts +23 -0
  40. package/dist/payment-link.d.ts.map +1 -0
  41. package/dist/payment-link.js +30 -0
  42. package/dist/payment-policy.d.ts +113 -0
  43. package/dist/payment-policy.d.ts.map +1 -0
  44. package/dist/payment-policy.js +193 -0
  45. package/dist/route-runtime.d.ts +22 -0
  46. package/dist/route-runtime.d.ts.map +1 -0
  47. package/dist/route-runtime.js +18 -0
  48. package/dist/routes-action-ledger.d.ts +181 -0
  49. package/dist/routes-action-ledger.d.ts.map +1 -0
  50. package/dist/routes-action-ledger.js +142 -0
  51. package/dist/routes-booking-billing.d.ts +852 -0
  52. package/dist/routes-booking-billing.d.ts.map +1 -0
  53. package/dist/routes-booking-billing.js +223 -0
  54. package/dist/routes-booking-create.d.ts +3 -0
  55. package/dist/routes-booking-create.d.ts.map +1 -0
  56. package/dist/routes-booking-create.js +194 -0
  57. package/dist/routes-booking-reads.d.ts +46 -0
  58. package/dist/routes-booking-reads.d.ts.map +1 -0
  59. package/dist/routes-booking-reads.js +20 -0
  60. package/dist/routes-documents.d.ts +195 -0
  61. package/dist/routes-documents.d.ts.map +1 -0
  62. package/dist/routes-documents.js +93 -0
  63. package/dist/routes-invoice-core.d.ts +794 -0
  64. package/dist/routes-invoice-core.d.ts.map +1 -0
  65. package/dist/routes-invoice-core.js +238 -0
  66. package/dist/routes-invoice-documents.d.ts +401 -0
  67. package/dist/routes-invoice-documents.d.ts.map +1 -0
  68. package/dist/routes-invoice-documents.js +91 -0
  69. package/dist/routes-invoice-issue.d.ts +384 -0
  70. package/dist/routes-invoice-issue.d.ts.map +1 -0
  71. package/dist/routes-invoice-issue.js +208 -0
  72. package/dist/routes-payment-processing.d.ts +1193 -0
  73. package/dist/routes-payment-processing.d.ts.map +1 -0
  74. package/dist/routes-payment-processing.js +238 -0
  75. package/dist/routes-payments.d.ts +309 -0
  76. package/dist/routes-payments.d.ts.map +1 -0
  77. package/dist/routes-payments.js +94 -0
  78. package/dist/routes-public.d.ts +1948 -0
  79. package/dist/routes-public.d.ts.map +1 -0
  80. package/dist/routes-public.js +275 -0
  81. package/dist/routes-reference-data.d.ts +977 -0
  82. package/dist/routes-reference-data.d.ts.map +1 -0
  83. package/dist/routes-reference-data.js +191 -0
  84. package/dist/routes-reports.d.ts +344 -0
  85. package/dist/routes-reports.d.ts.map +1 -0
  86. package/dist/routes-reports.js +93 -0
  87. package/dist/routes-runtime.d.ts +71 -0
  88. package/dist/routes-runtime.d.ts.map +1 -0
  89. package/dist/routes-runtime.js +59 -0
  90. package/dist/routes-settlement.d.ts +67 -0
  91. package/dist/routes-settlement.d.ts.map +1 -0
  92. package/dist/routes-settlement.js +23 -0
  93. package/dist/routes-shared.d.ts +35 -0
  94. package/dist/routes-shared.d.ts.map +1 -0
  95. package/dist/routes-shared.js +10 -0
  96. package/dist/routes-supplier-invoices.d.ts +778 -0
  97. package/dist/routes-supplier-invoices.d.ts.map +1 -0
  98. package/dist/routes-supplier-invoices.js +159 -0
  99. package/dist/routes-vouchers.d.ts +228 -0
  100. package/dist/routes-vouchers.d.ts.map +1 -0
  101. package/dist/routes-vouchers.js +54 -0
  102. package/dist/routes.d.ts +5577 -0
  103. package/dist/routes.d.ts.map +1 -0
  104. package/dist/routes.js +44 -0
  105. package/dist/schema/booking-billing.d.ts +1006 -0
  106. package/dist/schema/booking-billing.d.ts.map +1 -0
  107. package/dist/schema/booking-billing.js +106 -0
  108. package/dist/schema/enums.d.ts +48 -0
  109. package/dist/schema/enums.d.ts.map +1 -0
  110. package/dist/schema/enums.js +237 -0
  111. package/dist/schema/invoice-documents.d.ts +1245 -0
  112. package/dist/schema/invoice-documents.d.ts.map +1 -0
  113. package/dist/schema/invoice-documents.js +140 -0
  114. package/dist/schema/payment-instruments.d.ts +418 -0
  115. package/dist/schema/payment-instruments.d.ts.map +1 -0
  116. package/dist/schema/payment-instruments.js +45 -0
  117. package/dist/schema/payment-processing.d.ts +563 -0
  118. package/dist/schema/payment-processing.d.ts.map +1 -0
  119. package/dist/schema/payment-processing.js +65 -0
  120. package/dist/schema/payment-sessions.d.ts +728 -0
  121. package/dist/schema/payment-sessions.d.ts.map +1 -0
  122. package/dist/schema/payment-sessions.js +79 -0
  123. package/dist/schema/receivables.d.ts +1474 -0
  124. package/dist/schema/receivables.d.ts.map +1 -0
  125. package/dist/schema/receivables.js +179 -0
  126. package/dist/schema/relations.d.ts +82 -0
  127. package/dist/schema/relations.d.ts.map +1 -0
  128. package/dist/schema/relations.js +144 -0
  129. package/dist/schema/supplier-invoices.d.ts +1619 -0
  130. package/dist/schema/supplier-invoices.d.ts.map +1 -0
  131. package/dist/schema/supplier-invoices.js +228 -0
  132. package/dist/schema/tax.d.ts +712 -0
  133. package/dist/schema/tax.d.ts.map +1 -0
  134. package/dist/schema/tax.js +98 -0
  135. package/dist/schema/vouchers.d.ts +444 -0
  136. package/dist/schema/vouchers.d.ts.map +1 -0
  137. package/dist/schema/vouchers.js +64 -0
  138. package/dist/schema.d.ts +12 -0
  139. package/dist/schema.d.ts.map +1 -0
  140. package/dist/schema.js +11 -0
  141. package/dist/service-accountant-shares.d.ts +106 -0
  142. package/dist/service-accountant-shares.d.ts.map +1 -0
  143. package/dist/service-accountant-shares.js +331 -0
  144. package/dist/service-action-ledger-accounting.d.ts +104 -0
  145. package/dist/service-action-ledger-accounting.d.ts.map +1 -0
  146. package/dist/service-action-ledger-accounting.js +386 -0
  147. package/dist/service-action-ledger-booking-payments.d.ts +48 -0
  148. package/dist/service-action-ledger-booking-payments.d.ts.map +1 -0
  149. package/dist/service-action-ledger-booking-payments.js +178 -0
  150. package/dist/service-action-ledger-bookings.d.ts +44 -0
  151. package/dist/service-action-ledger-bookings.d.ts.map +1 -0
  152. package/dist/service-action-ledger-bookings.js +81 -0
  153. package/dist/service-action-ledger-payment-authorizations.d.ts +48 -0
  154. package/dist/service-action-ledger-payment-authorizations.d.ts.map +1 -0
  155. package/dist/service-action-ledger-payment-authorizations.js +209 -0
  156. package/dist/service-action-ledger-payment-sessions.d.ts +83 -0
  157. package/dist/service-action-ledger-payment-sessions.d.ts.map +1 -0
  158. package/dist/service-action-ledger-payment-sessions.js +294 -0
  159. package/dist/service-action-ledger-supplier-invoices.d.ts +27 -0
  160. package/dist/service-action-ledger-supplier-invoices.d.ts.map +1 -0
  161. package/dist/service-action-ledger-supplier-invoices.js +111 -0
  162. package/dist/service-action-ledger-supplier-payments.d.ts +21 -0
  163. package/dist/service-action-ledger-supplier-payments.d.ts.map +1 -0
  164. package/dist/service-action-ledger-supplier-payments.js +97 -0
  165. package/dist/service-action-ledger.d.ts +7 -0
  166. package/dist/service-action-ledger.d.ts.map +1 -0
  167. package/dist/service-action-ledger.js +6 -0
  168. package/dist/service-aggregates.d.ts +96 -0
  169. package/dist/service-aggregates.d.ts.map +1 -0
  170. package/dist/service-aggregates.js +294 -0
  171. package/dist/service-booking-billing.d.ts +2322 -0
  172. package/dist/service-booking-billing.d.ts.map +1 -0
  173. package/dist/service-booking-billing.js +8 -0
  174. package/dist/service-booking-create.d.ts +410 -0
  175. package/dist/service-booking-create.d.ts.map +1 -0
  176. package/dist/service-booking-create.js +1256 -0
  177. package/dist/service-booking-guarantees.d.ts +725 -0
  178. package/dist/service-booking-guarantees.d.ts.map +1 -0
  179. package/dist/service-booking-guarantees.js +153 -0
  180. package/dist/service-booking-item-billing.d.ts +1062 -0
  181. package/dist/service-booking-item-billing.d.ts.map +1 -0
  182. package/dist/service-booking-item-billing.js +77 -0
  183. package/dist/service-booking-payment-schedules.d.ts +557 -0
  184. package/dist/service-booking-payment-schedules.d.ts.map +1 -0
  185. package/dist/service-booking-payment-schedules.js +372 -0
  186. package/dist/service-bookings-dual-create.d.ts +308 -0
  187. package/dist/service-bookings-dual-create.d.ts.map +1 -0
  188. package/dist/service-bookings-dual-create.js +131 -0
  189. package/dist/service-boundary-sql.d.ts +6 -0
  190. package/dist/service-boundary-sql.d.ts.map +1 -0
  191. package/dist/service-boundary-sql.js +15 -0
  192. package/dist/service-cost-categories.d.ts +26 -0
  193. package/dist/service-cost-categories.d.ts.map +1 -0
  194. package/dist/service-cost-categories.js +76 -0
  195. package/dist/service-documents.d.ts +80 -0
  196. package/dist/service-documents.d.ts.map +1 -0
  197. package/dist/service-documents.js +228 -0
  198. package/dist/service-invoice-artifacts.d.ts +246 -0
  199. package/dist/service-invoice-artifacts.d.ts.map +1 -0
  200. package/dist/service-invoice-artifacts.js +277 -0
  201. package/dist/service-invoice-core.d.ts +405 -0
  202. package/dist/service-invoice-core.d.ts.map +1 -0
  203. package/dist/service-invoice-core.js +290 -0
  204. package/dist/service-invoice-credit-notes.d.ts +973 -0
  205. package/dist/service-invoice-credit-notes.d.ts.map +1 -0
  206. package/dist/service-invoice-credit-notes.js +142 -0
  207. package/dist/service-invoice-from-booking.d.ts +41 -0
  208. package/dist/service-invoice-from-booking.d.ts.map +1 -0
  209. package/dist/service-invoice-from-booking.js +267 -0
  210. package/dist/service-invoice-line-items.d.ts +432 -0
  211. package/dist/service-invoice-line-items.d.ts.map +1 -0
  212. package/dist/service-invoice-line-items.js +102 -0
  213. package/dist/service-invoice-numbering.d.ts +227 -0
  214. package/dist/service-invoice-numbering.d.ts.map +1 -0
  215. package/dist/service-invoice-numbering.js +260 -0
  216. package/dist/service-invoice-payments.d.ts +673 -0
  217. package/dist/service-invoice-payments.d.ts.map +1 -0
  218. package/dist/service-invoice-payments.js +398 -0
  219. package/dist/service-invoices.d.ts +2501 -0
  220. package/dist/service-invoices.d.ts.map +1 -0
  221. package/dist/service-invoices.js +12 -0
  222. package/dist/service-issue.d.ts +207 -0
  223. package/dist/service-issue.d.ts.map +1 -0
  224. package/dist/service-issue.js +431 -0
  225. package/dist/service-payment-authorizations.d.ts +164 -0
  226. package/dist/service-payment-authorizations.d.ts.map +1 -0
  227. package/dist/service-payment-authorizations.js +227 -0
  228. package/dist/service-payment-instruments.d.ts +116 -0
  229. package/dist/service-payment-instruments.d.ts.map +1 -0
  230. package/dist/service-payment-instruments.js +99 -0
  231. package/dist/service-payment-processing.d.ts +676 -0
  232. package/dist/service-payment-processing.d.ts.map +1 -0
  233. package/dist/service-payment-processing.js +10 -0
  234. package/dist/service-payment-session-completion.d.ts +48 -0
  235. package/dist/service-payment-session-completion.d.ts.map +1 -0
  236. package/dist/service-payment-session-completion.js +238 -0
  237. package/dist/service-payment-sessions.d.ts +361 -0
  238. package/dist/service-payment-sessions.d.ts.map +1 -0
  239. package/dist/service-payment-sessions.js +280 -0
  240. package/dist/service-profitability.d.ts +114 -0
  241. package/dist/service-profitability.d.ts.map +1 -0
  242. package/dist/service-profitability.js +794 -0
  243. package/dist/service-public.d.ts +553 -0
  244. package/dist/service-public.d.ts.map +1 -0
  245. package/dist/service-public.js +583 -0
  246. package/dist/service-reference-data.d.ts +272 -0
  247. package/dist/service-reference-data.d.ts.map +1 -0
  248. package/dist/service-reference-data.js +280 -0
  249. package/dist/service-rendition-wait.d.ts +38 -0
  250. package/dist/service-rendition-wait.d.ts.map +1 -0
  251. package/dist/service-rendition-wait.js +67 -0
  252. package/dist/service-reports.d.ts +37 -0
  253. package/dist/service-reports.d.ts.map +1 -0
  254. package/dist/service-reports.js +62 -0
  255. package/dist/service-settlement.d.ts +46 -0
  256. package/dist/service-settlement.d.ts.map +1 -0
  257. package/dist/service-settlement.js +185 -0
  258. package/dist/service-shared.d.ts +541 -0
  259. package/dist/service-shared.d.ts.map +1 -0
  260. package/dist/service-shared.js +764 -0
  261. package/dist/service-supplier-invoices.d.ts +871 -0
  262. package/dist/service-supplier-invoices.d.ts.map +1 -0
  263. package/dist/service-supplier-invoices.js +744 -0
  264. package/dist/service-supplier-payments.d.ts +69 -0
  265. package/dist/service-supplier-payments.d.ts.map +1 -0
  266. package/dist/service-supplier-payments.js +136 -0
  267. package/dist/service-vouchers-migration.d.ts +44 -0
  268. package/dist/service-vouchers-migration.d.ts.map +1 -0
  269. package/dist/service-vouchers-migration.js +148 -0
  270. package/dist/service-vouchers.d.ts +157 -0
  271. package/dist/service-vouchers.d.ts.map +1 -0
  272. package/dist/service-vouchers.js +191 -0
  273. package/dist/service.d.ts +6490 -0
  274. package/dist/service.d.ts.map +1 -0
  275. package/dist/service.js +29 -0
  276. package/dist/validation-billing.d.ts +2 -0
  277. package/dist/validation-billing.d.ts.map +1 -0
  278. package/dist/validation-billing.js +1 -0
  279. package/dist/validation-payments.d.ts +2 -0
  280. package/dist/validation-payments.d.ts.map +1 -0
  281. package/dist/validation-payments.js +1 -0
  282. package/dist/validation-public.d.ts +2 -0
  283. package/dist/validation-public.d.ts.map +1 -0
  284. package/dist/validation-public.js +1 -0
  285. package/dist/validation-shared.d.ts +2 -0
  286. package/dist/validation-shared.d.ts.map +1 -0
  287. package/dist/validation-shared.js +1 -0
  288. package/dist/validation-vouchers.d.ts +2 -0
  289. package/dist/validation-vouchers.d.ts.map +1 -0
  290. package/dist/validation-vouchers.js +1 -0
  291. package/dist/validation.d.ts +2 -0
  292. package/dist/validation.d.ts.map +1 -0
  293. package/dist/validation.js +1 -0
  294. package/package.json +121 -0
package/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ import { Hono } from "hono";
2
+ import { buildFinanceCheckoutRouteRuntime, createFinanceCheckoutAdminRoutes, createFinanceCheckoutRoutes, FINANCE_CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY, } from "./checkout-routes.js";
3
+ import { createInvoiceFxRoutes } from "./invoice-fx.js";
4
+ import { buildFinanceRouteRuntime, FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, } from "./route-runtime.js";
5
+ import { financeRoutes } from "./routes.js";
6
+ import { financeActionLedgerRoutes } from "./routes-action-ledger.js";
7
+ import { createFinanceAdminDocumentRoutes } from "./routes-documents.js";
8
+ import { createPublicFinanceRoutes } from "./routes-public.js";
9
+ import { createFinanceAdminSettlementRoutes } from "./routes-settlement.js";
10
+ import { supplierInvoiceRoutes } from "./routes-supplier-invoices.js";
11
+ export { buildFinanceCheckoutRouteRuntime, CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY, createFinanceCheckoutAdminRoutes, createFinanceCheckoutRoutes, FINANCE_CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY, } from "./checkout-routes.js";
12
+ export { bootstrapCheckoutCollection, initiateCheckoutCollection, previewCheckoutCollection, resolvePaymentSessionTarget, } from "./checkout-service.js";
13
+ export { bootstrapCheckoutCollectionSchema, bootstrappedCheckoutCollectionSchema, checkoutBankTransferInstructionsSchema, checkoutCollectionIntentSchema, checkoutCollectionInvoiceSchema, checkoutCollectionMethodSchema, checkoutCollectionPlanSchema, checkoutCollectionScheduleSchema, checkoutCollectionStageSchema, checkoutInvoiceDocumentTypeSchema, checkoutInvoiceNotificationSchema, checkoutNotificationAttachmentSchema, checkoutNotificationChannelSchema, checkoutNotificationDeliverySchema, checkoutNotificationDeliveryStatusSchema, checkoutPaymentSessionNotificationSchema, checkoutPaymentSessionTargetSchema, checkoutProviderStartInputSchema, checkoutProviderStartResultSchema, checkoutReminderRunListQuerySchema, checkoutReminderRunListResponseSchema, checkoutReminderRunSchema, checkoutReminderRunStatusSchema, checkoutReminderTargetTypeSchema, initiateCheckoutCollectionSchema, initiatedCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./checkout-validation.js";
14
+ export { buildBookingCheckoutUrl, buildPaymentLinkUrl, } from "./payment-link.js";
15
+ export { createPublicFinanceRoutes, publicFinanceRoutes, } from "./routes-public.js";
16
+ export { supplierInvoiceRoutes, } from "./routes-supplier-invoices.js";
17
+ export { publicFinanceService } from "./service-public.js";
18
+ export const invoiceLinkable = {
19
+ module: "finance",
20
+ entity: "invoice",
21
+ table: "invoices",
22
+ idPrefix: "inv",
23
+ };
24
+ export const invoiceTemplateLinkable = {
25
+ module: "finance",
26
+ entity: "invoiceTemplate",
27
+ table: "invoice_templates",
28
+ idPrefix: "invt",
29
+ };
30
+ export const creditNoteLinkable = {
31
+ module: "finance",
32
+ entity: "creditNote",
33
+ table: "credit_notes",
34
+ idPrefix: "crn",
35
+ };
36
+ export const supplierInvoiceLinkable = {
37
+ module: "finance",
38
+ entity: "supplierInvoice",
39
+ table: "supplier_invoices",
40
+ idPrefix: "sinv",
41
+ };
42
+ export const financeLinkable = {
43
+ invoice: invoiceLinkable,
44
+ invoiceTemplate: invoiceTemplateLinkable,
45
+ creditNote: creditNoteLinkable,
46
+ supplierInvoice: supplierInvoiceLinkable,
47
+ };
48
+ export const financeModule = {
49
+ name: "finance",
50
+ linkable: financeLinkable,
51
+ requiresTransactionalDb: true,
52
+ };
53
+ export function createFinanceHonoModule(options = {}) {
54
+ const adminRoutes = new Hono()
55
+ .route("/", financeRoutes)
56
+ .route("/", createFinanceCheckoutAdminRoutes(options))
57
+ .route("/", financeActionLedgerRoutes)
58
+ .route("/", supplierInvoiceRoutes)
59
+ .route("/", createInvoiceFxRoutes(options))
60
+ .route("/", createFinanceAdminDocumentRoutes(options))
61
+ .route("/", createFinanceAdminSettlementRoutes(options));
62
+ const module = {
63
+ ...financeModule,
64
+ bootstrap: ({ bindings, container, eventBus }) => {
65
+ const runtime = buildFinanceRouteRuntime(bindings, options);
66
+ // Wire the framework's eventBus into the route runtime so subscribers
67
+ // (notably the storefront's checkout-finalize workflow on
68
+ // `payment.completed`) actually receive emissions from
69
+ // `financeService.completePaymentSession`. Without this, the Netopia
70
+ // webhook silently no-ops because the runtime has no bus attached.
71
+ if (!runtime.eventBus && eventBus)
72
+ runtime.eventBus = eventBus;
73
+ container.register(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, runtime);
74
+ container.register(FINANCE_CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY, buildFinanceCheckoutRouteRuntime(bindings, options));
75
+ },
76
+ };
77
+ const publicRoutes = new Hono()
78
+ .route("/", createPublicFinanceRoutes(options))
79
+ .route("/", createFinanceCheckoutRoutes(options));
80
+ return {
81
+ module,
82
+ adminRoutes,
83
+ publicRoutes,
84
+ routes: adminRoutes,
85
+ };
86
+ }
87
+ export const financeHonoModule = createFinanceHonoModule();
88
+ export { computeBookingItemTaxLine, createBookingTaxHonoExtension, createBookingTaxRoutes, loadProductTaxFacts, matchesTaxPolicyCondition, mountBookingTaxRoutes, resolveBookingSellTaxRate, } from "./booking-tax.js";
89
+ export { resolveStoredDocumentDownload, } from "./document-download.js";
90
+ export { createInvoiceFxHonoExtension, createInvoiceFxRoutes, createVoyantDataFxExchangeRateResolver, mountInvoiceFxRoutes, resolveInvoiceFxContext, resolveInvoiceFxSettingsOrDefault, } from "./invoice-fx.js";
91
+ export { computePaymentSchedule, isPaymentPolicyEmpty, noDepositPolicy, policyShouldRequireFullPayment, resolveEffectivePaymentPolicy, } from "./payment-policy.js";
92
+ export { buildFinanceRouteRuntime, FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, } from "./route-runtime.js";
93
+ export { bookingsCreateExtension } from "./routes-booking-create.js";
94
+ export { createFinanceAdminDocumentRoutes, } from "./routes-documents.js";
95
+ export { createFinanceAdminSettlementRoutes, } from "./routes-settlement.js";
96
+ export { apServiceTypeEnum, bookingGuarantees, bookingItemCommissions, bookingItemTaxLines, bookingPaymentSchedules, costAllocationSplitMethodEnum, costAllocationTargetTypeEnum, creditNoteLineItems, creditNotes, financeNotes, invoiceAttachments, invoiceExternalRefs, invoiceLineItems, invoiceNumberSeries, invoiceRenditions, invoices, invoiceTemplates, paymentAuthorizations, paymentCaptures, paymentInstruments, paymentSessions, payments, supplierCostAllocations, supplierInvoiceAttachments, supplierInvoiceLines, supplierInvoiceStatusEnum, supplierInvoices, supplierPayments, taxClasses, taxPolicyProfiles, taxPolicyRules, taxRegimes, voucherRedemptions, voucherSourceTypeEnum, voucherStatusEnum, vouchers, } from "./schema.js";
97
+ export { financeService, InvoiceLineItemsPersistenceError, InvoiceNumberAllocationError, InvoiceNumberConflictError, renderInvoiceBody, } from "./service.js";
98
+ export { bookingCreateSchema, createBooking, } from "./service-booking-create.js";
99
+ export { dualCreateBooking, dualCreateBookingSchema, } from "./service-bookings-dual-create.js";
100
+ export { createPdfInvoiceDocumentGenerator, createStorageBackedInvoiceDocumentGenerator, defaultPdfInvoiceDocumentSerializer, defaultStorageBackedInvoiceDocumentSerializer, financeDocumentsService, } from "./service-documents.js";
101
+ export { buildInvoiceIssuedEvent, issueInvoiceFromBooking, issueProformaFromBooking, } from "./service-issue.js";
102
+ export { getLatestInvoiceRendition, waitForInvoiceRendition, waitFormatForMode, } from "./service-rendition-wait.js";
103
+ export { financeSettlementService } from "./service-settlement.js";
104
+ export { recomputeTotalsFromLines, SupplierInvoiceServiceError, supplierInvoicesService, validateAllocations, } from "./service-supplier-invoices.js";
105
+ export { VoucherServiceError, vouchersService } from "./service-vouchers.js";
106
+ export { migrateVouchersFromPaymentInstruments, } from "./service-vouchers-migration.js";
107
+ export { agingReportQuerySchema, allocateInvoiceNumberInputSchema, applyDefaultBookingPaymentPlanSchema, apServiceTypeSchema, cancelPaymentSessionSchema, completePaymentSessionSchema, costAllocationSplitMethodSchema, costAllocationTargetTypeSchema, createPaymentSessionFromGuaranteeSchema, createPaymentSessionFromInvoiceSchema, createPaymentSessionFromScheduleSchema, expirePaymentSessionSchema, failPaymentSessionSchema, financeAggregatesQuerySchema, generatedInvoiceDocumentResultSchema, generateInvoiceDocumentInputSchema, insertBookingGuaranteeSchema, insertBookingItemCommissionSchema, insertBookingItemTaxLineSchema, insertBookingPaymentScheduleSchema, insertCreditNoteLineItemSchema, insertCreditNoteSchema, insertFinanceNoteSchema, insertInvoiceExternalRefSchema, insertInvoiceLineItemSchema, insertInvoiceNumberSeriesSchema, insertInvoiceRenditionSchema, insertInvoiceSchema, insertInvoiceTemplateSchema, insertPaymentAuthorizationSchema, insertPaymentCaptureSchema, insertPaymentInstrumentSchema, insertPaymentSchema, insertPaymentSessionSchema, insertSupplierInvoiceAttachmentSchema, insertSupplierInvoiceSchema, insertSupplierPaymentSchema, insertTaxClassSchema, insertTaxPolicyProfileSchema, insertTaxPolicyRuleSchema, insertTaxRegimeSchema, invoiceFromBookingSchema, invoiceListQuerySchema, invoiceNumberSeriesListQuerySchema, invoiceTemplateListQuerySchema, markPaymentSessionRequiresRedirectSchema, paymentAuthorizationListQuerySchema, paymentCaptureListQuerySchema, paymentInstrumentListQuerySchema, paymentKindSchema, paymentListQuerySchema, paymentListSortDirSchema, paymentListSortFieldSchema, paymentProvenanceSchema, paymentSessionListQuerySchema, paymentTargetSchema, polledInvoiceSettlementProviderResultSchema, polledInvoiceSettlementResultSchema, pollInvoiceSettlementInputSchema, profitabilityQuerySchema, renderInvoiceInputSchema, revenueReportQuerySchema, setSupplierCostAllocationsSchema, setSupplierInvoiceLinesSchema, supplierCostAllocationInputSchema, supplierInvoiceLineInputSchema, supplierInvoiceListQuerySchema, supplierInvoiceStatusSchema, supplierPaymentListQuerySchema, taxClassListQuerySchema, taxPolicyProfileListQuerySchema, taxPolicyRuleListQuerySchema, taxRegimeListQuerySchema, updateBookingGuaranteeSchema, updateBookingItemCommissionSchema, updateBookingItemTaxLineSchema, updateBookingPaymentScheduleSchema, updateCreditNoteLineItemSchema, updateCreditNoteSchema, updateInvoiceExternalRefSchema, updateInvoiceLineItemSchema, updateInvoiceNumberSeriesSchema, updateInvoiceRenditionSchema, updateInvoiceSchema, updateInvoiceTemplateSchema, updatePaymentAuthorizationSchema, updatePaymentCaptureSchema, updatePaymentInstrumentSchema, updatePaymentSchema, updatePaymentSessionSchema, updateSupplierInvoiceSchema, updateSupplierPaymentSchema, updateTaxClassSchema, updateTaxPolicyProfileSchema, updateTaxPolicyRuleSchema, updateTaxRegimeSchema, } from "./validation.js";
108
+ export { publicBookingFinanceDocumentsSchema, publicBookingFinancePaymentsSchema, publicBookingPaymentOptionsSchema, publicFinanceBookingDocumentSchema, publicFinanceBookingPaymentSchema, publicFinanceDocumentAvailabilitySchema, publicFinanceDocumentFormatSchema, publicFinanceDocumentLookupQuerySchema, publicFinanceDocumentLookupSchema, publicFinanceInvoiceTypeSchema, publicPaymentOptionsQuerySchema, publicPaymentSessionSchema, publicStartPaymentSessionSchema, publicValidateVoucherSchema, publicVoucherValidationSchema, } from "./validation-public.js";
@@ -0,0 +1,134 @@
1
+ import type { ModuleContainer } from "@voyant-travel/core";
2
+ import type { HonoExtension } from "@voyant-travel/hono/module";
3
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
4
+ import type { Hono } from "hono";
5
+ import type { Env } from "./routes-shared.js";
6
+ export type InvoiceFxSettings = {
7
+ baseCurrency?: string | null;
8
+ fxCommissionBps?: number | null;
9
+ fxCommissionInvoiceMention?: string | null;
10
+ };
11
+ export type ResolveInvoiceFxSettings = (db: PostgresJsDatabase) => InvoiceFxSettings | null | undefined | Promise<InvoiceFxSettings | null | undefined>;
12
+ export type UpdateInvoiceFxSettings = (db: PostgresJsDatabase, settings: InvoiceFxSettings) => InvoiceFxSettings | null | undefined | Promise<InvoiceFxSettings | null | undefined>;
13
+ export type ResolveInvoiceExchangeRateInput = {
14
+ /** Currency being invoiced, e.g. EUR. */
15
+ baseCurrency: string;
16
+ /** Operator accounting/reporting currency, e.g. RON. */
17
+ quoteCurrency: string;
18
+ date?: string;
19
+ };
20
+ export type InvoiceExchangeRateResolution = {
21
+ rate: number;
22
+ fxRateSetId?: string;
23
+ source?: string;
24
+ quotedAt?: string;
25
+ validUntil?: string;
26
+ };
27
+ export type ResolveInvoiceExchangeRate = (input: ResolveInvoiceExchangeRateInput) => number | InvoiceExchangeRateResolution | null | undefined | Promise<number | InvoiceExchangeRateResolution | null | undefined>;
28
+ export type HandleInvoiceFxResolutionError = (error: unknown, input: ResolveInvoiceExchangeRateInput) => void | Promise<void>;
29
+ export interface InvoiceFxOptions {
30
+ invoiceFxSettings?: InvoiceFxSettings | null;
31
+ resolveInvoiceFxSettings?: ResolveInvoiceFxSettings;
32
+ updateInvoiceFxSettings?: UpdateInvoiceFxSettings;
33
+ resolveInvoiceExchangeRate?: ResolveInvoiceExchangeRate;
34
+ resolveInvoiceExchangeRateResolver?: (bindings: Record<string, unknown>) => ResolveInvoiceExchangeRate | undefined;
35
+ onInvoiceFxResolutionError?: HandleInvoiceFxResolutionError;
36
+ }
37
+ export interface InvoiceFxRouteOptions extends InvoiceFxOptions {
38
+ }
39
+ export type InvoiceFxInvoice = {
40
+ currency: string;
41
+ baseCurrency?: string | null;
42
+ issueDate?: string | Date | null;
43
+ };
44
+ export type InvoiceFxContext = {
45
+ baseCurrency: string;
46
+ fxRateSetId?: string;
47
+ fxRate: number;
48
+ fxRateSource?: string;
49
+ fxRateQuotedAt?: string;
50
+ fxRateValidUntil?: string;
51
+ fxCommissionBps: number;
52
+ effectiveRate: number;
53
+ fxCommissionInvoiceMention?: string;
54
+ };
55
+ export type ResolvedInvoiceFxSettings = {
56
+ baseCurrency: string;
57
+ fxCommissionBps: number;
58
+ fxCommissionInvoiceMention?: string;
59
+ };
60
+ export type VoyantDataFxResolverOptions = {
61
+ baseUrl?: string;
62
+ apiKey: string;
63
+ authHeader?: string;
64
+ authScheme?: string | null;
65
+ fetch?: typeof fetch;
66
+ headers?: HeadersInit;
67
+ userAgent?: string;
68
+ };
69
+ type InvoiceFxRouteEnv = Env & {
70
+ Variables: Env["Variables"] & {
71
+ container?: ModuleContainer;
72
+ };
73
+ };
74
+ export declare function resolveInvoiceFxSettingsOrDefault(db: PostgresJsDatabase, options?: InvoiceFxOptions): Promise<ResolvedInvoiceFxSettings>;
75
+ export declare function resolveInvoiceFxContext(db: PostgresJsDatabase, invoice: InvoiceFxInvoice, options?: InvoiceFxOptions): Promise<InvoiceFxContext | null>;
76
+ export declare function createVoyantDataFxExchangeRateResolver(options: VoyantDataFxResolverOptions): ResolveInvoiceExchangeRate;
77
+ export declare function createInvoiceFxRoutes(options?: InvoiceFxRouteOptions): import("hono/hono-base").HonoBase<InvoiceFxRouteEnv, {
78
+ "/invoice-fx-settings": {
79
+ $get: {
80
+ input: {};
81
+ output: {
82
+ data: {
83
+ baseCurrency: string;
84
+ fxCommissionBps: number;
85
+ fxCommissionInvoiceMention?: string | undefined;
86
+ };
87
+ };
88
+ outputFormat: "json";
89
+ status: import("hono/utils/http-status").ContentfulStatusCode;
90
+ };
91
+ };
92
+ } & {
93
+ "/invoice-fx-settings": {
94
+ $patch: {
95
+ input: {};
96
+ output: {
97
+ data: {
98
+ baseCurrency: string;
99
+ fxCommissionBps: number;
100
+ fxCommissionInvoiceMention?: string | undefined;
101
+ };
102
+ };
103
+ outputFormat: "json";
104
+ status: import("hono/utils/http-status").ContentfulStatusCode;
105
+ };
106
+ };
107
+ } & {
108
+ "/invoice-fx-rate": {
109
+ $get: {
110
+ input: {};
111
+ output: {
112
+ data: {
113
+ fxCommissionInvoiceMention?: string | undefined;
114
+ fxCommissionBps: number;
115
+ effectiveRate: number;
116
+ validUntil?: string | undefined;
117
+ quotedAt?: string | undefined;
118
+ source?: string | undefined;
119
+ fxRateSetId?: string | undefined;
120
+ rate: number;
121
+ baseCurrency: string;
122
+ quoteCurrency: string;
123
+ date: string | undefined;
124
+ };
125
+ };
126
+ outputFormat: "json";
127
+ status: import("hono/utils/http-status").ContentfulStatusCode;
128
+ };
129
+ };
130
+ }, "/", "/invoice-fx-rate">;
131
+ export declare function mountInvoiceFxRoutes(hono: Hono, options?: InvoiceFxRouteOptions): Hono;
132
+ export declare function createInvoiceFxHonoExtension(options?: InvoiceFxRouteOptions): HonoExtension;
133
+ export {};
134
+ //# sourceMappingURL=invoice-fx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-fx.d.ts","sourceRoot":"","sources":["../src/invoice-fx.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ import { createVoyantDataClient } from "@voyant-travel/data-sdk";
2
+ import { ApiHttpError, parseJsonBody, parseQuery } from "@voyant-travel/hono";
3
+ import { Hono as HonoApp } from "hono";
4
+ import { z } from "zod";
5
+ import { buildFinanceRouteRuntime, FINANCE_ROUTE_RUNTIME_CONTAINER_KEY, } from "./route-runtime.js";
6
+ const invoiceFxSettingsPatchSchema = z.object({
7
+ baseCurrency: z.string().min(3).max(8).nullable().optional(),
8
+ fxCommissionBps: z.number().int().min(0).max(100_000).nullable().optional(),
9
+ fxCommissionInvoiceMention: z.string().nullable().optional(),
10
+ });
11
+ const invoiceExchangeRateQuerySchema = z.object({
12
+ baseCurrency: z.string().min(3).max(8),
13
+ quoteCurrency: z.string().min(3).max(8),
14
+ date: z.string().optional(),
15
+ });
16
+ function getInvoiceFxRuntime(options, bindings, container) {
17
+ return ((container?.has(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY)
18
+ ? container.resolve(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY)
19
+ : undefined) ?? buildFinanceRouteRuntime(bindings, options));
20
+ }
21
+ export async function resolveInvoiceFxSettingsOrDefault(db, options = {}) {
22
+ const settings = await resolveConfiguredInvoiceFxSettings(db, options);
23
+ return {
24
+ baseCurrency: normalizeCurrency(settings?.baseCurrency) ?? "RON",
25
+ fxCommissionBps: normalizeBasisPoints(settings?.fxCommissionBps),
26
+ fxCommissionInvoiceMention: normalizeOptionalText(settings?.fxCommissionInvoiceMention),
27
+ };
28
+ }
29
+ export async function resolveInvoiceFxContext(db, invoice, options = {}) {
30
+ const settings = await resolveConfiguredInvoiceFxSettings(db, options);
31
+ const baseCurrency = normalizeCurrency(settings?.baseCurrency) ?? normalizeCurrency(invoice.baseCurrency) ?? "RON";
32
+ const invoiceCurrency = normalizeCurrency(invoice.currency);
33
+ if (!baseCurrency || !invoiceCurrency || invoiceCurrency === baseCurrency)
34
+ return null;
35
+ if (!options.resolveInvoiceExchangeRate)
36
+ return null;
37
+ const rateInput = {
38
+ baseCurrency: invoiceCurrency,
39
+ quoteCurrency: baseCurrency,
40
+ date: toDateString(invoice.issueDate),
41
+ };
42
+ let fxResolution;
43
+ try {
44
+ fxResolution = await options.resolveInvoiceExchangeRate(rateInput);
45
+ }
46
+ catch (error) {
47
+ await notifyInvoiceFxResolutionError(options, error, rateInput);
48
+ return null;
49
+ }
50
+ const resolvedRate = normalizeInvoiceExchangeRateResolution(fxResolution);
51
+ if (!resolvedRate)
52
+ return null;
53
+ const fxCommissionBps = normalizeBasisPoints(settings?.fxCommissionBps);
54
+ const effectiveRate = roundRate(resolvedRate.rate * (1 + fxCommissionBps / 10_000));
55
+ return {
56
+ baseCurrency,
57
+ ...(resolvedRate.fxRateSetId ? { fxRateSetId: resolvedRate.fxRateSetId } : {}),
58
+ fxRate: roundRate(resolvedRate.rate),
59
+ ...(resolvedRate.source ? { fxRateSource: resolvedRate.source } : {}),
60
+ ...(resolvedRate.quotedAt ? { fxRateQuotedAt: resolvedRate.quotedAt } : {}),
61
+ ...(resolvedRate.validUntil ? { fxRateValidUntil: resolvedRate.validUntil } : {}),
62
+ fxCommissionBps,
63
+ effectiveRate,
64
+ ...(fxCommissionBps > 0 && normalizeOptionalText(settings?.fxCommissionInvoiceMention)
65
+ ? { fxCommissionInvoiceMention: normalizeOptionalText(settings?.fxCommissionInvoiceMention) }
66
+ : {}),
67
+ };
68
+ }
69
+ export function createVoyantDataFxExchangeRateResolver(options) {
70
+ const client = createVoyantDataClient({
71
+ apiKey: options.apiKey,
72
+ ...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
73
+ ...(options.authHeader ? { authHeader: options.authHeader } : {}),
74
+ ...(options.authScheme !== undefined ? { authScheme: options.authScheme } : {}),
75
+ ...(options.fetch ? { fetch: options.fetch } : {}),
76
+ ...(options.headers ? { headers: options.headers } : {}),
77
+ userAgent: options.userAgent ?? "voyant-finance",
78
+ });
79
+ return async ({ baseCurrency, quoteCurrency }) => {
80
+ const quote = await client.fx.pair(baseCurrency, quoteCurrency);
81
+ if (typeof quote.conversionRate !== "number" || !Number.isFinite(quote.conversionRate)) {
82
+ return null;
83
+ }
84
+ const source = normalizeOptionalText(quote.source);
85
+ const quotedAt = normalizeOptionalText(quote.timeLastUpdateUtc);
86
+ const validUntil = normalizeOptionalText(quote.timeNextUpdateUtc);
87
+ return {
88
+ rate: quote.conversionRate,
89
+ ...(source ? { source } : {}),
90
+ ...(quotedAt ? { quotedAt } : {}),
91
+ ...(validUntil ? { validUntil } : {}),
92
+ };
93
+ };
94
+ }
95
+ export function createInvoiceFxRoutes(options = {}) {
96
+ return new HonoApp()
97
+ .get("/invoice-fx-settings", async (c) => {
98
+ const runtime = getInvoiceFxRuntime(options, c.env, c.var.container);
99
+ return c.json({
100
+ data: await resolveInvoiceFxSettingsOrDefault(c.get("db"), runtime),
101
+ });
102
+ })
103
+ .patch("/invoice-fx-settings", async (c) => {
104
+ const runtime = getInvoiceFxRuntime(options, c.env, c.var.container);
105
+ if (!runtime.updateInvoiceFxSettings) {
106
+ throw new ApiHttpError("Invoice FX settings updates are not configured", {
107
+ status: 501,
108
+ code: "invoice_fx_settings_update_not_configured",
109
+ });
110
+ }
111
+ const current = await resolveInvoiceFxSettingsOrDefault(c.get("db"), runtime);
112
+ const patch = await parseJsonBody(c, invoiceFxSettingsPatchSchema);
113
+ const next = await runtime.updateInvoiceFxSettings(c.get("db"), {
114
+ ...current,
115
+ ...patch,
116
+ });
117
+ return c.json({
118
+ data: await resolveInvoiceFxSettingsOrDefault(c.get("db"), { invoiceFxSettings: next }),
119
+ });
120
+ })
121
+ .get("/invoice-fx-rate", async (c) => {
122
+ const runtime = getInvoiceFxRuntime(options, c.env, c.var.container);
123
+ if (!runtime.resolveInvoiceExchangeRate) {
124
+ throw new ApiHttpError("Invoice FX rate resolution is not configured", {
125
+ status: 501,
126
+ code: "invoice_fx_rate_resolution_not_configured",
127
+ });
128
+ }
129
+ const query = parseQuery(c, invoiceExchangeRateQuerySchema);
130
+ const input = {
131
+ baseCurrency: normalizeCurrency(query.baseCurrency) ?? query.baseCurrency,
132
+ quoteCurrency: normalizeCurrency(query.quoteCurrency) ?? query.quoteCurrency,
133
+ date: query.date,
134
+ };
135
+ let rateResolution;
136
+ try {
137
+ rateResolution = await runtime.resolveInvoiceExchangeRate(input);
138
+ }
139
+ catch (error) {
140
+ await notifyInvoiceFxResolutionError(runtime, error, input);
141
+ throw new ApiHttpError("Invoice FX rate resolution failed", {
142
+ status: 502,
143
+ code: "invoice_fx_rate_resolution_failed",
144
+ });
145
+ }
146
+ const resolvedRate = normalizeInvoiceExchangeRateResolution(rateResolution);
147
+ if (!resolvedRate) {
148
+ throw new ApiHttpError("Invoice FX rate was not found", {
149
+ status: 404,
150
+ code: "invoice_fx_rate_not_found",
151
+ });
152
+ }
153
+ const settings = await resolveInvoiceFxSettingsOrDefault(c.get("db"), runtime);
154
+ const fxCommissionBps = settings.fxCommissionBps;
155
+ const effectiveRate = roundRate(resolvedRate.rate * (1 + fxCommissionBps / 10_000));
156
+ return c.json({
157
+ data: {
158
+ ...input,
159
+ rate: roundRate(resolvedRate.rate),
160
+ ...(resolvedRate.fxRateSetId ? { fxRateSetId: resolvedRate.fxRateSetId } : {}),
161
+ ...(resolvedRate.source ? { source: resolvedRate.source } : {}),
162
+ ...(resolvedRate.quotedAt ? { quotedAt: resolvedRate.quotedAt } : {}),
163
+ ...(resolvedRate.validUntil ? { validUntil: resolvedRate.validUntil } : {}),
164
+ fxCommissionBps,
165
+ effectiveRate,
166
+ ...(fxCommissionBps > 0 && settings.fxCommissionInvoiceMention
167
+ ? { fxCommissionInvoiceMention: settings.fxCommissionInvoiceMention }
168
+ : {}),
169
+ },
170
+ });
171
+ });
172
+ }
173
+ export function mountInvoiceFxRoutes(hono, options = {}) {
174
+ hono.route("/v1/admin/finance", createInvoiceFxRoutes(options));
175
+ return hono;
176
+ }
177
+ export function createInvoiceFxHonoExtension(options = {}) {
178
+ const extension = {
179
+ name: "finance.invoice-fx",
180
+ module: "finance",
181
+ };
182
+ return {
183
+ extension,
184
+ adminRoutes: createInvoiceFxRoutes(options),
185
+ routes: createInvoiceFxRoutes(options),
186
+ };
187
+ }
188
+ async function resolveConfiguredInvoiceFxSettings(db, options) {
189
+ return options.invoiceFxSettings !== undefined
190
+ ? options.invoiceFxSettings
191
+ : ((await options.resolveInvoiceFxSettings?.(db)) ?? null);
192
+ }
193
+ function normalizeCurrency(value) {
194
+ const normalized = value?.trim().toUpperCase();
195
+ return normalized ? normalized : null;
196
+ }
197
+ async function notifyInvoiceFxResolutionError(options, error, input) {
198
+ try {
199
+ await options.onInvoiceFxResolutionError?.(error, input);
200
+ }
201
+ catch {
202
+ // FX enrichment is optional; a reporting hook must not fail invoice issuance.
203
+ }
204
+ }
205
+ function normalizeBasisPoints(value) {
206
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.round(value) : 0;
207
+ }
208
+ function normalizeInvoiceExchangeRateResolution(resolution) {
209
+ if (typeof resolution === "number") {
210
+ return Number.isFinite(resolution) && resolution > 0 ? { rate: resolution } : null;
211
+ }
212
+ if (!resolution || typeof resolution !== "object")
213
+ return null;
214
+ if (typeof resolution.rate !== "number" || !Number.isFinite(resolution.rate))
215
+ return null;
216
+ if (resolution.rate <= 0)
217
+ return null;
218
+ const source = normalizeOptionalText(resolution.source);
219
+ const fxRateSetId = normalizeOptionalText(resolution.fxRateSetId);
220
+ const quotedAt = normalizeOptionalText(resolution.quotedAt);
221
+ const validUntil = normalizeOptionalText(resolution.validUntil);
222
+ return {
223
+ rate: resolution.rate,
224
+ ...(fxRateSetId ? { fxRateSetId } : {}),
225
+ ...(source ? { source } : {}),
226
+ ...(quotedAt ? { quotedAt } : {}),
227
+ ...(validUntil ? { validUntil } : {}),
228
+ };
229
+ }
230
+ function normalizeOptionalText(value) {
231
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
232
+ }
233
+ function toDateString(value) {
234
+ if (value instanceof Date)
235
+ return value.toISOString().slice(0, 10);
236
+ return typeof value === "string" && value.length > 0 ? value : undefined;
237
+ }
238
+ function roundRate(value) {
239
+ return Number(value.toFixed(8));
240
+ }
@@ -0,0 +1,2 @@
1
+ export declare function isInvoiceNumberUniqueConstraintError(error: unknown): boolean;
2
+ //# sourceMappingURL=invoice-number-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-number-errors.d.ts","sourceRoot":"","sources":["../src/invoice-number-errors.ts"],"names":[],"mappings":"AAeA,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,OAAO,WAGlE"}
@@ -0,0 +1,58 @@
1
+ const INVOICE_NUMBER_UNIQUE_TARGETS = [
2
+ "invoices_invoice_number_type_active_idx",
3
+ "invoices_invoice_number_type_unique",
4
+ "invoices_invoice_number_unique",
5
+ "invoices_invoice_number_key",
6
+ "invoice_number",
7
+ ];
8
+ const UNIQUE_VIOLATION_SQLSTATE = "23505";
9
+ export function isInvoiceNumberUniqueConstraintError(error) {
10
+ const signals = collectErrorSignals(error, new Set(), 0);
11
+ return signals.hasUniqueViolation && signals.hasInvoiceNumberTarget;
12
+ }
13
+ function collectErrorSignals(error, seen, depth) {
14
+ if (!error || typeof error !== "object" || depth > 6 || seen.has(error)) {
15
+ return { hasInvoiceNumberTarget: false, hasUniqueViolation: false };
16
+ }
17
+ seen.add(error);
18
+ const record = error;
19
+ const strings = errorStrings(record);
20
+ const signals = {
21
+ hasInvoiceNumberTarget: strings.some((value) => INVOICE_NUMBER_UNIQUE_TARGETS.some((target) => value.includes(target))),
22
+ hasUniqueViolation: strings.some((value) => value.includes(UNIQUE_VIOLATION_SQLSTATE)),
23
+ };
24
+ for (const nested of nestedErrors(record)) {
25
+ const nestedSignals = collectErrorSignals(nested, seen, depth + 1);
26
+ signals.hasInvoiceNumberTarget ||= nestedSignals.hasInvoiceNumberTarget;
27
+ signals.hasUniqueViolation ||= nestedSignals.hasUniqueViolation;
28
+ }
29
+ return signals;
30
+ }
31
+ function errorStrings(error) {
32
+ return [
33
+ error.code,
34
+ error.sqlState,
35
+ error.sqlstate,
36
+ error.sql_state,
37
+ error.constraint,
38
+ error.constraintName,
39
+ error.constraint_name,
40
+ error.detail,
41
+ error.message,
42
+ error.stack,
43
+ ].filter((value) => typeof value === "string");
44
+ }
45
+ function nestedErrors(error) {
46
+ const values = [
47
+ error.cause,
48
+ error.originalError,
49
+ error.original,
50
+ error.error,
51
+ error.queryError,
52
+ error.sourceError,
53
+ ];
54
+ if (Array.isArray(error.errors)) {
55
+ values.push(...error.errors);
56
+ }
57
+ return values;
58
+ }