@voyant-travel/finance 0.138.3 → 0.138.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/dist/checkout-routes.d.ts +37 -0
- package/dist/checkout-routes.d.ts.map +1 -1
- package/dist/checkout-routes.js +34 -9
- package/dist/routes-invoice-core.d.ts +95 -11
- package/dist/routes-invoice-core.d.ts.map +1 -1
- package/dist/routes-invoice-core.js +137 -43
- package/dist/routes-invoice-issue.d.ts.map +1 -1
- package/dist/routes-invoice-issue.js +27 -2
- package/dist/routes-payments.d.ts +27 -0
- package/dist/routes-payments.d.ts.map +1 -1
- package/dist/routes-payments.js +22 -7
- package/dist/routes.d.ts +122 -11
- package/dist/routes.d.ts.map +1 -1
- package/dist/service-invoice-core.d.ts.map +1 -1
- package/dist/service-invoice-core.js +55 -4
- package/dist/service-invoice-credit-notes.d.ts.map +1 -1
- package/dist/service-invoice-credit-notes.js +49 -1
- package/dist/service-invoice-line-items.d.ts.map +1 -1
- package/dist/service-invoice-line-items.js +28 -1
- package/dist/service-invoice-payments.d.ts.map +1 -1
- package/dist/service-invoice-payments.js +27 -1
- package/dist/service-shared.d.ts +9 -0
- package/dist/service-shared.d.ts.map +1 -1
- package/dist/service-shared.js +12 -0
- package/package.json +1 -1
|
@@ -37,6 +37,7 @@ export type CheckoutRouteRuntime = {
|
|
|
37
37
|
listBookingReminderRuns?: CheckoutRoutesOptions["listBookingReminderRuns"];
|
|
38
38
|
};
|
|
39
39
|
export declare const CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY = "providers.finance.checkout.runtime";
|
|
40
|
+
export declare const CHECKOUT_ROUTE_RUNTIME_NOT_CONFIGURED_MESSAGE = "Checkout payment links require a configured checkout provider. Configure a Finance checkout runtime with a card payment starter before generating payment links.";
|
|
40
41
|
export declare function createCheckoutRoutes(options?: CheckoutRoutesOptions): import("hono/hono-base").HonoBase<Env, {
|
|
41
42
|
"/bookings/:bookingId/collection-plan": {
|
|
42
43
|
$post: {
|
|
@@ -353,6 +354,17 @@ export declare function createCheckoutRoutes(options?: CheckoutRoutesOptions): i
|
|
|
353
354
|
};
|
|
354
355
|
outputFormat: "json";
|
|
355
356
|
status: 201;
|
|
357
|
+
} | {
|
|
358
|
+
input: {
|
|
359
|
+
param: {
|
|
360
|
+
bookingId: string;
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
output: {
|
|
364
|
+
error: string;
|
|
365
|
+
};
|
|
366
|
+
outputFormat: "json";
|
|
367
|
+
status: 501;
|
|
356
368
|
} | {
|
|
357
369
|
input: {
|
|
358
370
|
param: {
|
|
@@ -581,6 +593,13 @@ export declare function createCheckoutRoutes(options?: CheckoutRoutesOptions): i
|
|
|
581
593
|
};
|
|
582
594
|
outputFormat: "json";
|
|
583
595
|
status: 201;
|
|
596
|
+
} | {
|
|
597
|
+
input: {};
|
|
598
|
+
output: {
|
|
599
|
+
error: string;
|
|
600
|
+
};
|
|
601
|
+
outputFormat: "json";
|
|
602
|
+
status: 501;
|
|
584
603
|
} | {
|
|
585
604
|
input: {};
|
|
586
605
|
output: {
|
|
@@ -907,6 +926,17 @@ export declare function createCheckoutAdminRoutes(options?: CheckoutRoutesOption
|
|
|
907
926
|
};
|
|
908
927
|
outputFormat: "json";
|
|
909
928
|
status: 201;
|
|
929
|
+
} | {
|
|
930
|
+
input: {
|
|
931
|
+
param: {
|
|
932
|
+
bookingId: string;
|
|
933
|
+
};
|
|
934
|
+
};
|
|
935
|
+
output: {
|
|
936
|
+
error: string;
|
|
937
|
+
};
|
|
938
|
+
outputFormat: "json";
|
|
939
|
+
status: 501;
|
|
910
940
|
} | {
|
|
911
941
|
input: {
|
|
912
942
|
param: {
|
|
@@ -1135,6 +1165,13 @@ export declare function createCheckoutAdminRoutes(options?: CheckoutRoutesOption
|
|
|
1135
1165
|
};
|
|
1136
1166
|
outputFormat: "json";
|
|
1137
1167
|
status: 201;
|
|
1168
|
+
} | {
|
|
1169
|
+
input: {};
|
|
1170
|
+
output: {
|
|
1171
|
+
error: string;
|
|
1172
|
+
};
|
|
1173
|
+
outputFormat: "json";
|
|
1174
|
+
status: 501;
|
|
1138
1175
|
} | {
|
|
1139
1176
|
input: {};
|
|
1140
1177
|
output: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout-routes.d.ts","sourceRoot":"","sources":["../src/checkout-routes.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAQ1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAG3B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAI/B,MAAM,0BAA0B,CAAA;AAEjC,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,sBAAsB,CAAC,EAAE,8BAA8B,GAAG,IAAI,CAAA;IAC9D,6BAA6B,CAAC,EAAE,CAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,8BAA8B,GAAG,IAAI,CAAA;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IACxD,sBAAsB,CAAC,EAAE,CACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IAC3C,mBAAmB,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAA;IACxD,0BAA0B,CAAC,EAAE,CAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,2BAA2B,GAAG,IAAI,CAAA;IACvC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,4BAA4B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAC/F,uBAAuB,CAAC,EAAE,CACxB,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,4BAA4B,KAChC,OAAO,CAAC,uBAAuB,CAAC,CAAA;CACtC,CAAA;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,yBAAyB,EAAE,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,sBAAsB,EAAE,8BAA8B,GAAG,IAAI,CAAA;IAC7D,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IACvD,mBAAmB,EAAE,2BAA2B,GAAG,IAAI,CAAA;IACvD,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,uBAAuB,CAAC,EAAE,qBAAqB,CAAC,yBAAyB,CAAC,CAAA;CAC3E,CAAA;AAED,eAAO,MAAM,oCAAoC,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"checkout-routes.d.ts","sourceRoot":"","sources":["../src/checkout-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/checkout-routes.js
CHANGED
|
@@ -4,6 +4,12 @@ import { Hono } from "hono";
|
|
|
4
4
|
import { bootstrapCheckoutCollection, initiateCheckoutCollection, previewCheckoutCollection, } from "./checkout-service.js";
|
|
5
5
|
import { bootstrapCheckoutCollectionSchema, checkoutReminderRunListQuerySchema, initiateCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./checkout-validation.js";
|
|
6
6
|
export const CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY = "providers.finance.checkout.runtime";
|
|
7
|
+
export const CHECKOUT_ROUTE_RUNTIME_NOT_CONFIGURED_MESSAGE = "Checkout payment links require a configured checkout provider. Configure a Finance checkout runtime with a card payment starter before generating payment links.";
|
|
8
|
+
class CheckoutRouteRuntimeNotConfiguredError extends Error {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(CHECKOUT_ROUTE_RUNTIME_NOT_CONFIGURED_MESSAGE);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
7
13
|
function runtimeEnv(c) {
|
|
8
14
|
return c.env;
|
|
9
15
|
}
|
|
@@ -26,9 +32,8 @@ function attachCollectionRoutes(app, options) {
|
|
|
26
32
|
// Pin the middleware to this module's Env so Hono doesn't intersect the
|
|
27
33
|
// middleware's default VoyantBindings into the handlers' `c.env` type.
|
|
28
34
|
const collectionIdempotency = () => idempotencyKey();
|
|
29
|
-
function getRuntime(bindings,
|
|
30
|
-
return (
|
|
31
|
-
buildCheckoutRouteRuntime(bindings, options));
|
|
35
|
+
function getRuntime(bindings, container) {
|
|
36
|
+
return resolveCheckoutRouteRuntime(bindings, options, container);
|
|
32
37
|
}
|
|
33
38
|
return (app
|
|
34
39
|
// Mostly a read, but `ensureDefaultPaymentPlan` can materialize a
|
|
@@ -49,8 +54,10 @@ function attachCollectionRoutes(app, options) {
|
|
|
49
54
|
})
|
|
50
55
|
.post("/bookings/:bookingId/initiate-collection", collectionIdempotency(), async (c) => {
|
|
51
56
|
try {
|
|
52
|
-
const
|
|
53
|
-
const
|
|
57
|
+
const input = await parseJsonBody(c, initiateCheckoutCollectionSchema);
|
|
58
|
+
const runtime = getRuntime(c.env, c.var.container);
|
|
59
|
+
assertCheckoutRuntimeSupportsCollection(runtime, input);
|
|
60
|
+
const result = await initiateCheckoutCollection(c.get("db"), c.req.param("bookingId"), input, options.policy, runtime);
|
|
54
61
|
if (!result) {
|
|
55
62
|
return c.json({ error: "Booking not found" }, 404);
|
|
56
63
|
}
|
|
@@ -61,13 +68,18 @@ function attachCollectionRoutes(app, options) {
|
|
|
61
68
|
if (message.includes("Booking not found")) {
|
|
62
69
|
return c.json({ error: message }, 404);
|
|
63
70
|
}
|
|
71
|
+
if (error instanceof CheckoutRouteRuntimeNotConfiguredError) {
|
|
72
|
+
return c.json({ error: message }, 501);
|
|
73
|
+
}
|
|
64
74
|
return c.json({ error: message }, 409);
|
|
65
75
|
}
|
|
66
76
|
})
|
|
67
77
|
.post("/collections/bootstrap", collectionIdempotency(), async (c) => {
|
|
68
78
|
try {
|
|
69
|
-
const
|
|
70
|
-
const
|
|
79
|
+
const input = await parseJsonBody(c, bootstrapCheckoutCollectionSchema);
|
|
80
|
+
const runtime = getRuntime(c.env, c.var.container);
|
|
81
|
+
assertCheckoutRuntimeSupportsCollection(runtime, input);
|
|
82
|
+
const result = await bootstrapCheckoutCollection(c.get("db"), input, options.policy, runtime);
|
|
71
83
|
if (!result) {
|
|
72
84
|
return c.json({ error: "Booking session not found" }, 404);
|
|
73
85
|
}
|
|
@@ -78,6 +90,9 @@ function attachCollectionRoutes(app, options) {
|
|
|
78
90
|
if (message.includes("Booking not found")) {
|
|
79
91
|
return c.json({ error: message }, 404);
|
|
80
92
|
}
|
|
93
|
+
if (error instanceof CheckoutRouteRuntimeNotConfiguredError) {
|
|
94
|
+
return c.json({ error: message }, 501);
|
|
95
|
+
}
|
|
81
96
|
return c.json({ error: message }, 409);
|
|
82
97
|
}
|
|
83
98
|
}));
|
|
@@ -91,8 +106,7 @@ export function createCheckoutRoutes(options = {}) {
|
|
|
91
106
|
export function createCheckoutAdminRoutes(options = {}) {
|
|
92
107
|
const app = new Hono().get("/bookings/:bookingId/reminder-runs", async (c) => {
|
|
93
108
|
const query = parseQuery(c, checkoutReminderRunListQuerySchema);
|
|
94
|
-
const runtime = c.var.container
|
|
95
|
-
buildCheckoutRouteRuntime(c.env, options);
|
|
109
|
+
const runtime = resolveCheckoutRouteRuntime(c.env, options, c.var.container);
|
|
96
110
|
if (!runtime.listBookingReminderRuns) {
|
|
97
111
|
return c.json({ data: [], total: 0, limit: query.limit, offset: query.offset });
|
|
98
112
|
}
|
|
@@ -100,6 +114,17 @@ export function createCheckoutAdminRoutes(options = {}) {
|
|
|
100
114
|
});
|
|
101
115
|
return attachCollectionRoutes(app, options);
|
|
102
116
|
}
|
|
117
|
+
function resolveCheckoutRouteRuntime(bindings, options, container) {
|
|
118
|
+
if (container?.has(CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY)) {
|
|
119
|
+
return container.resolve(CHECKOUT_ROUTE_RUNTIME_CONTAINER_KEY);
|
|
120
|
+
}
|
|
121
|
+
return buildCheckoutRouteRuntime(bindings, options);
|
|
122
|
+
}
|
|
123
|
+
function assertCheckoutRuntimeSupportsCollection(runtime, input) {
|
|
124
|
+
if (input.method === "card" && Object.keys(runtime.paymentStarters).length === 0) {
|
|
125
|
+
throw new CheckoutRouteRuntimeNotConfiguredError();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
103
128
|
export function buildCheckoutRouteRuntime(bindings, options = {}) {
|
|
104
129
|
return {
|
|
105
130
|
bindings,
|
|
@@ -274,6 +274,29 @@ export declare const financeInvoiceCoreRoutes: OpenAPIHono<Env, import("hono/typ
|
|
|
274
274
|
};
|
|
275
275
|
outputFormat: "json";
|
|
276
276
|
status: 400;
|
|
277
|
+
} | {
|
|
278
|
+
input: {
|
|
279
|
+
param: {
|
|
280
|
+
id: string;
|
|
281
|
+
};
|
|
282
|
+
} & {
|
|
283
|
+
json: {
|
|
284
|
+
creditNoteNumber: string;
|
|
285
|
+
amountCents: number;
|
|
286
|
+
currency: string;
|
|
287
|
+
reason: string;
|
|
288
|
+
status?: "draft" | "issued" | "applied" | undefined;
|
|
289
|
+
baseCurrency?: string | null | undefined;
|
|
290
|
+
baseAmountCents?: number | null | undefined;
|
|
291
|
+
fxRateSetId?: string | null | undefined;
|
|
292
|
+
notes?: string | null | undefined;
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
output: {
|
|
296
|
+
error: string;
|
|
297
|
+
};
|
|
298
|
+
outputFormat: "json";
|
|
299
|
+
status: 409;
|
|
277
300
|
} | {
|
|
278
301
|
input: {
|
|
279
302
|
param: {
|
|
@@ -363,6 +386,30 @@ export declare const financeInvoiceCoreRoutes: OpenAPIHono<Env, import("hono/typ
|
|
|
363
386
|
};
|
|
364
387
|
outputFormat: "json";
|
|
365
388
|
status: 400;
|
|
389
|
+
} | {
|
|
390
|
+
input: {
|
|
391
|
+
param: {
|
|
392
|
+
id: string;
|
|
393
|
+
creditNoteId: string;
|
|
394
|
+
};
|
|
395
|
+
} & {
|
|
396
|
+
json: {
|
|
397
|
+
creditNoteNumber?: string | undefined;
|
|
398
|
+
status?: "draft" | "issued" | "applied" | undefined;
|
|
399
|
+
amountCents?: number | undefined;
|
|
400
|
+
currency?: string | undefined;
|
|
401
|
+
baseCurrency?: string | null | undefined;
|
|
402
|
+
baseAmountCents?: number | null | undefined;
|
|
403
|
+
fxRateSetId?: string | null | undefined;
|
|
404
|
+
reason?: string | undefined;
|
|
405
|
+
notes?: string | null | undefined;
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
output: {
|
|
409
|
+
error: string;
|
|
410
|
+
};
|
|
411
|
+
outputFormat: "json";
|
|
412
|
+
status: 409;
|
|
366
413
|
} | {
|
|
367
414
|
input: {
|
|
368
415
|
param: {
|
|
@@ -1005,6 +1052,43 @@ export declare const financeInvoiceCoreRoutes: OpenAPIHono<Env, import("hono/typ
|
|
|
1005
1052
|
};
|
|
1006
1053
|
outputFormat: "json";
|
|
1007
1054
|
status: 400;
|
|
1055
|
+
} | {
|
|
1056
|
+
input: {
|
|
1057
|
+
param: {
|
|
1058
|
+
id: string;
|
|
1059
|
+
};
|
|
1060
|
+
} & {
|
|
1061
|
+
json: {
|
|
1062
|
+
invoiceNumber?: string | undefined;
|
|
1063
|
+
bookingId?: string | undefined;
|
|
1064
|
+
personId?: string | null | undefined;
|
|
1065
|
+
organizationId?: string | null | undefined;
|
|
1066
|
+
status?: "draft" | "pending_external_allocation" | "issued" | "partially_paid" | "paid" | "overdue" | "void" | undefined;
|
|
1067
|
+
currency?: string | undefined;
|
|
1068
|
+
baseCurrency?: string | null | undefined;
|
|
1069
|
+
fxRateSetId?: string | null | undefined;
|
|
1070
|
+
subtotalCents?: number | undefined;
|
|
1071
|
+
baseSubtotalCents?: number | null | undefined;
|
|
1072
|
+
taxCents?: number | undefined;
|
|
1073
|
+
baseTaxCents?: number | null | undefined;
|
|
1074
|
+
totalCents?: number | undefined;
|
|
1075
|
+
baseTotalCents?: number | null | undefined;
|
|
1076
|
+
paidCents?: number | undefined;
|
|
1077
|
+
basePaidCents?: number | null | undefined;
|
|
1078
|
+
balanceDueCents?: number | undefined;
|
|
1079
|
+
baseBalanceDueCents?: number | null | undefined;
|
|
1080
|
+
commissionPercent?: number | null | undefined;
|
|
1081
|
+
commissionAmountCents?: number | null | undefined;
|
|
1082
|
+
issueDate?: string | undefined;
|
|
1083
|
+
dueDate?: string | undefined;
|
|
1084
|
+
notes?: string | null | undefined;
|
|
1085
|
+
};
|
|
1086
|
+
};
|
|
1087
|
+
output: {
|
|
1088
|
+
error: string;
|
|
1089
|
+
};
|
|
1090
|
+
outputFormat: "json";
|
|
1091
|
+
status: 409;
|
|
1008
1092
|
};
|
|
1009
1093
|
};
|
|
1010
1094
|
} & {
|
|
@@ -1068,6 +1152,17 @@ export declare const financeInvoiceCoreRoutes: OpenAPIHono<Env, import("hono/typ
|
|
|
1068
1152
|
};
|
|
1069
1153
|
outputFormat: "json";
|
|
1070
1154
|
status: 400;
|
|
1155
|
+
} | {
|
|
1156
|
+
input: {
|
|
1157
|
+
param: {
|
|
1158
|
+
id: string;
|
|
1159
|
+
};
|
|
1160
|
+
};
|
|
1161
|
+
output: {
|
|
1162
|
+
error: string;
|
|
1163
|
+
};
|
|
1164
|
+
outputFormat: "json";
|
|
1165
|
+
status: 409;
|
|
1071
1166
|
} | {
|
|
1072
1167
|
input: {
|
|
1073
1168
|
param: {
|
|
@@ -1115,17 +1210,6 @@ export declare const financeInvoiceCoreRoutes: OpenAPIHono<Env, import("hono/typ
|
|
|
1115
1210
|
};
|
|
1116
1211
|
outputFormat: "json";
|
|
1117
1212
|
status: 200;
|
|
1118
|
-
} | {
|
|
1119
|
-
input: {
|
|
1120
|
-
param: {
|
|
1121
|
-
id: string;
|
|
1122
|
-
};
|
|
1123
|
-
};
|
|
1124
|
-
output: {
|
|
1125
|
-
error: string;
|
|
1126
|
-
};
|
|
1127
|
-
outputFormat: "json";
|
|
1128
|
-
status: 409;
|
|
1129
1213
|
};
|
|
1130
1214
|
};
|
|
1131
1215
|
} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-invoice-core.d.ts","sourceRoot":"","sources":["../src/routes-invoice-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAe,WAAW,EAAK,MAAM,mBAAmB,CAAA;AAe/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"routes-invoice-core.d.ts","sourceRoot":"","sources":["../src/routes-invoice-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAe,WAAW,EAAK,MAAM,mBAAmB,CAAA;AAe/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAgwB7C,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAQZ,CAAA"}
|
|
@@ -25,7 +25,7 @@ import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
|
|
25
25
|
import { openApiValidationHook, parseOptionalJsonBody, requireUserId } from "@voyant-travel/hono";
|
|
26
26
|
import { creditNoteLineItemSchema, creditNoteSchema, errorResponseSchema, financeNoteSchema, invoiceDetailSchema, invoiceLineItemSchema, invoiceSchema, paymentSchema, paymentSessionSchema, successResponseSchema, } from "./routes-invoice-schemas.js";
|
|
27
27
|
import { getActionLedgerRequestContext, getFinanceRouteRuntime } from "./routes-runtime.js";
|
|
28
|
-
import { financeService, PaymentValidationError } from "./service.js";
|
|
28
|
+
import { financeService, InvoiceNumberConflictError, InvoiceValidationError, PaymentValidationError, } from "./service.js";
|
|
29
29
|
import { createPaymentSessionFromInvoiceSchema, insertCreditNoteLineItemSchema, insertCreditNoteSchema, insertFinanceNoteSchema, insertInvoiceLineItemSchema, insertPaymentSchema, updateCreditNoteSchema, updateInvoiceLineItemSchema, updateInvoiceSchema, voidInvoiceSchema, } from "./validation.js";
|
|
30
30
|
const idParamSchema = z.object({ id: z.string() });
|
|
31
31
|
const lineParamSchema = z.object({ id: z.string(), lineId: z.string() });
|
|
@@ -69,6 +69,10 @@ const updateInvoiceRoute = createRoute({
|
|
|
69
69
|
description: "Invoice not found",
|
|
70
70
|
content: { "application/json": { schema: errorResponseSchema } },
|
|
71
71
|
},
|
|
72
|
+
409: {
|
|
73
|
+
description: "Invoice number already exists",
|
|
74
|
+
content: { "application/json": { schema: errorResponseSchema } },
|
|
75
|
+
},
|
|
72
76
|
},
|
|
73
77
|
});
|
|
74
78
|
const deleteInvoiceRoute = createRoute({
|
|
@@ -154,13 +158,28 @@ const invoiceActionRoutes = new OpenAPIHono({ defaultHook: openApiValidationHook
|
|
|
154
158
|
return row ? c.json({ data: row }, 200) : c.json({ error: "Invoice not found" }, 404);
|
|
155
159
|
})
|
|
156
160
|
.openapi(updateInvoiceRoute, async (c) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
try {
|
|
162
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
163
|
+
const row = await financeService.updateInvoice(c.get("db"), c.req.valid("param").id, c.req.valid("json"), {
|
|
164
|
+
eventBus: runtime?.eventBus,
|
|
165
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
166
|
+
actionLedgerAuthorizationSource: "finance.invoice.route",
|
|
167
|
+
});
|
|
168
|
+
return row ? c.json({ data: row }, 200) : c.json({ error: "Invoice not found" }, 404);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
if (error instanceof InvoiceNumberConflictError) {
|
|
172
|
+
return c.json({
|
|
173
|
+
error: "Invoice number already exists",
|
|
174
|
+
code: error.code,
|
|
175
|
+
invoiceNumber: error.invoiceNumber,
|
|
176
|
+
}, 409);
|
|
177
|
+
}
|
|
178
|
+
if (error instanceof InvoiceValidationError) {
|
|
179
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, error.status);
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
164
183
|
})
|
|
165
184
|
.openapi(deleteInvoiceRoute, async (c) => {
|
|
166
185
|
const runtime = getFinanceRouteRuntime(c);
|
|
@@ -304,22 +323,48 @@ const deleteInvoiceLineItemRoute = createRoute({
|
|
|
304
323
|
const invoiceLineItemRoutes = new OpenAPIHono({ defaultHook: openApiValidationHook })
|
|
305
324
|
.openapi(listInvoiceLineItemsRoute, async (c) => c.json({ data: await financeService.listInvoiceLineItems(c.get("db"), c.req.valid("param").id) }, 200))
|
|
306
325
|
.openapi(createInvoiceLineItemRoute, async (c) => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
326
|
+
try {
|
|
327
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
328
|
+
const row = await financeService.createInvoiceLineItem(c.get("db"), c.req.valid("param").id, c.req.valid("json"), {
|
|
329
|
+
eventBus: runtime?.eventBus,
|
|
330
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
331
|
+
actionLedgerAuthorizationSource: "finance.invoice_line_item.route",
|
|
332
|
+
});
|
|
333
|
+
return row ? c.json({ data: row }, 201) : c.json({ error: "Invoice not found" }, 404);
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
if (error instanceof InvoiceValidationError) {
|
|
337
|
+
if (error.status === 404) {
|
|
338
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 404);
|
|
339
|
+
}
|
|
340
|
+
if (error.status === 409)
|
|
341
|
+
throw error;
|
|
342
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 400);
|
|
343
|
+
}
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
314
346
|
})
|
|
315
347
|
.openapi(updateInvoiceLineItemRoute, async (c) => {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
348
|
+
try {
|
|
349
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
350
|
+
const row = await financeService.updateInvoiceLineItem(c.get("db"), c.req.valid("param").lineId, c.req.valid("json"), {
|
|
351
|
+
eventBus: runtime?.eventBus,
|
|
352
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
353
|
+
actionLedgerAuthorizationSource: "finance.invoice_line_item.route",
|
|
354
|
+
});
|
|
355
|
+
return row ? c.json({ data: row }, 200) : c.json({ error: "Line item not found" }, 404);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (error instanceof InvoiceValidationError) {
|
|
359
|
+
if (error.status === 404) {
|
|
360
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 404);
|
|
361
|
+
}
|
|
362
|
+
if (error.status === 409)
|
|
363
|
+
throw error;
|
|
364
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 400);
|
|
365
|
+
}
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
323
368
|
})
|
|
324
369
|
.openapi(deleteInvoiceLineItemRoute, async (c) => {
|
|
325
370
|
const runtime = getFinanceRouteRuntime(c);
|
|
@@ -428,6 +473,10 @@ const createCreditNoteRoute = createRoute({
|
|
|
428
473
|
description: "Invoice not found",
|
|
429
474
|
content: { "application/json": { schema: errorResponseSchema } },
|
|
430
475
|
},
|
|
476
|
+
409: {
|
|
477
|
+
description: "Credit note would exceed the invoice balance due",
|
|
478
|
+
content: { "application/json": { schema: errorResponseSchema } },
|
|
479
|
+
},
|
|
431
480
|
},
|
|
432
481
|
});
|
|
433
482
|
const updateCreditNoteRoute = createRoute({
|
|
@@ -453,27 +502,59 @@ const updateCreditNoteRoute = createRoute({
|
|
|
453
502
|
description: "Credit note not found",
|
|
454
503
|
content: { "application/json": { schema: errorResponseSchema } },
|
|
455
504
|
},
|
|
505
|
+
409: {
|
|
506
|
+
description: "Credit note would exceed the invoice balance due",
|
|
507
|
+
content: { "application/json": { schema: errorResponseSchema } },
|
|
508
|
+
},
|
|
456
509
|
},
|
|
457
510
|
});
|
|
458
511
|
const creditNoteRoutes = new OpenAPIHono({ defaultHook: openApiValidationHook })
|
|
459
512
|
.openapi(listCreditNotesRoute, async (c) => c.json({ data: await financeService.listCreditNotes(c.get("db"), c.req.valid("param").id) }, 200))
|
|
460
513
|
.openapi(createCreditNoteRoute, async (c) => {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
514
|
+
try {
|
|
515
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
516
|
+
const row = await financeService.createCreditNote(c.get("db"), c.req.valid("param").id, c.req.valid("json"), {
|
|
517
|
+
...(runtime ?? {}),
|
|
518
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
519
|
+
actionLedgerAuthorizationSource: "finance.credit_note.route",
|
|
520
|
+
});
|
|
521
|
+
return row ? c.json({ data: row }, 201) : c.json({ error: "Invoice not found" }, 404);
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
if (error instanceof InvoiceValidationError) {
|
|
525
|
+
if (error.status === 404) {
|
|
526
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 404);
|
|
527
|
+
}
|
|
528
|
+
if (error.status === 409) {
|
|
529
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 409);
|
|
530
|
+
}
|
|
531
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 400);
|
|
532
|
+
}
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
468
535
|
})
|
|
469
536
|
.openapi(updateCreditNoteRoute, async (c) => {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
537
|
+
try {
|
|
538
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
539
|
+
const row = await financeService.updateCreditNote(c.get("db"), c.req.valid("param").creditNoteId, c.req.valid("json"), {
|
|
540
|
+
...(runtime ?? {}),
|
|
541
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
542
|
+
actionLedgerAuthorizationSource: "finance.credit_note.route",
|
|
543
|
+
});
|
|
544
|
+
return row ? c.json({ data: row }, 200) : c.json({ error: "Credit note not found" }, 404);
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
if (error instanceof InvoiceValidationError) {
|
|
548
|
+
if (error.status === 404) {
|
|
549
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 404);
|
|
550
|
+
}
|
|
551
|
+
if (error.status === 409) {
|
|
552
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 409);
|
|
553
|
+
}
|
|
554
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 400);
|
|
555
|
+
}
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
477
558
|
});
|
|
478
559
|
// --- credit note line items ------------------------------------------------
|
|
479
560
|
const listCreditNoteLineItemsRoute = createRoute({
|
|
@@ -519,13 +600,26 @@ const creditNoteLineItemRoutes = new OpenAPIHono({ defaultHook: openApiValidatio
|
|
|
519
600
|
data: await financeService.listCreditNoteLineItems(c.get("db"), c.req.valid("param").creditNoteId),
|
|
520
601
|
}, 200))
|
|
521
602
|
.openapi(createCreditNoteLineItemRoute, async (c) => {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
603
|
+
try {
|
|
604
|
+
const runtime = getFinanceRouteRuntime(c);
|
|
605
|
+
const row = await financeService.createCreditNoteLineItem(c.get("db"), c.req.valid("param").creditNoteId, c.req.valid("json"), {
|
|
606
|
+
eventBus: runtime?.eventBus,
|
|
607
|
+
actionLedgerContext: getActionLedgerRequestContext(c),
|
|
608
|
+
actionLedgerAuthorizationSource: "finance.credit_note_line_item.route",
|
|
609
|
+
});
|
|
610
|
+
return row ? c.json({ data: row }, 201) : c.json({ error: "Credit note not found" }, 404);
|
|
611
|
+
}
|
|
612
|
+
catch (error) {
|
|
613
|
+
if (error instanceof InvoiceValidationError) {
|
|
614
|
+
if (error.status === 404) {
|
|
615
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 404);
|
|
616
|
+
}
|
|
617
|
+
if (error.status === 409)
|
|
618
|
+
throw error;
|
|
619
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, 400);
|
|
620
|
+
}
|
|
621
|
+
throw error;
|
|
622
|
+
}
|
|
529
623
|
});
|
|
530
624
|
// --- finance notes ---------------------------------------------------------
|
|
531
625
|
const listNotesRoute = createRoute({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-invoice-issue.d.ts","sourceRoot":"","sources":["../src/routes-invoice-issue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAe,WAAW,EAAK,MAAM,mBAAmB,CAAA;AAc/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"routes-invoice-issue.d.ts","sourceRoot":"","sources":["../src/routes-invoice-issue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAe,WAAW,EAAK,MAAM,mBAAmB,CAAA;AAc/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAsH7C,eAAO,MAAM,yBAAyB,2BAEpC,CAAA"}
|
|
@@ -18,7 +18,7 @@ import { openApiValidationHook, parseJsonBody } from "@voyant-travel/hono";
|
|
|
18
18
|
import { listResponseSchema } from "@voyant-travel/types";
|
|
19
19
|
import { errorResponseSchema, invoiceListItemSchema, invoiceSchema, } from "./routes-invoice-schemas.js";
|
|
20
20
|
import { getActionLedgerRequestContext, getFinanceRouteRuntime, routeIdempotencyKey, } from "./routes-runtime.js";
|
|
21
|
-
import { financeService, InvoiceFromBookingValidationError, InvoiceNumberAllocationError, InvoiceNumberConflictError, } from "./service.js";
|
|
21
|
+
import { financeService, InvoiceFromBookingValidationError, InvoiceNumberAllocationError, InvoiceNumberConflictError, InvoiceValidationError, } from "./service.js";
|
|
22
22
|
import { insertInvoiceSchema, invoiceFromBookingSchema, invoiceListQuerySchema, } from "./validation.js";
|
|
23
23
|
const idParamSchema = z.object({ id: z.string() });
|
|
24
24
|
const listInvoicesRoute = createRoute({
|
|
@@ -50,6 +50,14 @@ const createInvoiceRoute = createRoute({
|
|
|
50
50
|
description: "invalid_request: request body failed validation",
|
|
51
51
|
content: { "application/json": { schema: errorResponseSchema } },
|
|
52
52
|
},
|
|
53
|
+
404: {
|
|
54
|
+
description: "Booking, person, or organization reference not found",
|
|
55
|
+
content: { "application/json": { schema: errorResponseSchema } },
|
|
56
|
+
},
|
|
57
|
+
409: {
|
|
58
|
+
description: "Invoice number already exists",
|
|
59
|
+
content: { "application/json": { schema: errorResponseSchema } },
|
|
60
|
+
},
|
|
53
61
|
},
|
|
54
62
|
});
|
|
55
63
|
const issueInvoiceFromBookingRoute = createRoute({
|
|
@@ -126,7 +134,24 @@ financeInvoiceIssueRoutes.use("/invoices/from-booking", postOnly(routeIdempotenc
|
|
|
126
134
|
})));
|
|
127
135
|
financeInvoiceIssueRoutes
|
|
128
136
|
.openapi(listInvoicesRoute, async (c) => c.json(await financeService.listInvoices(c.get("db"), c.req.valid("query")), 200))
|
|
129
|
-
.openapi(createInvoiceRoute, async (c) =>
|
|
137
|
+
.openapi(createInvoiceRoute, async (c) => {
|
|
138
|
+
try {
|
|
139
|
+
return c.json({ data: (await financeService.createInvoice(c.get("db"), c.req.valid("json"))) ?? null }, 201);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (error instanceof InvoiceNumberConflictError) {
|
|
143
|
+
return c.json({
|
|
144
|
+
error: "Invoice number already exists",
|
|
145
|
+
code: error.code,
|
|
146
|
+
invoiceNumber: error.invoiceNumber,
|
|
147
|
+
}, 409);
|
|
148
|
+
}
|
|
149
|
+
if (error instanceof InvoiceValidationError) {
|
|
150
|
+
return c.json({ error: error.message, code: error.code, details: error.details }, error.status);
|
|
151
|
+
}
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
})
|
|
130
155
|
.openapi(issueInvoiceFromBookingRoute, async (c) => {
|
|
131
156
|
const input = c.req.valid("json");
|
|
132
157
|
const db = c.get("db");
|