@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
@@ -0,0 +1,91 @@
1
+ import { parseJsonBody, parseQuery } from "@voyant-travel/hono";
2
+ import { Hono } from "hono";
3
+ import { buildInlineDownload, resolveWaitRequest } from "./routes-runtime.js";
4
+ import { financeService } from "./service.js";
5
+ import { waitForInvoiceRendition, waitFormatForMode } from "./service-rendition-wait.js";
6
+ import { insertInvoiceAttachmentSchema, insertInvoiceExternalRefSchema, invoiceDocumentWaitQuerySchema, renderInvoiceInputSchema, updateInvoiceAttachmentSchema, } from "./validation.js";
7
+ export const financeInvoiceDocumentRoutes = new Hono()
8
+ // ========================================================================
9
+ // Invoice Renditions & External Refs (nested under invoice)
10
+ // ========================================================================
11
+ .get("/invoices/:id/renditions", async (c) => {
12
+ const rows = await financeService.listInvoiceRenditions(c.get("db"), c.req.param("id"));
13
+ return c.json({ data: rows });
14
+ })
15
+ .get("/invoices/:id/attachments", async (c) => {
16
+ const rows = await financeService.listInvoiceAttachments(c.get("db"), c.req.param("id"));
17
+ return c.json({ data: rows });
18
+ })
19
+ .post("/invoices/:id/attachments", async (c) => {
20
+ const row = await financeService.createInvoiceAttachment(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertInvoiceAttachmentSchema));
21
+ if (!row)
22
+ return c.json({ error: "Invoice not found" }, 404);
23
+ return c.json({ data: row }, 201);
24
+ })
25
+ .patch("/invoices/:id/attachments/:attachmentId", async (c) => {
26
+ const row = await financeService.updateInvoiceAttachment(c.get("db"), c.req.param("id"), c.req.param("attachmentId"), await parseJsonBody(c, updateInvoiceAttachmentSchema));
27
+ if (!row)
28
+ return c.json({ error: "Attachment not found" }, 404);
29
+ return c.json({ data: row });
30
+ })
31
+ .get("/invoice-attachments/:id/download", async (c) => {
32
+ const attachment = await financeService.getInvoiceAttachmentById(c.get("db"), c.req.param("id"));
33
+ if (!attachment)
34
+ return c.json({ error: "Attachment not found" }, 404);
35
+ const download = await buildInlineDownload(c, attachment);
36
+ if (download.status === "resolver_not_configured") {
37
+ return c.json({ error: "Document download resolver is not configured" }, 501);
38
+ }
39
+ if (download.status !== "ready") {
40
+ return c.json({ error: "Attachment file is not available" }, 404);
41
+ }
42
+ return c.redirect(download.download.url, 302);
43
+ })
44
+ .delete("/invoices/:id/attachments/:attachmentId", async (c) => {
45
+ const row = await financeService.deleteInvoiceAttachment(c.get("db"), c.req.param("id"), c.req.param("attachmentId"));
46
+ if (!row)
47
+ return c.json({ error: "Attachment not found" }, 404);
48
+ return c.json({ success: true });
49
+ })
50
+ .post("/invoices/:id/render", async (c) => {
51
+ const input = await parseJsonBody(c, renderInvoiceInputSchema);
52
+ const waitRequest = resolveWaitRequest(input, parseQuery(c, invoiceDocumentWaitQuerySchema));
53
+ const result = await financeService.renderInvoice(c.get("db"), c.req.param("id"), input);
54
+ if (result.status === "not_found")
55
+ return c.json({ error: "Invoice not found" }, 404);
56
+ if (waitRequest.mode !== "none" && result.rendition) {
57
+ const waitResult = await waitForInvoiceRendition(c.get("db"), c.req.param("id"), {
58
+ renditionId: result.rendition.id,
59
+ format: waitFormatForMode(waitRequest.mode),
60
+ timeoutMs: waitRequest.timeoutMs,
61
+ });
62
+ const payload = {
63
+ rendition: waitResult.rendition ?? result.rendition,
64
+ };
65
+ if (waitResult.status !== "ready") {
66
+ return c.json({ data: payload }, 202);
67
+ }
68
+ const download = await buildInlineDownload(c, waitResult.rendition);
69
+ if (download.status !== "ready") {
70
+ return c.json({ data: payload }, 202);
71
+ }
72
+ return c.json({ data: { ...payload, download: download.download } }, 201);
73
+ }
74
+ return c.json({ data: result.rendition }, 201);
75
+ })
76
+ .get("/invoices/:id/external-refs", async (c) => {
77
+ const rows = await financeService.listInvoiceExternalRefs(c.get("db"), c.req.param("id"));
78
+ return c.json({ data: rows });
79
+ })
80
+ .post("/invoices/:id/external-refs", async (c) => {
81
+ const row = await financeService.registerInvoiceExternalRef(c.get("db"), c.req.param("id"), await parseJsonBody(c, insertInvoiceExternalRefSchema));
82
+ if (!row)
83
+ return c.json({ error: "Invoice not found" }, 404);
84
+ return c.json({ data: row }, 201);
85
+ })
86
+ .delete("/invoices/:id/external-refs/:refId", async (c) => {
87
+ const row = await financeService.deleteInvoiceExternalRef(c.get("db"), c.req.param("refId"));
88
+ if (!row)
89
+ return c.json({ error: "External ref not found" }, 404);
90
+ return c.json({ success: true });
91
+ });
@@ -0,0 +1,384 @@
1
+ import type { Env } from "./routes-shared.js";
2
+ export declare const financeInvoiceIssueRoutes: import("hono/hono-base").HonoBase<Env, {
3
+ "/invoices": {
4
+ $get: {
5
+ input: {};
6
+ output: {
7
+ data: {
8
+ bookingPaymentScheduleIds: string[];
9
+ id: string;
10
+ invoiceNumber: string;
11
+ invoiceType: "invoice" | "proforma" | "credit_note";
12
+ convertedFromInvoiceId: string | null;
13
+ seriesId: string | null;
14
+ sequence: number | null;
15
+ templateId: string | null;
16
+ taxRegimeId: string | null;
17
+ language: string | null;
18
+ bookingId: string;
19
+ personId: string | null;
20
+ organizationId: string | null;
21
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
22
+ currency: string;
23
+ baseCurrency: string | null;
24
+ fxRateSetId: string | null;
25
+ subtotalCents: number;
26
+ baseSubtotalCents: number | null;
27
+ taxCents: number;
28
+ baseTaxCents: number | null;
29
+ totalCents: number;
30
+ baseTotalCents: number | null;
31
+ paidCents: number;
32
+ basePaidCents: number | null;
33
+ balanceDueCents: number;
34
+ baseBalanceDueCents: number | null;
35
+ commissionPercent: number | null;
36
+ commissionAmountCents: number | null;
37
+ issueDate: string;
38
+ dueDate: string;
39
+ notes: string | null;
40
+ voidedAt: string | null;
41
+ voidReason: string | null;
42
+ createdAt: string;
43
+ updatedAt: string;
44
+ }[];
45
+ total: number;
46
+ limit: number;
47
+ offset: number;
48
+ };
49
+ outputFormat: "json";
50
+ status: import("hono/utils/http-status").ContentfulStatusCode;
51
+ };
52
+ };
53
+ } & {
54
+ "/invoices": {
55
+ $post: {
56
+ input: {};
57
+ output: {
58
+ data: {
59
+ subtotalCents: number;
60
+ currency: string;
61
+ id: string;
62
+ createdAt: string;
63
+ updatedAt: string;
64
+ taxRegimeId: string | null;
65
+ taxCents: number;
66
+ totalCents: number;
67
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
68
+ bookingId: string;
69
+ notes: string | null;
70
+ templateId: string | null;
71
+ dueDate: string;
72
+ invoiceNumber: string;
73
+ invoiceType: "invoice" | "proforma" | "credit_note";
74
+ convertedFromInvoiceId: string | null;
75
+ seriesId: string | null;
76
+ sequence: number | null;
77
+ language: string | null;
78
+ personId: string | null;
79
+ organizationId: string | null;
80
+ baseCurrency: string | null;
81
+ fxRateSetId: string | null;
82
+ baseSubtotalCents: number | null;
83
+ baseTaxCents: number | null;
84
+ baseTotalCents: number | null;
85
+ paidCents: number;
86
+ basePaidCents: number | null;
87
+ balanceDueCents: number;
88
+ baseBalanceDueCents: number | null;
89
+ commissionPercent: number | null;
90
+ commissionAmountCents: number | null;
91
+ issueDate: string;
92
+ voidedAt: string | null;
93
+ voidReason: string | null;
94
+ } | undefined;
95
+ };
96
+ outputFormat: "json";
97
+ status: 201;
98
+ };
99
+ };
100
+ } & {
101
+ "/invoices/from-booking": {
102
+ $post: {
103
+ input: {};
104
+ output: {
105
+ error: string;
106
+ };
107
+ outputFormat: "json";
108
+ status: 404;
109
+ } | {
110
+ input: {};
111
+ output: {
112
+ error: import("./service-shared.js").InvoiceNumberAllocationErrorCode;
113
+ scope: import("./service-shared.js").InvoiceNumberScope;
114
+ seriesId: string | null;
115
+ };
116
+ outputFormat: "json";
117
+ status: 409;
118
+ } | {
119
+ input: {};
120
+ output: {
121
+ error: string;
122
+ code: string;
123
+ invoiceNumber: string;
124
+ };
125
+ outputFormat: "json";
126
+ status: 409;
127
+ } | {
128
+ input: {};
129
+ output: {
130
+ error: string;
131
+ code: string;
132
+ details: {
133
+ [x: string]: import("hono/utils/types").JSONValue;
134
+ } | undefined;
135
+ };
136
+ outputFormat: "json";
137
+ status: 400;
138
+ } | {
139
+ input: {};
140
+ output: {
141
+ data: {
142
+ subtotalCents: number;
143
+ currency: string;
144
+ id: string;
145
+ createdAt: string;
146
+ updatedAt: string;
147
+ taxRegimeId: string | null;
148
+ taxCents: number;
149
+ totalCents: number;
150
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
151
+ bookingId: string;
152
+ notes: string | null;
153
+ templateId: string | null;
154
+ dueDate: string;
155
+ invoiceNumber: string;
156
+ invoiceType: "invoice" | "proforma" | "credit_note";
157
+ convertedFromInvoiceId: string | null;
158
+ seriesId: string | null;
159
+ sequence: number | null;
160
+ language: string | null;
161
+ personId: string | null;
162
+ organizationId: string | null;
163
+ baseCurrency: string | null;
164
+ fxRateSetId: string | null;
165
+ baseSubtotalCents: number | null;
166
+ baseTaxCents: number | null;
167
+ baseTotalCents: number | null;
168
+ paidCents: number;
169
+ basePaidCents: number | null;
170
+ balanceDueCents: number;
171
+ baseBalanceDueCents: number | null;
172
+ commissionPercent: number | null;
173
+ commissionAmountCents: number | null;
174
+ issueDate: string;
175
+ voidedAt: string | null;
176
+ voidReason: string | null;
177
+ } | null;
178
+ };
179
+ outputFormat: "json";
180
+ status: 201;
181
+ } | {
182
+ input: {};
183
+ output: {
184
+ data: {
185
+ invoice: {
186
+ subtotalCents: number;
187
+ currency: string;
188
+ id: string;
189
+ createdAt: string;
190
+ updatedAt: string;
191
+ taxRegimeId: string | null;
192
+ taxCents: number;
193
+ totalCents: number;
194
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
195
+ bookingId: string;
196
+ notes: string | null;
197
+ templateId: string | null;
198
+ dueDate: string;
199
+ invoiceNumber: string;
200
+ invoiceType: "invoice" | "proforma" | "credit_note";
201
+ convertedFromInvoiceId: string | null;
202
+ seriesId: string | null;
203
+ sequence: number | null;
204
+ language: string | null;
205
+ personId: string | null;
206
+ organizationId: string | null;
207
+ baseCurrency: string | null;
208
+ fxRateSetId: string | null;
209
+ baseSubtotalCents: number | null;
210
+ baseTaxCents: number | null;
211
+ baseTotalCents: number | null;
212
+ paidCents: number;
213
+ basePaidCents: number | null;
214
+ balanceDueCents: number;
215
+ baseBalanceDueCents: number | null;
216
+ commissionPercent: number | null;
217
+ commissionAmountCents: number | null;
218
+ issueDate: string;
219
+ voidedAt: string | null;
220
+ voidReason: string | null;
221
+ };
222
+ rendition: {
223
+ format: "json" | "html" | "pdf" | "xml";
224
+ id: string;
225
+ createdAt: string;
226
+ updatedAt: string;
227
+ metadata: import("hono/utils/types").JSONValue;
228
+ status: "failed" | "pending" | "ready" | "stale";
229
+ errorMessage: string | null;
230
+ invoiceId: string;
231
+ templateId: string | null;
232
+ language: string | null;
233
+ storageKey: string | null;
234
+ fileSize: number | null;
235
+ checksum: string | null;
236
+ generatedAt: string | null;
237
+ } | null;
238
+ };
239
+ };
240
+ outputFormat: "json";
241
+ status: 202;
242
+ } | {
243
+ input: {};
244
+ output: {
245
+ data: {
246
+ download: {
247
+ url: string;
248
+ expiresAt: string | null;
249
+ filename: string | null;
250
+ };
251
+ invoice: {
252
+ subtotalCents: number;
253
+ currency: string;
254
+ id: string;
255
+ createdAt: string;
256
+ updatedAt: string;
257
+ taxRegimeId: string | null;
258
+ taxCents: number;
259
+ totalCents: number;
260
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
261
+ bookingId: string;
262
+ notes: string | null;
263
+ templateId: string | null;
264
+ dueDate: string;
265
+ invoiceNumber: string;
266
+ invoiceType: "invoice" | "proforma" | "credit_note";
267
+ convertedFromInvoiceId: string | null;
268
+ seriesId: string | null;
269
+ sequence: number | null;
270
+ language: string | null;
271
+ personId: string | null;
272
+ organizationId: string | null;
273
+ baseCurrency: string | null;
274
+ fxRateSetId: string | null;
275
+ baseSubtotalCents: number | null;
276
+ baseTaxCents: number | null;
277
+ baseTotalCents: number | null;
278
+ paidCents: number;
279
+ basePaidCents: number | null;
280
+ balanceDueCents: number;
281
+ baseBalanceDueCents: number | null;
282
+ commissionPercent: number | null;
283
+ commissionAmountCents: number | null;
284
+ issueDate: string;
285
+ voidedAt: string | null;
286
+ voidReason: string | null;
287
+ };
288
+ rendition: {
289
+ format: "json" | "html" | "pdf" | "xml";
290
+ id: string;
291
+ createdAt: string;
292
+ updatedAt: string;
293
+ metadata: import("hono/utils/types").JSONValue;
294
+ status: "failed" | "pending" | "ready" | "stale";
295
+ errorMessage: string | null;
296
+ invoiceId: string;
297
+ templateId: string | null;
298
+ language: string | null;
299
+ storageKey: string | null;
300
+ fileSize: number | null;
301
+ checksum: string | null;
302
+ generatedAt: string | null;
303
+ } | null;
304
+ };
305
+ };
306
+ outputFormat: "json";
307
+ status: 201;
308
+ };
309
+ };
310
+ } & {
311
+ "/invoices/:id/convert-to-invoice": {
312
+ $post: {
313
+ input: {
314
+ param: {
315
+ id: string;
316
+ };
317
+ };
318
+ output: {
319
+ error: string;
320
+ };
321
+ outputFormat: "json";
322
+ status: 404;
323
+ } | {
324
+ input: {
325
+ param: {
326
+ id: string;
327
+ };
328
+ };
329
+ output: {
330
+ error: string;
331
+ };
332
+ outputFormat: "json";
333
+ status: 409;
334
+ } | {
335
+ input: {
336
+ param: {
337
+ id: string;
338
+ };
339
+ };
340
+ output: {
341
+ data: {
342
+ subtotalCents: number;
343
+ currency: string;
344
+ id: string;
345
+ createdAt: string;
346
+ updatedAt: string;
347
+ taxRegimeId: string | null;
348
+ taxCents: number;
349
+ totalCents: number;
350
+ status: "void" | "paid" | "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "overdue";
351
+ bookingId: string;
352
+ notes: string | null;
353
+ templateId: string | null;
354
+ dueDate: string;
355
+ invoiceNumber: string;
356
+ invoiceType: "invoice" | "proforma" | "credit_note";
357
+ convertedFromInvoiceId: string | null;
358
+ seriesId: string | null;
359
+ sequence: number | null;
360
+ language: string | null;
361
+ personId: string | null;
362
+ organizationId: string | null;
363
+ baseCurrency: string | null;
364
+ fxRateSetId: string | null;
365
+ baseSubtotalCents: number | null;
366
+ baseTaxCents: number | null;
367
+ baseTotalCents: number | null;
368
+ paidCents: number;
369
+ basePaidCents: number | null;
370
+ balanceDueCents: number;
371
+ baseBalanceDueCents: number | null;
372
+ commissionPercent: number | null;
373
+ commissionAmountCents: number | null;
374
+ issueDate: string;
375
+ voidedAt: string | null;
376
+ voidReason: string | null;
377
+ };
378
+ };
379
+ outputFormat: "json";
380
+ status: 201;
381
+ };
382
+ };
383
+ }, "/", "/invoices/:id/convert-to-invoice">;
384
+ //# sourceMappingURL=routes-invoice-issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes-invoice-issue.d.ts","sourceRoot":"","sources":["../src/routes-invoice-issue.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAe7C,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAqQlC,CAAA"}
@@ -0,0 +1,208 @@
1
+ import { parseJsonBody, parseQuery } from "@voyant-travel/hono";
2
+ import { Hono } from "hono";
3
+ import { FINANCE_ROUTE_RUNTIME_CONTAINER_KEY } from "./route-runtime.js";
4
+ import { buildInlineDownload, getActionLedgerRequestContext, resolveWaitRequest, routeIdempotencyKey, } from "./routes-runtime.js";
5
+ import { financeService, InvoiceFromBookingValidationError, InvoiceNumberAllocationError, InvoiceNumberConflictError, } from "./service.js";
6
+ import { waitForInvoiceRendition, waitFormatForMode } from "./service-rendition-wait.js";
7
+ import { insertInvoiceSchema, invoiceDocumentWaitQuerySchema, invoiceFromBookingSchema, invoiceListQuerySchema, } from "./validation.js";
8
+ export const financeInvoiceIssueRoutes = new Hono()
9
+ // ========================================================================
10
+ // Invoices CRUD
11
+ // ========================================================================
12
+ // GET /invoices — List invoices
13
+ .get("/invoices", async (c) => {
14
+ const query = parseQuery(c, invoiceListQuerySchema);
15
+ return c.json(await financeService.listInvoices(c.get("db"), query));
16
+ })
17
+ // POST /invoices — Create invoice
18
+ .post("/invoices", routeIdempotencyKey("POST /v1/admin/finance/invoices"), async (c) => {
19
+ return c.json({
20
+ data: await financeService.createInvoice(c.get("db"), await parseJsonBody(c, insertInvoiceSchema)),
21
+ }, 201);
22
+ })
23
+ // POST /invoices/from-booking — Create + issue invoice/proforma from a booking or schedule row
24
+ .post("/invoices/from-booking", routeIdempotencyKey("POST /v1/admin/finance/invoices/from-booking", {
25
+ fingerprintSearchParams: ["wait", "waitTimeoutMs"],
26
+ }), async (c) => {
27
+ const input = await parseJsonBody(c, invoiceFromBookingSchema);
28
+ const waitRequest = resolveWaitRequest(input, parseQuery(c, invoiceDocumentWaitQuerySchema));
29
+ const db = c.get("db");
30
+ const [{ bookingItems, bookings }, { bookingPaymentSchedules }, { and, asc, eq }, { issueInvoiceFromBooking, issueProformaFromBooking },] = await Promise.all([
31
+ import("@voyant-travel/bookings/schema"),
32
+ import("./schema.js"),
33
+ import("drizzle-orm"),
34
+ import("./service-issue.js"),
35
+ ]);
36
+ const [booking] = await db
37
+ .select()
38
+ .from(bookings)
39
+ .where(eq(bookings.id, input.bookingId))
40
+ .limit(1);
41
+ if (!booking) {
42
+ return c.json({ error: "Booking not found" }, 404);
43
+ }
44
+ const items = await db
45
+ .select()
46
+ .from(bookingItems)
47
+ .where(eq(bookingItems.bookingId, booking.id))
48
+ .orderBy(asc(bookingItems.createdAt), asc(bookingItems.id));
49
+ const [paymentSchedule] = input.bookingPaymentScheduleId
50
+ ? await db
51
+ .select()
52
+ .from(bookingPaymentSchedules)
53
+ .where(and(eq(bookingPaymentSchedules.id, input.bookingPaymentScheduleId), eq(bookingPaymentSchedules.bookingId, booking.id)))
54
+ .limit(1)
55
+ : [];
56
+ if (input.bookingPaymentScheduleId && !paymentSchedule) {
57
+ return c.json({ error: "Booking payment schedule not found" }, 404);
58
+ }
59
+ const runtime = (() => {
60
+ try {
61
+ return c.var.container?.resolve(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY);
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ })();
67
+ const issuer = input.invoiceType === "proforma" ? issueProformaFromBooking : issueInvoiceFromBooking;
68
+ let row;
69
+ try {
70
+ row = await issuer(db, input, {
71
+ booking: {
72
+ id: booking.id,
73
+ bookingNumber: booking.bookingNumber,
74
+ personId: booking.personId,
75
+ organizationId: booking.organizationId,
76
+ startDate: booking.startDate,
77
+ endDate: booking.endDate,
78
+ sellCurrency: booking.sellCurrency,
79
+ baseCurrency: booking.baseCurrency,
80
+ fxRateSetId: booking.fxRateSetId,
81
+ sellAmountCents: booking.sellAmountCents,
82
+ baseSellAmountCents: booking.baseSellAmountCents,
83
+ },
84
+ paymentSchedule: paymentSchedule
85
+ ? {
86
+ id: paymentSchedule.id,
87
+ bookingId: paymentSchedule.bookingId,
88
+ bookingItemId: paymentSchedule.bookingItemId,
89
+ scheduleType: paymentSchedule.scheduleType,
90
+ dueDate: paymentSchedule.dueDate,
91
+ currency: paymentSchedule.currency,
92
+ amountCents: paymentSchedule.amountCents,
93
+ }
94
+ : null,
95
+ items: items.map((item) => ({
96
+ id: item.id,
97
+ title: item.title,
98
+ productId: item.productId,
99
+ productName: item.productNameSnapshot,
100
+ productNameSnapshot: item.productNameSnapshot,
101
+ optionNameSnapshot: item.optionNameSnapshot,
102
+ unitNameSnapshot: item.unitNameSnapshot,
103
+ departureLabelSnapshot: item.departureLabelSnapshot,
104
+ startDate: item.serviceDate ?? item.startsAt,
105
+ serviceDate: item.serviceDate,
106
+ startsAt: item.startsAt,
107
+ endDate: item.endsAt ?? item.serviceDate,
108
+ endsAt: item.endsAt,
109
+ quantity: item.quantity,
110
+ unitSellAmountCents: item.unitSellAmountCents,
111
+ totalSellAmountCents: item.totalSellAmountCents,
112
+ })),
113
+ }, {
114
+ ...(runtime ?? {}),
115
+ actionLedgerContext: getActionLedgerRequestContext(c),
116
+ actionLedgerAuthorizationSource: "finance.invoice.from_booking.route",
117
+ });
118
+ }
119
+ catch (error) {
120
+ if (error instanceof InvoiceNumberAllocationError) {
121
+ return c.json({ error: error.code, scope: error.scope, seriesId: error.seriesId ?? null }, 409);
122
+ }
123
+ if (error instanceof InvoiceNumberConflictError) {
124
+ return c.json({
125
+ error: "Invoice number already exists",
126
+ code: error.code,
127
+ invoiceNumber: error.invoiceNumber,
128
+ }, 409);
129
+ }
130
+ if (error instanceof InvoiceFromBookingValidationError) {
131
+ return c.json({ error: error.message, code: error.code, details: error.details }, error.status);
132
+ }
133
+ throw error;
134
+ }
135
+ if (!row || waitRequest.mode === "none") {
136
+ return c.json({ data: row }, 201);
137
+ }
138
+ const waitResult = await waitForInvoiceRendition(db, row.id, {
139
+ format: waitFormatForMode(waitRequest.mode),
140
+ timeoutMs: waitRequest.timeoutMs,
141
+ });
142
+ const payload = {
143
+ invoice: row,
144
+ rendition: waitResult.rendition,
145
+ };
146
+ if (waitResult.status !== "ready") {
147
+ return c.json({ data: payload }, 202);
148
+ }
149
+ const download = await buildInlineDownload(c, waitResult.rendition);
150
+ if (download.status !== "ready") {
151
+ return c.json({ data: payload }, 202);
152
+ }
153
+ return c.json({ data: { ...payload, download: download.download } }, 201);
154
+ })
155
+ // POST /invoices/:id/convert-to-invoice — Convert a proforma into a final invoice
156
+ .post("/invoices/:id/convert-to-invoice", async (c) => {
157
+ const { convertProformaToInvoice } = await import("./service-issue.js");
158
+ const input = await c.req
159
+ .json()
160
+ .catch(() => ({}));
161
+ const runtime = (() => {
162
+ try {
163
+ return c.var.container?.resolve(FINANCE_ROUTE_RUNTIME_CONTAINER_KEY);
164
+ }
165
+ catch {
166
+ return undefined;
167
+ }
168
+ })();
169
+ let result;
170
+ try {
171
+ result = await convertProformaToInvoice(c.get("db"), c.req.param("id"), input, {
172
+ eventBus: runtime?.eventBus,
173
+ });
174
+ }
175
+ catch (error) {
176
+ if (error instanceof InvoiceNumberConflictError) {
177
+ return c.json({
178
+ error: "Invoice number already exists",
179
+ code: error.code,
180
+ invoiceNumber: error.invoiceNumber,
181
+ }, 409);
182
+ }
183
+ throw error;
184
+ }
185
+ if (result.status === "not_found") {
186
+ return c.json({ error: "Invoice not found" }, 404);
187
+ }
188
+ if (result.status === "not_proforma") {
189
+ return c.json({ error: "Only proforma invoices can be converted" }, 409);
190
+ }
191
+ if (result.status === "already_converted") {
192
+ return c.json({
193
+ error: "This proforma has already been converted",
194
+ code: "proforma_already_converted",
195
+ existingInvoiceId: result.invoice?.id ?? null,
196
+ existingInvoiceNumber: result.invoice?.invoiceNumber ?? null,
197
+ }, 409);
198
+ }
199
+ if (result.status === "duplicate_fiscal_invoice") {
200
+ return c.json({
201
+ error: "A fiscal invoice already exists for this booking amount",
202
+ code: "duplicate_fiscal_invoice",
203
+ existingInvoiceId: result.invoice.id,
204
+ existingInvoiceNumber: result.invoice.invoiceNumber,
205
+ }, 409);
206
+ }
207
+ return c.json({ data: result.invoice }, 201);
208
+ });