@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,124 @@
1
+ import type { HonoExtension } from "@voyant-travel/hono/module";
2
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
3
+ import type { Hono } from "hono";
4
+ export type ProductTaxFacts = {
5
+ hasAccommodation: boolean;
6
+ accommodationCountries: string[];
7
+ };
8
+ export type ResolvedBookingSellTaxRate = {
9
+ code: string;
10
+ label: string;
11
+ rate: number;
12
+ priceMode: "inclusive" | "exclusive";
13
+ };
14
+ export type BookingTaxSettings = {
15
+ taxPriceMode?: "inclusive" | "exclusive" | null;
16
+ taxPolicyProfileId?: string | null;
17
+ };
18
+ export type ResolveBookingTaxSettings = (db: PostgresJsDatabase) => BookingTaxSettings | null | undefined | Promise<BookingTaxSettings | null | undefined>;
19
+ export type UpdateBookingTaxSettings = (db: PostgresJsDatabase, settings: BookingTaxSettings) => BookingTaxSettings | null | undefined | Promise<BookingTaxSettings | null | undefined>;
20
+ export type TaxPolicyCondition = {
21
+ always: true;
22
+ } | {
23
+ all: TaxPolicyCondition[];
24
+ } | {
25
+ any: TaxPolicyCondition[];
26
+ } | {
27
+ fact: keyof ProductTaxFacts;
28
+ eq?: unknown;
29
+ contains?: unknown;
30
+ };
31
+ export interface ResolveBookingSellTaxRateOptions {
32
+ settings?: BookingTaxSettings | null;
33
+ resolveBookingTaxSettings?: ResolveBookingTaxSettings;
34
+ }
35
+ export interface BookingTaxRouteOptions extends ResolveBookingSellTaxRateOptions {
36
+ updateBookingTaxSettings?: UpdateBookingTaxSettings;
37
+ }
38
+ export declare function resolveBookingSellTaxRate(db: PostgresJsDatabase, args: {
39
+ productId?: string | null;
40
+ facts?: Partial<ProductTaxFacts>;
41
+ }, options?: ResolveBookingSellTaxRateOptions): Promise<ResolvedBookingSellTaxRate | null>;
42
+ export declare function computeBookingItemTaxLine(taxRate: ResolvedBookingSellTaxRate | null, amountCents: number, currency: string, sortOrder?: number): {
43
+ code: string;
44
+ name: string;
45
+ scope: "included" | "excluded";
46
+ currency: string;
47
+ amountCents: number;
48
+ rateBasisPoints: number;
49
+ includedInPrice: boolean;
50
+ sortOrder: number;
51
+ } | null;
52
+ export declare function loadProductTaxFacts(db: PostgresJsDatabase, productId: string): Promise<ProductTaxFacts>;
53
+ export declare function matchesTaxPolicyCondition(condition: TaxPolicyCondition | null | undefined, facts: ProductTaxFacts): boolean;
54
+ export declare function createBookingTaxRoutes(options?: BookingTaxRouteOptions): import("hono/hono-base").HonoBase<{
55
+ Variables: {
56
+ db: PostgresJsDatabase;
57
+ };
58
+ }, {
59
+ "/tax-settings": {
60
+ $get: {
61
+ input: {};
62
+ output: {
63
+ data: {
64
+ taxPriceMode?: "inclusive" | "exclusive" | null | undefined;
65
+ taxPolicyProfileId?: string | null | undefined;
66
+ };
67
+ };
68
+ outputFormat: "json";
69
+ status: import("hono/utils/http-status").ContentfulStatusCode;
70
+ };
71
+ };
72
+ } & {
73
+ "/tax-settings": {
74
+ $patch: {
75
+ input: {};
76
+ output: {
77
+ data: {
78
+ taxPriceMode?: "inclusive" | "exclusive" | null | undefined;
79
+ taxPolicyProfileId?: string | null | undefined;
80
+ };
81
+ };
82
+ outputFormat: "json";
83
+ status: import("hono/utils/http-status").ContentfulStatusCode;
84
+ };
85
+ };
86
+ } & {
87
+ "/tax-preview": {
88
+ $post: {
89
+ input: {};
90
+ output: {
91
+ data: {
92
+ subtotalCents: number;
93
+ taxCents: number;
94
+ totalCents: number;
95
+ currency: string;
96
+ taxRate: null;
97
+ };
98
+ };
99
+ outputFormat: "json";
100
+ status: import("hono/utils/http-status").ContentfulStatusCode;
101
+ } | {
102
+ input: {};
103
+ output: {
104
+ data: {
105
+ subtotalCents: number;
106
+ taxCents: number;
107
+ totalCents: number;
108
+ currency: string;
109
+ taxRate: {
110
+ code: string;
111
+ label: string;
112
+ rateBasisPoints: number;
113
+ priceMode: "inclusive" | "exclusive";
114
+ };
115
+ };
116
+ };
117
+ outputFormat: "json";
118
+ status: import("hono/utils/http-status").ContentfulStatusCode;
119
+ };
120
+ };
121
+ }, "/", "/tax-preview">;
122
+ export declare function mountBookingTaxRoutes(hono: Hono, options?: BookingTaxRouteOptions): void;
123
+ export declare function createBookingTaxHonoExtension(options?: BookingTaxRouteOptions): HonoExtension;
124
+ //# sourceMappingURL=booking-tax.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"booking-tax.d.ts","sourceRoot":"","sources":["../src/booking-tax.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAOhC,MAAM,MAAM,eAAe,GAAG;IAC5B,gBAAgB,EAAE,OAAO,CAAA;IACzB,sBAAsB,EAAE,MAAM,EAAE,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,WAAW,GAAG,WAAW,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAAA;IAC/C,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,EAAE,EAAE,kBAAkB,KACnB,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;AAE3F,MAAM,MAAM,wBAAwB,GAAG,CACrC,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,kBAAkB,KACzB,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;AAE3F,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAChB;IAAE,GAAG,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAC7B;IAAE,GAAG,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,MAAM,eAAe,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAErE,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACpC,yBAAyB,CAAC,EAAE,yBAAyB,CAAA;CACtD;AAED,MAAM,WAAW,sBAAuB,SAAQ,gCAAgC;IAC9E,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;CACpD;AAaD,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,kBAAkB,EACtB,IAAI,EAAE;IACJ,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;CACjC,EACD,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAoC5C;AAiBD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAAG,IAAI,EAC1C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI;;;;;;;;;SAmBd;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAgC1B;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAChD,KAAK,EAAE,eAAe,GACrB,OAAO,CAeT;AA6FD,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B;eAE5D;QACT,EAAE,EAAE,kBAAkB,CAAA;KACvB;;;;;;;mCApRY,WAAW,GAAG,WAAW,GAAG,IAAI;yCAC1B,MAAM,GAAG,IAAI;;;;;;;;;;;;;mCADnB,WAAW,GAAG,WAAW,GAAG,IAAI;yCAC1B,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA0VnC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,sBAA2B,GAAG,IAAI,CAE5F;AAED,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,sBAA2B,GAAG,aAAa,CAUjG"}
@@ -0,0 +1,264 @@
1
+ import { ApiHttpError, parseJsonBody } from "@voyant-travel/hono";
2
+ import { and, asc, eq, sql } from "drizzle-orm";
3
+ import { Hono as HonoApp } from "hono";
4
+ import { z } from "zod";
5
+ import { taxClasses, taxPolicyProfiles, taxPolicyRules, taxRegimes } from "./schema.js";
6
+ import { executeBoundaryRows } from "./service-boundary-sql.js";
7
+ const taxPreviewBodySchema = z.object({
8
+ productId: z.string().min(1),
9
+ subtotalCents: z.number().int().min(0),
10
+ currency: z.string().min(3).max(8),
11
+ });
12
+ const bookingTaxSettingsPatchSchema = z.object({
13
+ taxPriceMode: z.enum(["inclusive", "exclusive"]).optional(),
14
+ taxPolicyProfileId: z.string().min(1).nullable().optional(),
15
+ });
16
+ export async function resolveBookingSellTaxRate(db, args, options = {}) {
17
+ const resolvedSettings = options.settings !== undefined
18
+ ? options.settings
19
+ : ((await options.resolveBookingTaxSettings?.(db)) ?? null);
20
+ const priceMode = resolvedSettings?.taxPriceMode === "exclusive" ? "exclusive" : "inclusive";
21
+ const policyProfile = await resolveTaxPolicyProfile(db, resolvedSettings?.taxPolicyProfileId);
22
+ if (policyProfile) {
23
+ const facts = normalizeTaxFacts(args.facts ?? (args.productId ? await loadProductTaxFacts(db, args.productId) : undefined));
24
+ const rules = await db
25
+ .select({
26
+ condition: taxPolicyRules.condition,
27
+ taxRegimeId: taxPolicyRules.taxRegimeId,
28
+ })
29
+ .from(taxPolicyRules)
30
+ .where(and(eq(taxPolicyRules.profileId, policyProfile.id), eq(taxPolicyRules.side, "sell"), eq(taxPolicyRules.active, true)))
31
+ .orderBy(asc(taxPolicyRules.priority), asc(taxPolicyRules.createdAt));
32
+ for (const rule of rules) {
33
+ if (!matchesTaxPolicyCondition(rule.condition, facts))
34
+ continue;
35
+ const resolved = await loadResolvedTaxRegime(db, rule.taxRegimeId, policyProfile.code);
36
+ if (resolved)
37
+ return { ...resolved, priceMode };
38
+ }
39
+ }
40
+ return args.productId ? resolveProductTaxClassRate(db, args.productId, priceMode) : null;
41
+ }
42
+ async function resolveBookingTaxSettingsOrDefault(db, options = {}) {
43
+ const settings = options.settings !== undefined
44
+ ? options.settings
45
+ : ((await options.resolveBookingTaxSettings?.(db)) ?? null);
46
+ return {
47
+ taxPriceMode: settings?.taxPriceMode === "exclusive" ? "exclusive" : "inclusive",
48
+ taxPolicyProfileId: settings?.taxPolicyProfileId ?? null,
49
+ };
50
+ }
51
+ export function computeBookingItemTaxLine(taxRate, amountCents, currency, sortOrder = 0) {
52
+ if (!taxRate || taxRate.rate <= 0 || amountCents <= 0)
53
+ return null;
54
+ const includedInPrice = taxRate.priceMode === "inclusive";
55
+ const taxCents = includedInPrice
56
+ ? Math.round(amountCents - amountCents / (1 + taxRate.rate))
57
+ : Math.round(amountCents * taxRate.rate);
58
+ if (taxCents <= 0)
59
+ return null;
60
+ return {
61
+ code: taxRate.code,
62
+ name: taxRate.label,
63
+ scope: includedInPrice ? "included" : "excluded",
64
+ currency,
65
+ amountCents: taxCents,
66
+ rateBasisPoints: Math.round(taxRate.rate * 10_000),
67
+ includedInPrice,
68
+ sortOrder,
69
+ };
70
+ }
71
+ export async function loadProductTaxFacts(db, productId) {
72
+ const [accommodationLocations, accommodationServices] = await Promise.all([
73
+ executeBoundaryRows(db,
74
+ // agent-quality: raw-sql reviewed -- owner: finance; Product owns product_locations and product ids are parameter-bound through Drizzle.
75
+ sql `
76
+ SELECT country_code
77
+ FROM product_locations
78
+ WHERE product_id = ${productId}
79
+ `),
80
+ executeBoundaryRows(db,
81
+ // agent-quality: raw-sql reviewed -- owner: finance; Product itinerary tables are read-only tax fact inputs with parameter-bound product id.
82
+ sql `
83
+ SELECT pds.id, pds.country_code
84
+ FROM product_day_services pds
85
+ INNER JOIN product_days pd ON pds.day_id = pd.id
86
+ INNER JOIN product_itineraries pi ON pd.itinerary_id = pi.id
87
+ WHERE pi.product_id = ${productId}
88
+ AND pds.service_type::text = 'accommodation'
89
+ `),
90
+ ]);
91
+ const accommodationCountries = [...accommodationServices, ...accommodationLocations]
92
+ .map((entry) => entry.country_code?.trim().toUpperCase())
93
+ .filter((countryCode) => Boolean(countryCode));
94
+ return {
95
+ hasAccommodation: accommodationLocations.length > 0 || accommodationServices.length > 0,
96
+ accommodationCountries: [...new Set(accommodationCountries)],
97
+ };
98
+ }
99
+ export function matchesTaxPolicyCondition(condition, facts) {
100
+ if (!condition)
101
+ return true;
102
+ if ("always" in condition)
103
+ return condition.always === true;
104
+ if ("all" in condition)
105
+ return condition.all.every((entry) => matchesTaxPolicyCondition(entry, facts));
106
+ if ("any" in condition)
107
+ return condition.any.some((entry) => matchesTaxPolicyCondition(entry, facts));
108
+ if (!("fact" in condition))
109
+ return false;
110
+ const value = facts[condition.fact];
111
+ if ("eq" in condition)
112
+ return value === condition.eq;
113
+ if ("contains" in condition) {
114
+ return Array.isArray(value) && value.includes(String(condition.contains).toUpperCase());
115
+ }
116
+ return false;
117
+ }
118
+ function normalizeTaxFacts(facts) {
119
+ return {
120
+ hasAccommodation: facts?.hasAccommodation === true,
121
+ accommodationCountries: [
122
+ ...new Set((facts?.accommodationCountries ?? [])
123
+ .map((countryCode) => countryCode.trim().toUpperCase())
124
+ .filter(Boolean)),
125
+ ],
126
+ };
127
+ }
128
+ async function resolveTaxPolicyProfile(db, configuredProfileId) {
129
+ if (configuredProfileId) {
130
+ const [configured] = await db
131
+ .select()
132
+ .from(taxPolicyProfiles)
133
+ .where(eq(taxPolicyProfiles.id, configuredProfileId))
134
+ .limit(1);
135
+ if (configured?.active)
136
+ return configured;
137
+ }
138
+ const [active] = await db
139
+ .select()
140
+ .from(taxPolicyProfiles)
141
+ .where(eq(taxPolicyProfiles.active, true))
142
+ .orderBy(asc(taxPolicyProfiles.createdAt))
143
+ .limit(1);
144
+ return active ?? null;
145
+ }
146
+ async function loadResolvedTaxRegime(db, taxRegimeId, codePrefix) {
147
+ const [regime] = await db
148
+ .select({
149
+ ratePercent: taxRegimes.ratePercent,
150
+ code: taxRegimes.code,
151
+ name: taxRegimes.name,
152
+ })
153
+ .from(taxRegimes)
154
+ .where(eq(taxRegimes.id, taxRegimeId))
155
+ .limit(1);
156
+ if (!regime || regime.ratePercent == null)
157
+ return null;
158
+ return {
159
+ code: `${codePrefix}/${regime.code}`,
160
+ label: regime.name,
161
+ rate: regime.ratePercent / 100,
162
+ };
163
+ }
164
+ async function resolveProductTaxClassRate(db, productId, priceMode) {
165
+ const productRows = await executeBoundaryRows(db,
166
+ // agent-quality: raw-sql reviewed -- owner: finance; Product owns product tax-class assignment and product id is parameter-bound.
167
+ sql `
168
+ SELECT tax_class_id
169
+ FROM products
170
+ WHERE id = ${productId}
171
+ LIMIT 1
172
+ `);
173
+ const taxClassId = productRows[0]?.tax_class_id;
174
+ if (!taxClassId)
175
+ return null;
176
+ const classRows = await db
177
+ .select({
178
+ defaultRegimeId: taxClasses.defaultRegimeId,
179
+ code: taxClasses.code,
180
+ })
181
+ .from(taxClasses)
182
+ .where(eq(taxClasses.id, taxClassId))
183
+ .limit(1);
184
+ const klass = classRows[0];
185
+ if (!klass?.defaultRegimeId)
186
+ return null;
187
+ const resolved = await loadResolvedTaxRegime(db, klass.defaultRegimeId, klass.code);
188
+ return resolved ? { ...resolved, priceMode } : null;
189
+ }
190
+ export function createBookingTaxRoutes(options = {}) {
191
+ return new HonoApp()
192
+ .get("/tax-settings", async (c) => {
193
+ return c.json({
194
+ data: await resolveBookingTaxSettingsOrDefault(c.get("db"), options),
195
+ });
196
+ })
197
+ .patch("/tax-settings", async (c) => {
198
+ if (!options.updateBookingTaxSettings) {
199
+ throw new ApiHttpError("Booking tax settings updates are not configured", {
200
+ status: 409,
201
+ code: "booking_tax_settings_update_not_configured",
202
+ });
203
+ }
204
+ const current = await resolveBookingTaxSettingsOrDefault(c.get("db"), options);
205
+ const patch = await parseJsonBody(c, bookingTaxSettingsPatchSchema);
206
+ const next = await options.updateBookingTaxSettings(c.get("db"), {
207
+ taxPriceMode: patch.taxPriceMode ?? current.taxPriceMode,
208
+ taxPolicyProfileId: patch.taxPolicyProfileId === undefined
209
+ ? current.taxPolicyProfileId
210
+ : patch.taxPolicyProfileId,
211
+ });
212
+ return c.json({
213
+ data: await resolveBookingTaxSettingsOrDefault(c.get("db"), { settings: next }),
214
+ });
215
+ })
216
+ .post("/tax-preview", async (c) => {
217
+ const body = await parseJsonBody(c, taxPreviewBodySchema);
218
+ const taxRate = await resolveBookingSellTaxRate(c.get("db"), { productId: body.productId }, options);
219
+ const taxLine = computeBookingItemTaxLine(taxRate, body.subtotalCents, body.currency);
220
+ if (!taxRate || !taxLine) {
221
+ return c.json({
222
+ data: {
223
+ subtotalCents: body.subtotalCents,
224
+ taxCents: 0,
225
+ totalCents: body.subtotalCents,
226
+ currency: body.currency,
227
+ taxRate: null,
228
+ },
229
+ });
230
+ }
231
+ const inclusive = taxLine.includedInPrice;
232
+ const displaySubtotal = inclusive
233
+ ? Math.max(0, body.subtotalCents - taxLine.amountCents)
234
+ : body.subtotalCents;
235
+ const total = inclusive ? body.subtotalCents : body.subtotalCents + taxLine.amountCents;
236
+ return c.json({
237
+ data: {
238
+ subtotalCents: displaySubtotal,
239
+ taxCents: taxLine.amountCents,
240
+ totalCents: total,
241
+ currency: body.currency,
242
+ taxRate: {
243
+ code: taxRate.code,
244
+ label: taxRate.label,
245
+ rateBasisPoints: Math.round(taxRate.rate * 10_000),
246
+ priceMode: taxRate.priceMode,
247
+ },
248
+ },
249
+ });
250
+ });
251
+ }
252
+ export function mountBookingTaxRoutes(hono, options = {}) {
253
+ hono.route("/v1/admin/bookings", createBookingTaxRoutes(options));
254
+ }
255
+ export function createBookingTaxHonoExtension(options = {}) {
256
+ const extension = {
257
+ name: "booking-tax",
258
+ module: "bookings",
259
+ };
260
+ return {
261
+ extension,
262
+ adminRoutes: createBookingTaxRoutes(options),
263
+ };
264
+ }