@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.
- package/LICENSE +201 -0
- package/README.md +192 -0
- package/dist/action-ledger-drift.d.ts +29 -0
- package/dist/action-ledger-drift.d.ts.map +1 -0
- package/dist/action-ledger-drift.js +166 -0
- package/dist/booking-tax.d.ts +124 -0
- package/dist/booking-tax.d.ts.map +1 -0
- package/dist/booking-tax.js +264 -0
- package/dist/checkout-routes.d.ts +1154 -0
- package/dist/checkout-routes.d.ts.map +1 -0
- package/dist/checkout-routes.js +116 -0
- package/dist/checkout-service-plan.d.ts +137 -0
- package/dist/checkout-service-plan.d.ts.map +1 -0
- package/dist/checkout-service-plan.js +119 -0
- package/dist/checkout-service.d.ts +9 -0
- package/dist/checkout-service.d.ts.map +1 -0
- package/dist/checkout-service.js +324 -0
- package/dist/checkout-validation.d.ts +1682 -0
- package/dist/checkout-validation.d.ts.map +1 -0
- package/dist/checkout-validation.js +228 -0
- package/dist/document-download.d.ts +3 -0
- package/dist/document-download.d.ts.map +1 -0
- package/dist/document-download.js +1 -0
- package/dist/fx-money.d.ts +17 -0
- package/dist/fx-money.d.ts.map +1 -0
- package/dist/fx-money.js +194 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/dist/invoice-fx.d.ts +134 -0
- package/dist/invoice-fx.d.ts.map +1 -0
- package/dist/invoice-fx.js +240 -0
- package/dist/invoice-number-errors.d.ts +2 -0
- package/dist/invoice-number-errors.d.ts.map +1 -0
- package/dist/invoice-number-errors.js +58 -0
- package/dist/markets-ref.d.ts +149 -0
- package/dist/markets-ref.d.ts.map +1 -0
- package/dist/markets-ref.js +17 -0
- package/dist/payment-link.d.ts +23 -0
- package/dist/payment-link.d.ts.map +1 -0
- package/dist/payment-link.js +30 -0
- package/dist/payment-policy.d.ts +113 -0
- package/dist/payment-policy.d.ts.map +1 -0
- package/dist/payment-policy.js +193 -0
- package/dist/route-runtime.d.ts +22 -0
- package/dist/route-runtime.d.ts.map +1 -0
- package/dist/route-runtime.js +18 -0
- package/dist/routes-action-ledger.d.ts +181 -0
- package/dist/routes-action-ledger.d.ts.map +1 -0
- package/dist/routes-action-ledger.js +142 -0
- package/dist/routes-booking-billing.d.ts +852 -0
- package/dist/routes-booking-billing.d.ts.map +1 -0
- package/dist/routes-booking-billing.js +223 -0
- package/dist/routes-booking-create.d.ts +3 -0
- package/dist/routes-booking-create.d.ts.map +1 -0
- package/dist/routes-booking-create.js +194 -0
- package/dist/routes-booking-reads.d.ts +46 -0
- package/dist/routes-booking-reads.d.ts.map +1 -0
- package/dist/routes-booking-reads.js +20 -0
- package/dist/routes-documents.d.ts +195 -0
- package/dist/routes-documents.d.ts.map +1 -0
- package/dist/routes-documents.js +93 -0
- package/dist/routes-invoice-core.d.ts +794 -0
- package/dist/routes-invoice-core.d.ts.map +1 -0
- package/dist/routes-invoice-core.js +238 -0
- package/dist/routes-invoice-documents.d.ts +401 -0
- package/dist/routes-invoice-documents.d.ts.map +1 -0
- package/dist/routes-invoice-documents.js +91 -0
- package/dist/routes-invoice-issue.d.ts +384 -0
- package/dist/routes-invoice-issue.d.ts.map +1 -0
- package/dist/routes-invoice-issue.js +208 -0
- package/dist/routes-payment-processing.d.ts +1193 -0
- package/dist/routes-payment-processing.d.ts.map +1 -0
- package/dist/routes-payment-processing.js +238 -0
- package/dist/routes-payments.d.ts +309 -0
- package/dist/routes-payments.d.ts.map +1 -0
- package/dist/routes-payments.js +94 -0
- package/dist/routes-public.d.ts +1948 -0
- package/dist/routes-public.d.ts.map +1 -0
- package/dist/routes-public.js +275 -0
- package/dist/routes-reference-data.d.ts +977 -0
- package/dist/routes-reference-data.d.ts.map +1 -0
- package/dist/routes-reference-data.js +191 -0
- package/dist/routes-reports.d.ts +344 -0
- package/dist/routes-reports.d.ts.map +1 -0
- package/dist/routes-reports.js +93 -0
- package/dist/routes-runtime.d.ts +71 -0
- package/dist/routes-runtime.d.ts.map +1 -0
- package/dist/routes-runtime.js +59 -0
- package/dist/routes-settlement.d.ts +67 -0
- package/dist/routes-settlement.d.ts.map +1 -0
- package/dist/routes-settlement.js +23 -0
- package/dist/routes-shared.d.ts +35 -0
- package/dist/routes-shared.d.ts.map +1 -0
- package/dist/routes-shared.js +10 -0
- package/dist/routes-supplier-invoices.d.ts +778 -0
- package/dist/routes-supplier-invoices.d.ts.map +1 -0
- package/dist/routes-supplier-invoices.js +159 -0
- package/dist/routes-vouchers.d.ts +228 -0
- package/dist/routes-vouchers.d.ts.map +1 -0
- package/dist/routes-vouchers.js +54 -0
- package/dist/routes.d.ts +5577 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +44 -0
- package/dist/schema/booking-billing.d.ts +1006 -0
- package/dist/schema/booking-billing.d.ts.map +1 -0
- package/dist/schema/booking-billing.js +106 -0
- package/dist/schema/enums.d.ts +48 -0
- package/dist/schema/enums.d.ts.map +1 -0
- package/dist/schema/enums.js +237 -0
- package/dist/schema/invoice-documents.d.ts +1245 -0
- package/dist/schema/invoice-documents.d.ts.map +1 -0
- package/dist/schema/invoice-documents.js +140 -0
- package/dist/schema/payment-instruments.d.ts +418 -0
- package/dist/schema/payment-instruments.d.ts.map +1 -0
- package/dist/schema/payment-instruments.js +45 -0
- package/dist/schema/payment-processing.d.ts +563 -0
- package/dist/schema/payment-processing.d.ts.map +1 -0
- package/dist/schema/payment-processing.js +65 -0
- package/dist/schema/payment-sessions.d.ts +728 -0
- package/dist/schema/payment-sessions.d.ts.map +1 -0
- package/dist/schema/payment-sessions.js +79 -0
- package/dist/schema/receivables.d.ts +1474 -0
- package/dist/schema/receivables.d.ts.map +1 -0
- package/dist/schema/receivables.js +179 -0
- package/dist/schema/relations.d.ts +82 -0
- package/dist/schema/relations.d.ts.map +1 -0
- package/dist/schema/relations.js +144 -0
- package/dist/schema/supplier-invoices.d.ts +1619 -0
- package/dist/schema/supplier-invoices.d.ts.map +1 -0
- package/dist/schema/supplier-invoices.js +228 -0
- package/dist/schema/tax.d.ts +712 -0
- package/dist/schema/tax.d.ts.map +1 -0
- package/dist/schema/tax.js +98 -0
- package/dist/schema/vouchers.d.ts +444 -0
- package/dist/schema/vouchers.d.ts.map +1 -0
- package/dist/schema/vouchers.js +64 -0
- package/dist/schema.d.ts +12 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +11 -0
- package/dist/service-accountant-shares.d.ts +106 -0
- package/dist/service-accountant-shares.d.ts.map +1 -0
- package/dist/service-accountant-shares.js +331 -0
- package/dist/service-action-ledger-accounting.d.ts +104 -0
- package/dist/service-action-ledger-accounting.d.ts.map +1 -0
- package/dist/service-action-ledger-accounting.js +386 -0
- package/dist/service-action-ledger-booking-payments.d.ts +48 -0
- package/dist/service-action-ledger-booking-payments.d.ts.map +1 -0
- package/dist/service-action-ledger-booking-payments.js +178 -0
- package/dist/service-action-ledger-bookings.d.ts +44 -0
- package/dist/service-action-ledger-bookings.d.ts.map +1 -0
- package/dist/service-action-ledger-bookings.js +81 -0
- package/dist/service-action-ledger-payment-authorizations.d.ts +48 -0
- package/dist/service-action-ledger-payment-authorizations.d.ts.map +1 -0
- package/dist/service-action-ledger-payment-authorizations.js +209 -0
- package/dist/service-action-ledger-payment-sessions.d.ts +83 -0
- package/dist/service-action-ledger-payment-sessions.d.ts.map +1 -0
- package/dist/service-action-ledger-payment-sessions.js +294 -0
- package/dist/service-action-ledger-supplier-invoices.d.ts +27 -0
- package/dist/service-action-ledger-supplier-invoices.d.ts.map +1 -0
- package/dist/service-action-ledger-supplier-invoices.js +111 -0
- package/dist/service-action-ledger-supplier-payments.d.ts +21 -0
- package/dist/service-action-ledger-supplier-payments.d.ts.map +1 -0
- package/dist/service-action-ledger-supplier-payments.js +97 -0
- package/dist/service-action-ledger.d.ts +7 -0
- package/dist/service-action-ledger.d.ts.map +1 -0
- package/dist/service-action-ledger.js +6 -0
- package/dist/service-aggregates.d.ts +96 -0
- package/dist/service-aggregates.d.ts.map +1 -0
- package/dist/service-aggregates.js +294 -0
- package/dist/service-booking-billing.d.ts +2322 -0
- package/dist/service-booking-billing.d.ts.map +1 -0
- package/dist/service-booking-billing.js +8 -0
- package/dist/service-booking-create.d.ts +410 -0
- package/dist/service-booking-create.d.ts.map +1 -0
- package/dist/service-booking-create.js +1256 -0
- package/dist/service-booking-guarantees.d.ts +725 -0
- package/dist/service-booking-guarantees.d.ts.map +1 -0
- package/dist/service-booking-guarantees.js +153 -0
- package/dist/service-booking-item-billing.d.ts +1062 -0
- package/dist/service-booking-item-billing.d.ts.map +1 -0
- package/dist/service-booking-item-billing.js +77 -0
- package/dist/service-booking-payment-schedules.d.ts +557 -0
- package/dist/service-booking-payment-schedules.d.ts.map +1 -0
- package/dist/service-booking-payment-schedules.js +372 -0
- package/dist/service-bookings-dual-create.d.ts +308 -0
- package/dist/service-bookings-dual-create.d.ts.map +1 -0
- package/dist/service-bookings-dual-create.js +131 -0
- package/dist/service-boundary-sql.d.ts +6 -0
- package/dist/service-boundary-sql.d.ts.map +1 -0
- package/dist/service-boundary-sql.js +15 -0
- package/dist/service-cost-categories.d.ts +26 -0
- package/dist/service-cost-categories.d.ts.map +1 -0
- package/dist/service-cost-categories.js +76 -0
- package/dist/service-documents.d.ts +80 -0
- package/dist/service-documents.d.ts.map +1 -0
- package/dist/service-documents.js +228 -0
- package/dist/service-invoice-artifacts.d.ts +246 -0
- package/dist/service-invoice-artifacts.d.ts.map +1 -0
- package/dist/service-invoice-artifacts.js +277 -0
- package/dist/service-invoice-core.d.ts +405 -0
- package/dist/service-invoice-core.d.ts.map +1 -0
- package/dist/service-invoice-core.js +290 -0
- package/dist/service-invoice-credit-notes.d.ts +973 -0
- package/dist/service-invoice-credit-notes.d.ts.map +1 -0
- package/dist/service-invoice-credit-notes.js +142 -0
- package/dist/service-invoice-from-booking.d.ts +41 -0
- package/dist/service-invoice-from-booking.d.ts.map +1 -0
- package/dist/service-invoice-from-booking.js +267 -0
- package/dist/service-invoice-line-items.d.ts +432 -0
- package/dist/service-invoice-line-items.d.ts.map +1 -0
- package/dist/service-invoice-line-items.js +102 -0
- package/dist/service-invoice-numbering.d.ts +227 -0
- package/dist/service-invoice-numbering.d.ts.map +1 -0
- package/dist/service-invoice-numbering.js +260 -0
- package/dist/service-invoice-payments.d.ts +673 -0
- package/dist/service-invoice-payments.d.ts.map +1 -0
- package/dist/service-invoice-payments.js +398 -0
- package/dist/service-invoices.d.ts +2501 -0
- package/dist/service-invoices.d.ts.map +1 -0
- package/dist/service-invoices.js +12 -0
- package/dist/service-issue.d.ts +207 -0
- package/dist/service-issue.d.ts.map +1 -0
- package/dist/service-issue.js +431 -0
- package/dist/service-payment-authorizations.d.ts +164 -0
- package/dist/service-payment-authorizations.d.ts.map +1 -0
- package/dist/service-payment-authorizations.js +227 -0
- package/dist/service-payment-instruments.d.ts +116 -0
- package/dist/service-payment-instruments.d.ts.map +1 -0
- package/dist/service-payment-instruments.js +99 -0
- package/dist/service-payment-processing.d.ts +676 -0
- package/dist/service-payment-processing.d.ts.map +1 -0
- package/dist/service-payment-processing.js +10 -0
- package/dist/service-payment-session-completion.d.ts +48 -0
- package/dist/service-payment-session-completion.d.ts.map +1 -0
- package/dist/service-payment-session-completion.js +238 -0
- package/dist/service-payment-sessions.d.ts +361 -0
- package/dist/service-payment-sessions.d.ts.map +1 -0
- package/dist/service-payment-sessions.js +280 -0
- package/dist/service-profitability.d.ts +114 -0
- package/dist/service-profitability.d.ts.map +1 -0
- package/dist/service-profitability.js +794 -0
- package/dist/service-public.d.ts +553 -0
- package/dist/service-public.d.ts.map +1 -0
- package/dist/service-public.js +583 -0
- package/dist/service-reference-data.d.ts +272 -0
- package/dist/service-reference-data.d.ts.map +1 -0
- package/dist/service-reference-data.js +280 -0
- package/dist/service-rendition-wait.d.ts +38 -0
- package/dist/service-rendition-wait.d.ts.map +1 -0
- package/dist/service-rendition-wait.js +67 -0
- package/dist/service-reports.d.ts +37 -0
- package/dist/service-reports.d.ts.map +1 -0
- package/dist/service-reports.js +62 -0
- package/dist/service-settlement.d.ts +46 -0
- package/dist/service-settlement.d.ts.map +1 -0
- package/dist/service-settlement.js +185 -0
- package/dist/service-shared.d.ts +541 -0
- package/dist/service-shared.d.ts.map +1 -0
- package/dist/service-shared.js +764 -0
- package/dist/service-supplier-invoices.d.ts +871 -0
- package/dist/service-supplier-invoices.d.ts.map +1 -0
- package/dist/service-supplier-invoices.js +744 -0
- package/dist/service-supplier-payments.d.ts +69 -0
- package/dist/service-supplier-payments.d.ts.map +1 -0
- package/dist/service-supplier-payments.js +136 -0
- package/dist/service-vouchers-migration.d.ts +44 -0
- package/dist/service-vouchers-migration.d.ts.map +1 -0
- package/dist/service-vouchers-migration.js +148 -0
- package/dist/service-vouchers.d.ts +157 -0
- package/dist/service-vouchers.d.ts.map +1 -0
- package/dist/service-vouchers.js +191 -0
- package/dist/service.d.ts +6490 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +29 -0
- package/dist/validation-billing.d.ts +2 -0
- package/dist/validation-billing.d.ts.map +1 -0
- package/dist/validation-billing.js +1 -0
- package/dist/validation-payments.d.ts +2 -0
- package/dist/validation-payments.d.ts.map +1 -0
- package/dist/validation-payments.js +1 -0
- package/dist/validation-public.d.ts +2 -0
- package/dist/validation-public.d.ts.map +1 -0
- package/dist/validation-public.js +1 -0
- package/dist/validation-shared.d.ts +2 -0
- package/dist/validation-shared.d.ts.map +1 -0
- package/dist/validation-shared.js +1 -0
- package/dist/validation-vouchers.d.ts +2 -0
- package/dist/validation-vouchers.d.ts.map +1 -0
- package/dist/validation-vouchers.js +1 -0
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +1 -0
- 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 @@
|
|
|
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
|
+
}
|