@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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { CreateSupplierPaymentInput, FinanceServiceRuntime, PostgresJsDatabase, SupplierPaymentListQuery, UpdateSupplierPaymentInput } from "./service-shared.js";
|
|
2
|
+
export declare const financeSupplierPaymentService: {
|
|
3
|
+
listSupplierPayments(db: PostgresJsDatabase, query: SupplierPaymentListQuery): Promise<{
|
|
4
|
+
data: {
|
|
5
|
+
id: string;
|
|
6
|
+
bookingId: string | null;
|
|
7
|
+
supplierId: string | null;
|
|
8
|
+
bookingSupplierStatusId: string | null;
|
|
9
|
+
supplierInvoiceId: string | null;
|
|
10
|
+
amountCents: number;
|
|
11
|
+
currency: string;
|
|
12
|
+
baseCurrency: string | null;
|
|
13
|
+
baseAmountCents: number | null;
|
|
14
|
+
fxRateSetId: string | null;
|
|
15
|
+
paymentMethod: "other" | "bank_transfer" | "credit_card" | "voucher" | "debit_card" | "cash" | "cheque" | "wallet" | "direct_bill";
|
|
16
|
+
paymentInstrumentId: string | null;
|
|
17
|
+
status: "failed" | "pending" | "completed" | "refunded";
|
|
18
|
+
referenceNumber: string | null;
|
|
19
|
+
paymentDate: string;
|
|
20
|
+
notes: string | null;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
updatedAt: Date;
|
|
23
|
+
}[];
|
|
24
|
+
total: number;
|
|
25
|
+
limit: number;
|
|
26
|
+
offset: number;
|
|
27
|
+
}>;
|
|
28
|
+
createSupplierPayment(db: PostgresJsDatabase, data: CreateSupplierPaymentInput, runtime?: FinanceServiceRuntime): Promise<{
|
|
29
|
+
currency: string;
|
|
30
|
+
id: string;
|
|
31
|
+
createdAt: Date;
|
|
32
|
+
updatedAt: Date;
|
|
33
|
+
status: "failed" | "pending" | "completed" | "refunded";
|
|
34
|
+
bookingId: string | null;
|
|
35
|
+
amountCents: number;
|
|
36
|
+
notes: string | null;
|
|
37
|
+
paymentMethod: "other" | "bank_transfer" | "credit_card" | "voucher" | "debit_card" | "cash" | "cheque" | "wallet" | "direct_bill";
|
|
38
|
+
baseCurrency: string | null;
|
|
39
|
+
fxRateSetId: string | null;
|
|
40
|
+
supplierId: string | null;
|
|
41
|
+
paymentInstrumentId: string | null;
|
|
42
|
+
referenceNumber: string | null;
|
|
43
|
+
baseAmountCents: number | null;
|
|
44
|
+
paymentDate: string;
|
|
45
|
+
supplierInvoiceId: string | null;
|
|
46
|
+
bookingSupplierStatusId: string | null;
|
|
47
|
+
} | null>;
|
|
48
|
+
updateSupplierPayment(db: PostgresJsDatabase, id: string, data: UpdateSupplierPaymentInput, runtime?: FinanceServiceRuntime): Promise<{
|
|
49
|
+
id: string;
|
|
50
|
+
bookingId: string | null;
|
|
51
|
+
supplierId: string | null;
|
|
52
|
+
bookingSupplierStatusId: string | null;
|
|
53
|
+
supplierInvoiceId: string | null;
|
|
54
|
+
amountCents: number;
|
|
55
|
+
currency: string;
|
|
56
|
+
baseCurrency: string | null;
|
|
57
|
+
baseAmountCents: number | null;
|
|
58
|
+
fxRateSetId: string | null;
|
|
59
|
+
paymentMethod: "other" | "bank_transfer" | "credit_card" | "voucher" | "debit_card" | "cash" | "cheque" | "wallet" | "direct_bill";
|
|
60
|
+
paymentInstrumentId: string | null;
|
|
61
|
+
status: "failed" | "pending" | "completed" | "refunded";
|
|
62
|
+
referenceNumber: string | null;
|
|
63
|
+
paymentDate: string;
|
|
64
|
+
notes: string | null;
|
|
65
|
+
createdAt: Date;
|
|
66
|
+
updatedAt: Date;
|
|
67
|
+
} | null>;
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=service-supplier-payments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-supplier-payments.d.ts","sourceRoot":"","sources":["../src/service-supplier-payments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,qBAAqB,CAAA;AAoB5B,eAAO,MAAM,6BAA6B;6BACT,kBAAkB,SAAS,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;8BAuE5E,kBAAkB,QAChB,0BAA0B,YACvB,qBAAqB;;;;;;;;;;;;;;;;;;;;8BA2D1B,kBAAkB,MAClB,MAAM,QACJ,0BAA0B,YACvB,qBAAqB;;;;;;;;;;;;;;;;;;;;CA6CjC,CAAA"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { and, appendActionLedgerMutation, asc, bookings, buildSupplierPaymentCreateActionLedgerInput, buildSupplierPaymentUpdateActionLedgerInput, desc, eq, gte, lte, recomputeSupplierInvoiceBalance, resolveFxMoneyBaseAmount, resolveSupplierPaymentUpdateData, sql, supplierInvoices, supplierPayments, } from "./service-shared.js";
|
|
2
|
+
export const financeSupplierPaymentService = {
|
|
3
|
+
async listSupplierPayments(db, query) {
|
|
4
|
+
const conditions = [];
|
|
5
|
+
if (query.bookingId) {
|
|
6
|
+
conditions.push(eq(supplierPayments.bookingId, query.bookingId));
|
|
7
|
+
}
|
|
8
|
+
if (query.supplierInvoiceId) {
|
|
9
|
+
conditions.push(eq(supplierPayments.supplierInvoiceId, query.supplierInvoiceId));
|
|
10
|
+
}
|
|
11
|
+
if (query.supplierId) {
|
|
12
|
+
conditions.push(eq(supplierPayments.supplierId, query.supplierId));
|
|
13
|
+
}
|
|
14
|
+
if (query.status) {
|
|
15
|
+
conditions.push(eq(supplierPayments.status, query.status));
|
|
16
|
+
}
|
|
17
|
+
if (query.paymentMethod) {
|
|
18
|
+
conditions.push(eq(supplierPayments.paymentMethod, query.paymentMethod));
|
|
19
|
+
}
|
|
20
|
+
if (query.currency) {
|
|
21
|
+
conditions.push(eq(supplierPayments.currency, query.currency));
|
|
22
|
+
}
|
|
23
|
+
if (query.paymentDateFrom) {
|
|
24
|
+
conditions.push(gte(supplierPayments.paymentDate, query.paymentDateFrom));
|
|
25
|
+
}
|
|
26
|
+
if (query.paymentDateTo) {
|
|
27
|
+
conditions.push(lte(supplierPayments.paymentDate, query.paymentDateTo));
|
|
28
|
+
}
|
|
29
|
+
const where = conditions.length > 0 ? and(...conditions) : undefined;
|
|
30
|
+
const sortColumn = (() => {
|
|
31
|
+
switch (query.sortBy) {
|
|
32
|
+
case "amountCents":
|
|
33
|
+
return supplierPayments.amountCents;
|
|
34
|
+
case "status":
|
|
35
|
+
return supplierPayments.status;
|
|
36
|
+
case "paymentDate":
|
|
37
|
+
return supplierPayments.paymentDate;
|
|
38
|
+
default:
|
|
39
|
+
return supplierPayments.createdAt;
|
|
40
|
+
}
|
|
41
|
+
})();
|
|
42
|
+
const sortFn = query.sortDir === "asc" ? asc : desc;
|
|
43
|
+
const [rows, countResult] = await Promise.all([
|
|
44
|
+
db
|
|
45
|
+
.select()
|
|
46
|
+
.from(supplierPayments)
|
|
47
|
+
.where(where)
|
|
48
|
+
.limit(query.limit)
|
|
49
|
+
.offset(query.offset)
|
|
50
|
+
.orderBy(sortFn(sortColumn), desc(supplierPayments.createdAt)),
|
|
51
|
+
db.select({ count: sql `count(*)::int` }).from(supplierPayments).where(where),
|
|
52
|
+
]);
|
|
53
|
+
return {
|
|
54
|
+
data: rows,
|
|
55
|
+
total: countResult[0]?.count ?? 0,
|
|
56
|
+
limit: query.limit,
|
|
57
|
+
offset: query.offset,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
async createSupplierPayment(db, data, runtime = {}) {
|
|
61
|
+
// Derive the reporting base currency from the booking when present, else
|
|
62
|
+
// from the supplier invoice the payment settles (AP payments may have no
|
|
63
|
+
// booking). See §5.4.
|
|
64
|
+
let targetBaseCurrency = null;
|
|
65
|
+
let fallbackFxRateSetId = null;
|
|
66
|
+
if (data.bookingId) {
|
|
67
|
+
const [booking] = await db
|
|
68
|
+
.select()
|
|
69
|
+
.from(bookings)
|
|
70
|
+
.where(eq(bookings.id, data.bookingId))
|
|
71
|
+
.limit(1);
|
|
72
|
+
targetBaseCurrency = booking?.baseCurrency ?? null;
|
|
73
|
+
fallbackFxRateSetId = booking?.fxRateSetId ?? null;
|
|
74
|
+
}
|
|
75
|
+
else if (data.supplierInvoiceId) {
|
|
76
|
+
const [invoice] = await db
|
|
77
|
+
.select()
|
|
78
|
+
.from(supplierInvoices)
|
|
79
|
+
.where(eq(supplierInvoices.id, data.supplierInvoiceId))
|
|
80
|
+
.limit(1);
|
|
81
|
+
targetBaseCurrency = invoice?.baseCurrency ?? null;
|
|
82
|
+
fallbackFxRateSetId = invoice?.fxRateSetId ?? null;
|
|
83
|
+
}
|
|
84
|
+
const paymentData = await resolveFxMoneyBaseAmount(db, data, {
|
|
85
|
+
...runtime,
|
|
86
|
+
targetBaseCurrency,
|
|
87
|
+
fallbackFxRateSetId,
|
|
88
|
+
date: data.paymentDate,
|
|
89
|
+
});
|
|
90
|
+
const row = await db.transaction(async (tx) => {
|
|
91
|
+
const [created] = await tx
|
|
92
|
+
.insert(supplierPayments)
|
|
93
|
+
.values({ ...paymentData, paymentInstrumentId: paymentData.paymentInstrumentId ?? null })
|
|
94
|
+
.returning();
|
|
95
|
+
if (created && runtime.actionLedgerContext) {
|
|
96
|
+
await appendActionLedgerMutation(tx, await buildSupplierPaymentCreateActionLedgerInput(runtime.actionLedgerContext, { payment: created }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
|
|
97
|
+
}
|
|
98
|
+
// Keep the settled invoice's paid/balance/status in sync (§10).
|
|
99
|
+
if (created?.supplierInvoiceId) {
|
|
100
|
+
await recomputeSupplierInvoiceBalance(tx, created.supplierInvoiceId);
|
|
101
|
+
}
|
|
102
|
+
return created ?? null;
|
|
103
|
+
});
|
|
104
|
+
return row;
|
|
105
|
+
},
|
|
106
|
+
async updateSupplierPayment(db, id, data, runtime = {}) {
|
|
107
|
+
const [existing] = await db
|
|
108
|
+
.select()
|
|
109
|
+
.from(supplierPayments)
|
|
110
|
+
.where(eq(supplierPayments.id, id))
|
|
111
|
+
.limit(1);
|
|
112
|
+
if (!existing)
|
|
113
|
+
return null;
|
|
114
|
+
const updateData = await resolveSupplierPaymentUpdateData(db, id, data, runtime);
|
|
115
|
+
if (!updateData)
|
|
116
|
+
return null;
|
|
117
|
+
const row = await db.transaction(async (tx) => {
|
|
118
|
+
const [updated] = await tx
|
|
119
|
+
.update(supplierPayments)
|
|
120
|
+
.set({ ...updateData, updatedAt: new Date() })
|
|
121
|
+
.where(eq(supplierPayments.id, id))
|
|
122
|
+
.returning();
|
|
123
|
+
if (updated && runtime.actionLedgerContext) {
|
|
124
|
+
await appendActionLedgerMutation(tx, buildSupplierPaymentUpdateActionLedgerInput(runtime.actionLedgerContext, { payment: updated, changes: updateData }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
|
|
125
|
+
}
|
|
126
|
+
// Recompute both the previously-linked and newly-linked invoices so a
|
|
127
|
+
// re-pointed or status-changed payment leaves balances consistent (§10).
|
|
128
|
+
const affected = new Set([existing.supplierInvoiceId, updated?.supplierInvoiceId].filter((value) => Boolean(value)));
|
|
129
|
+
for (const invoiceId of affected) {
|
|
130
|
+
await recomputeSupplierInvoiceBalance(tx, invoiceId);
|
|
131
|
+
}
|
|
132
|
+
return updated ?? null;
|
|
133
|
+
});
|
|
134
|
+
return row ?? null;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
+
export interface VoucherMigrationOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When true, report what would happen without writing. Defaults to false.
|
|
5
|
+
*/
|
|
6
|
+
dryRun?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Per-row hook for progress reporting. Not called on skipped rows.
|
|
9
|
+
*/
|
|
10
|
+
onRowMigrated?: (info: {
|
|
11
|
+
paymentInstrumentId: string;
|
|
12
|
+
voucherCode: string;
|
|
13
|
+
}) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface VoucherMigrationSkip {
|
|
16
|
+
paymentInstrumentId: string;
|
|
17
|
+
reason: "already_migrated" | "missing_code" | "missing_currency" | "missing_amount" | "duplicate_code_collision";
|
|
18
|
+
}
|
|
19
|
+
export interface VoucherMigrationResult {
|
|
20
|
+
candidates: number;
|
|
21
|
+
migrated: number;
|
|
22
|
+
skipped: VoucherMigrationSkip[];
|
|
23
|
+
dryRun: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Backfill the `vouchers` table from legacy voucher rows in
|
|
27
|
+
* `payment_instruments`. A legacy voucher is a row with `instrumentType =
|
|
28
|
+
* 'voucher'` whose code lives in one of `metadata.code`, `external_token`, or
|
|
29
|
+
* `direct_bill_reference`, and whose balance lives in
|
|
30
|
+
* `metadata.remainingAmountCents` (falling back to `metadata.amountCents` when
|
|
31
|
+
* no redemption has touched the row).
|
|
32
|
+
*
|
|
33
|
+
* The migration is idempotent: rows whose code already exists in the new
|
|
34
|
+
* `vouchers` table are skipped so re-running the script after a partial run
|
|
35
|
+
* (or after issuing new vouchers via the first-class API) is safe.
|
|
36
|
+
*
|
|
37
|
+
* Why skip rather than update: the new table treats `code` as a primary lookup
|
|
38
|
+
* key and the legacy path has already been read-only-fallback since #256
|
|
39
|
+
* landed, so any voucher that exists in both tables is by definition already
|
|
40
|
+
* migrated. Picking one source of truth avoids clobbering balances the
|
|
41
|
+
* operator may have adjusted through the new redemption flow.
|
|
42
|
+
*/
|
|
43
|
+
export declare function migrateVouchersFromPaymentInstruments(db: PostgresJsDatabase, options?: VoucherMigrationOptions): Promise<VoucherMigrationResult>;
|
|
44
|
+
//# sourceMappingURL=service-vouchers-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-vouchers-migration.d.ts","sourceRoot":"","sources":["../src/service-vouchers-migration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAsCjE,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,mBAAmB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACrF;AAED,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,EACF,kBAAkB,GAClB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,GAChB,0BAA0B,CAAA;CAC/B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,oBAAoB,EAAE,CAAA;IAC/B,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qCAAqC,CACzD,EAAE,EAAE,kBAAkB,EACtB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CA6GjC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { eq, sql } from "drizzle-orm";
|
|
2
|
+
import { paymentInstruments, vouchers } from "./schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Pulls a (possibly nested, array-wrapped, or null) value out of a JSONB
|
|
5
|
+
* metadata column. Keeps the narrow runtime checks local so callers can stay
|
|
6
|
+
* declarative about the shape they expect.
|
|
7
|
+
*/
|
|
8
|
+
function asRecord(metadata) {
|
|
9
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return metadata;
|
|
13
|
+
}
|
|
14
|
+
function asString(record, key) {
|
|
15
|
+
const value = record?.[key];
|
|
16
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
17
|
+
}
|
|
18
|
+
function asNumber(record, key) {
|
|
19
|
+
const value = record?.[key];
|
|
20
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
21
|
+
}
|
|
22
|
+
function asStringArray(record, key) {
|
|
23
|
+
const value = record?.[key];
|
|
24
|
+
if (!Array.isArray(value))
|
|
25
|
+
return [];
|
|
26
|
+
return value.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
27
|
+
}
|
|
28
|
+
function asDate(value) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return null;
|
|
31
|
+
const parsed = new Date(value);
|
|
32
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Backfill the `vouchers` table from legacy voucher rows in
|
|
36
|
+
* `payment_instruments`. A legacy voucher is a row with `instrumentType =
|
|
37
|
+
* 'voucher'` whose code lives in one of `metadata.code`, `external_token`, or
|
|
38
|
+
* `direct_bill_reference`, and whose balance lives in
|
|
39
|
+
* `metadata.remainingAmountCents` (falling back to `metadata.amountCents` when
|
|
40
|
+
* no redemption has touched the row).
|
|
41
|
+
*
|
|
42
|
+
* The migration is idempotent: rows whose code already exists in the new
|
|
43
|
+
* `vouchers` table are skipped so re-running the script after a partial run
|
|
44
|
+
* (or after issuing new vouchers via the first-class API) is safe.
|
|
45
|
+
*
|
|
46
|
+
* Why skip rather than update: the new table treats `code` as a primary lookup
|
|
47
|
+
* key and the legacy path has already been read-only-fallback since #256
|
|
48
|
+
* landed, so any voucher that exists in both tables is by definition already
|
|
49
|
+
* migrated. Picking one source of truth avoids clobbering balances the
|
|
50
|
+
* operator may have adjusted through the new redemption flow.
|
|
51
|
+
*/
|
|
52
|
+
export async function migrateVouchersFromPaymentInstruments(db, options = {}) {
|
|
53
|
+
const dryRun = options.dryRun ?? false;
|
|
54
|
+
const skipped = [];
|
|
55
|
+
let migrated = 0;
|
|
56
|
+
const candidates = await db
|
|
57
|
+
.select()
|
|
58
|
+
.from(paymentInstruments)
|
|
59
|
+
.where(eq(paymentInstruments.instrumentType, "voucher"));
|
|
60
|
+
for (const instrument of candidates) {
|
|
61
|
+
const metadata = asRecord(instrument.metadata);
|
|
62
|
+
const code = asString(metadata, "code") ?? instrument.externalToken ?? instrument.directBillReference;
|
|
63
|
+
if (!code) {
|
|
64
|
+
skipped.push({ paymentInstrumentId: instrument.id, reason: "missing_code" });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const currency = asString(metadata, "currency");
|
|
68
|
+
if (!currency || currency.length !== 3) {
|
|
69
|
+
skipped.push({ paymentInstrumentId: instrument.id, reason: "missing_currency" });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const initialAmountCents = asNumber(metadata, "amountCents");
|
|
73
|
+
if (initialAmountCents === null || initialAmountCents <= 0) {
|
|
74
|
+
skipped.push({ paymentInstrumentId: instrument.id, reason: "missing_amount" });
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const remainingAmountCents = asNumber(metadata, "remainingAmountCents") ?? initialAmountCents;
|
|
78
|
+
const [existing] = await db
|
|
79
|
+
.select({ id: vouchers.id })
|
|
80
|
+
.from(vouchers)
|
|
81
|
+
// agent-quality: raw-sql reviewed -- owner: finance; dynamic SQL interpolation uses Drizzle parameter binding or vetted SQL identifiers.
|
|
82
|
+
.where(sql `lower(${vouchers.code}) = ${code.toLowerCase()}`)
|
|
83
|
+
.limit(1);
|
|
84
|
+
if (existing) {
|
|
85
|
+
skipped.push({ paymentInstrumentId: instrument.id, reason: "already_migrated" });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const expiresAt = asDate(asString(metadata, "expiresAt"));
|
|
89
|
+
// OpenTravel uses `effectiveDate`; some legacy payloads also wrote
|
|
90
|
+
// `validFrom` directly. Check both so existing rows aren't silently
|
|
91
|
+
// dropped.
|
|
92
|
+
const validFrom = asDate(asString(metadata, "validFrom")) ?? asDate(asString(metadata, "effectiveDate"));
|
|
93
|
+
const seriesCode = asString(metadata, "seriesCode");
|
|
94
|
+
const bookingIds = asStringArray(metadata, "bookingIds");
|
|
95
|
+
const sourceBookingId = asString(metadata, "bookingId") ?? bookingIds[0] ?? null;
|
|
96
|
+
// Collapse the legacy status/balance pair onto the new enum. If there's no
|
|
97
|
+
// balance left, treat as already spent; otherwise follow the instrument's
|
|
98
|
+
// own active/inactive flag.
|
|
99
|
+
const status = remainingAmountCents <= 0 ? "redeemed" : instrument.status === "active" ? "active" : "void";
|
|
100
|
+
if (dryRun) {
|
|
101
|
+
migrated++;
|
|
102
|
+
options.onRowMigrated?.({ paymentInstrumentId: instrument.id, voucherCode: code });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
await db.insert(vouchers).values({
|
|
107
|
+
code,
|
|
108
|
+
seriesCode,
|
|
109
|
+
status,
|
|
110
|
+
currency: currency.toUpperCase(),
|
|
111
|
+
initialAmountCents,
|
|
112
|
+
remainingAmountCents: Math.max(0, remainingAmountCents),
|
|
113
|
+
issuedToPersonId: instrument.personId ?? null,
|
|
114
|
+
issuedToOrganizationId: instrument.organizationId ?? null,
|
|
115
|
+
// We don't know the original source (refund vs gift vs promo) from the
|
|
116
|
+
// legacy shape, so mark everything as `manual` — operators can reclassify
|
|
117
|
+
// later via PATCH /vouchers/:id.
|
|
118
|
+
sourceType: "manual",
|
|
119
|
+
sourceBookingId,
|
|
120
|
+
notes: instrument.notes ?? null,
|
|
121
|
+
validFrom,
|
|
122
|
+
expiresAt,
|
|
123
|
+
createdAt: instrument.createdAt,
|
|
124
|
+
updatedAt: instrument.updatedAt,
|
|
125
|
+
});
|
|
126
|
+
migrated++;
|
|
127
|
+
options.onRowMigrated?.({ paymentInstrumentId: instrument.id, voucherCode: code });
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
// Unique-index collision is the only realistic insert failure here
|
|
131
|
+
// (another concurrent migration or a race with a manual issuance). Record
|
|
132
|
+
// it as a skip rather than aborting the batch so a retry finishes the
|
|
133
|
+
// rest.
|
|
134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
+
if (message.includes("uidx_vouchers_code") || message.includes("duplicate key")) {
|
|
136
|
+
skipped.push({ paymentInstrumentId: instrument.id, reason: "duplicate_code_collision" });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
candidates: candidates.length,
|
|
144
|
+
migrated,
|
|
145
|
+
skipped,
|
|
146
|
+
dryRun,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
import type { insertVoucherSchema, redeemVoucherSchema, updateVoucherSchema, voucherListQuerySchema } from "./validation-vouchers.js";
|
|
4
|
+
type CreateVoucherInput = z.infer<typeof insertVoucherSchema>;
|
|
5
|
+
type UpdateVoucherInput = z.infer<typeof updateVoucherSchema>;
|
|
6
|
+
type RedeemVoucherInput = z.infer<typeof redeemVoucherSchema>;
|
|
7
|
+
type VoucherListQuery = z.infer<typeof voucherListQuerySchema>;
|
|
8
|
+
/**
|
|
9
|
+
* Raised by the voucher service. Code + message; route handlers map to HTTP.
|
|
10
|
+
* Reasons the route layer cares about:
|
|
11
|
+
* - `code_in_use` — supplied code collides with an existing voucher
|
|
12
|
+
* - `voucher_not_found` — id-not-found / code-not-found read path
|
|
13
|
+
* - `voucher_inactive` — redeem attempted against non-active status
|
|
14
|
+
* - `voucher_not_started`— validFrom is set and hasn't happened yet
|
|
15
|
+
* - `voucher_expired` — expiresAt has passed
|
|
16
|
+
* - `insufficient_balance` — requested amount > remainingAmountCents
|
|
17
|
+
*/
|
|
18
|
+
export declare class VoucherServiceError extends Error {
|
|
19
|
+
readonly code: "code_in_use" | "voucher_not_found" | "voucher_inactive" | "voucher_not_started" | "voucher_expired" | "insufficient_balance";
|
|
20
|
+
constructor(code: "code_in_use" | "voucher_not_found" | "voucher_inactive" | "voucher_not_started" | "voucher_expired" | "insufficient_balance", message?: string);
|
|
21
|
+
}
|
|
22
|
+
export declare const vouchersService: {
|
|
23
|
+
list(db: PostgresJsDatabase, query: VoucherListQuery): Promise<{
|
|
24
|
+
data: {
|
|
25
|
+
id: string;
|
|
26
|
+
code: string;
|
|
27
|
+
seriesCode: string | null;
|
|
28
|
+
status: "expired" | "active" | "void" | "redeemed";
|
|
29
|
+
currency: string;
|
|
30
|
+
initialAmountCents: number;
|
|
31
|
+
remainingAmountCents: number;
|
|
32
|
+
issuedToPersonId: string | null;
|
|
33
|
+
issuedToOrganizationId: string | null;
|
|
34
|
+
sourceType: "manual" | "refund" | "cancellation_credit" | "gift" | "promo";
|
|
35
|
+
sourceBookingId: string | null;
|
|
36
|
+
sourcePaymentId: string | null;
|
|
37
|
+
validFrom: Date | null;
|
|
38
|
+
expiresAt: Date | null;
|
|
39
|
+
notes: string | null;
|
|
40
|
+
issuedByUserId: string | null;
|
|
41
|
+
createdAt: Date;
|
|
42
|
+
updatedAt: Date;
|
|
43
|
+
}[];
|
|
44
|
+
total: number;
|
|
45
|
+
limit: number;
|
|
46
|
+
offset: number;
|
|
47
|
+
}>;
|
|
48
|
+
getById(db: PostgresJsDatabase, id: string): Promise<{
|
|
49
|
+
redemptions: {
|
|
50
|
+
id: string;
|
|
51
|
+
voucherId: string;
|
|
52
|
+
bookingId: string;
|
|
53
|
+
paymentId: string | null;
|
|
54
|
+
amountCents: number;
|
|
55
|
+
createdAt: Date;
|
|
56
|
+
createdByUserId: string | null;
|
|
57
|
+
}[];
|
|
58
|
+
id: string;
|
|
59
|
+
code: string;
|
|
60
|
+
seriesCode: string | null;
|
|
61
|
+
status: "expired" | "active" | "void" | "redeemed";
|
|
62
|
+
currency: string;
|
|
63
|
+
initialAmountCents: number;
|
|
64
|
+
remainingAmountCents: number;
|
|
65
|
+
issuedToPersonId: string | null;
|
|
66
|
+
issuedToOrganizationId: string | null;
|
|
67
|
+
sourceType: "manual" | "refund" | "cancellation_credit" | "gift" | "promo";
|
|
68
|
+
sourceBookingId: string | null;
|
|
69
|
+
sourcePaymentId: string | null;
|
|
70
|
+
validFrom: Date | null;
|
|
71
|
+
expiresAt: Date | null;
|
|
72
|
+
notes: string | null;
|
|
73
|
+
issuedByUserId: string | null;
|
|
74
|
+
createdAt: Date;
|
|
75
|
+
updatedAt: Date;
|
|
76
|
+
} | null>;
|
|
77
|
+
create(db: PostgresJsDatabase, input: CreateVoucherInput, issuedByUserId?: string): Promise<{
|
|
78
|
+
id: string;
|
|
79
|
+
status: "expired" | "active" | "void" | "redeemed";
|
|
80
|
+
createdAt: Date;
|
|
81
|
+
expiresAt: Date | null;
|
|
82
|
+
notes: string | null;
|
|
83
|
+
updatedAt: Date;
|
|
84
|
+
currency: string;
|
|
85
|
+
code: string;
|
|
86
|
+
seriesCode: string | null;
|
|
87
|
+
initialAmountCents: number;
|
|
88
|
+
remainingAmountCents: number;
|
|
89
|
+
issuedToPersonId: string | null;
|
|
90
|
+
issuedToOrganizationId: string | null;
|
|
91
|
+
sourceType: "manual" | "refund" | "cancellation_credit" | "gift" | "promo";
|
|
92
|
+
sourceBookingId: string | null;
|
|
93
|
+
sourcePaymentId: string | null;
|
|
94
|
+
validFrom: Date | null;
|
|
95
|
+
issuedByUserId: string | null;
|
|
96
|
+
} | null>;
|
|
97
|
+
update(db: PostgresJsDatabase, id: string, input: UpdateVoucherInput): Promise<{
|
|
98
|
+
id: string;
|
|
99
|
+
code: string;
|
|
100
|
+
seriesCode: string | null;
|
|
101
|
+
status: "expired" | "active" | "void" | "redeemed";
|
|
102
|
+
currency: string;
|
|
103
|
+
initialAmountCents: number;
|
|
104
|
+
remainingAmountCents: number;
|
|
105
|
+
issuedToPersonId: string | null;
|
|
106
|
+
issuedToOrganizationId: string | null;
|
|
107
|
+
sourceType: "manual" | "refund" | "cancellation_credit" | "gift" | "promo";
|
|
108
|
+
sourceBookingId: string | null;
|
|
109
|
+
sourcePaymentId: string | null;
|
|
110
|
+
validFrom: Date | null;
|
|
111
|
+
expiresAt: Date | null;
|
|
112
|
+
notes: string | null;
|
|
113
|
+
issuedByUserId: string | null;
|
|
114
|
+
createdAt: Date;
|
|
115
|
+
updatedAt: Date;
|
|
116
|
+
} | null>;
|
|
117
|
+
/**
|
|
118
|
+
* Apply a voucher against a booking. Runs in a transaction so
|
|
119
|
+
* `remainingAmountCents` and the redemption row either both land or neither.
|
|
120
|
+
* Guards: voucher must exist, be active, not expired, and have enough
|
|
121
|
+
* balance for the requested amount. When remaining hits zero the voucher
|
|
122
|
+
* flips to `status = 'redeemed'`.
|
|
123
|
+
*/
|
|
124
|
+
redeem(db: PostgresJsDatabase, voucherId: string, input: RedeemVoucherInput, userId?: string): Promise<{
|
|
125
|
+
voucher: {
|
|
126
|
+
id: string;
|
|
127
|
+
code: string;
|
|
128
|
+
seriesCode: string | null;
|
|
129
|
+
status: "expired" | "active" | "void" | "redeemed";
|
|
130
|
+
currency: string;
|
|
131
|
+
initialAmountCents: number;
|
|
132
|
+
remainingAmountCents: number;
|
|
133
|
+
issuedToPersonId: string | null;
|
|
134
|
+
issuedToOrganizationId: string | null;
|
|
135
|
+
sourceType: "manual" | "refund" | "cancellation_credit" | "gift" | "promo";
|
|
136
|
+
sourceBookingId: string | null;
|
|
137
|
+
sourcePaymentId: string | null;
|
|
138
|
+
validFrom: Date | null;
|
|
139
|
+
expiresAt: Date | null;
|
|
140
|
+
notes: string | null;
|
|
141
|
+
issuedByUserId: string | null;
|
|
142
|
+
createdAt: Date;
|
|
143
|
+
updatedAt: Date;
|
|
144
|
+
};
|
|
145
|
+
redemption: {
|
|
146
|
+
id: string;
|
|
147
|
+
createdAt: Date;
|
|
148
|
+
bookingId: string;
|
|
149
|
+
amountCents: number;
|
|
150
|
+
paymentId: string | null;
|
|
151
|
+
voucherId: string;
|
|
152
|
+
createdByUserId: string | null;
|
|
153
|
+
} | null;
|
|
154
|
+
}>;
|
|
155
|
+
};
|
|
156
|
+
export {};
|
|
157
|
+
//# sourceMappingURL=service-vouchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-vouchers.d.ts","sourceRoot":"","sources":["../src/service-vouchers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,0BAA0B,CAAA;AAEjC,KAAK,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC7D,KAAK,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC7D,KAAK,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC7D,KAAK,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE9D;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAE1C,QAAQ,CAAC,IAAI,EACT,aAAa,GACb,mBAAmB,GACnB,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,sBAAsB;gBANjB,IAAI,EACT,aAAa,GACb,mBAAmB,GACnB,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,sBAAsB,EAC1B,OAAO,CAAC,EAAE,MAAM;CAKnB;AAsBD,eAAO,MAAM,eAAe;aACX,kBAAkB,SAAS,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;gBAuCxC,kBAAkB,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAW/B,kBAAkB,SAAS,kBAAkB,mBAAmB,MAAM;;;;;;;;;;;;;;;;;;;;eAiCtE,kBAAkB,MAAM,MAAM,SAAS,kBAAkB;;;;;;;;;;;;;;;;;;;;IA0B1E;;;;;;OAMG;eAEG,kBAAkB,aACX,MAAM,SACV,kBAAkB,WAChB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ClB,CAAA"}
|