@voyantjs/checkout 0.3.0 → 0.4.0

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/README.md CHANGED
@@ -8,17 +8,30 @@ This package sits above `@voyantjs/finance` and `@voyantjs/notifications`. It do
8
8
 
9
9
  - previews a booking collection plan
10
10
  - creates bank-transfer collection documents (`proforma` by default)
11
+ - supports exact-amount collection overrides by falling back to invoice-backed
12
+ collection when the requested amount does not match an existing schedule
11
13
  - creates card collection `payment_sessions`
12
14
  - supports schedule-backed or invoice-backed card collection
15
+ - can start the provider flow in the same checkout request when a payment
16
+ starter is configured
17
+ - can return customer-safe bank-transfer instructions when a bank-transfer
18
+ resolver is configured
13
19
  - optionally sends invoice or payment-session notifications
14
20
 
15
21
  ## Routes
16
22
 
17
23
  - `POST /v1/checkout/bookings/:bookingId/collection-plan`
18
24
  - `POST /v1/checkout/bookings/:bookingId/initiate-collection`
25
+ - `GET /v1/admin/checkout/bookings/:bookingId/reminder-runs`
19
26
 
20
27
  ## Notes
21
28
 
22
29
  - payment-provider plugins like Netopia remain optional
30
+ - provider startup is injected through `paymentStarters` or
31
+ `resolvePaymentStarters`
32
+ - bank-transfer instructions are injected through `bankTransferDetails` or
33
+ `resolveBankTransferDetails`
23
34
  - email-provider choice remains app-owned
24
- - projects can override the default collection policy when mounting the routes
35
+ - projects can override the default collection policy when mounting checkout
36
+ - `createCheckoutHonoModule()` now mounts checkout through Voyant's module
37
+ system while preserving the legacy `/v1/checkout/*` public path
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { createCheckoutRoutes } from "./routes.js";
2
- export type { CheckoutCollectionPlan, CheckoutPolicyOptions, InitiatedCheckoutCollection, } from "./service.js";
3
- export { initiateCheckoutCollection, previewCheckoutCollection, resolvePaymentSessionTarget, } from "./service.js";
4
- export type { InitiateCheckoutCollectionInput, PreviewCheckoutCollectionInput, } from "./validation.js";
5
- export { checkoutCollectionMethodSchema, checkoutCollectionStageSchema, checkoutInvoiceDocumentTypeSchema, checkoutPaymentSessionTargetSchema, initiateCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./validation.js";
1
+ export { checkoutModule, createCheckoutAdminRoutes, createCheckoutHonoModule, createCheckoutRoutes, } from "./routes.js";
2
+ export type { CheckoutBankTransferDetails, CheckoutCollectionPlan, CheckoutPaymentStarter, CheckoutPolicyOptions, CheckoutProviderStartResult, CheckoutReminderRunList, CheckoutReminderRunSummary, CheckoutRuntimeOptions, InitiatedCheckoutCollection, } from "./service.js";
3
+ export { initiateCheckoutCollection, listBookingReminderRuns, previewCheckoutCollection, resolvePaymentSessionTarget, } from "./service.js";
4
+ export type { CheckoutBankTransferInstructionsRecord, CheckoutCollectionPlanRecord, CheckoutProviderStartInput, CheckoutProviderStartResultRecord, CheckoutReminderRunListQuery, CheckoutReminderRunRecord, InitiateCheckoutCollectionInput, InitiatedCheckoutCollectionRecord, PreviewCheckoutCollectionInput, } from "./validation.js";
5
+ export { checkoutBankTransferInstructionsSchema, checkoutCollectionInvoiceSchema, checkoutCollectionMethodSchema, checkoutCollectionPlanSchema, checkoutCollectionScheduleSchema, checkoutCollectionStageSchema, checkoutInvoiceDocumentTypeSchema, checkoutNotificationDeliverySchema, checkoutPaymentSessionTargetSchema, checkoutProviderStartInputSchema, checkoutProviderStartResultSchema, checkoutReminderRunListQuerySchema, checkoutReminderRunListResponseSchema, checkoutReminderRunSchema, initiateCheckoutCollectionSchema, initiatedCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./validation.js";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,EAC7B,iCAAiC,EACjC,kCAAkC,EAClC,gCAAgC,EAChC,+BAA+B,GAChC,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,sCAAsC,EACtC,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,EACjC,4BAA4B,EAC5B,yBAAyB,EACzB,+BAA+B,EAC/B,iCAAiC,EACjC,8BAA8B,GAC/B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,sCAAsC,EACtC,+BAA+B,EAC/B,8BAA8B,EAC9B,4BAA4B,EAC5B,gCAAgC,EAChC,6BAA6B,EAC7B,iCAAiC,EACjC,kCAAkC,EAClC,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,EACrC,yBAAyB,EACzB,gCAAgC,EAChC,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,iBAAiB,CAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { createCheckoutRoutes } from "./routes.js";
2
- export { initiateCheckoutCollection, previewCheckoutCollection, resolvePaymentSessionTarget, } from "./service.js";
3
- export { checkoutCollectionMethodSchema, checkoutCollectionStageSchema, checkoutInvoiceDocumentTypeSchema, checkoutPaymentSessionTargetSchema, initiateCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./validation.js";
1
+ export { checkoutModule, createCheckoutAdminRoutes, createCheckoutHonoModule, createCheckoutRoutes, } from "./routes.js";
2
+ export { initiateCheckoutCollection, listBookingReminderRuns, previewCheckoutCollection, resolvePaymentSessionTarget, } from "./service.js";
3
+ export { checkoutBankTransferInstructionsSchema, checkoutCollectionInvoiceSchema, checkoutCollectionMethodSchema, checkoutCollectionPlanSchema, checkoutCollectionScheduleSchema, checkoutCollectionStageSchema, checkoutInvoiceDocumentTypeSchema, checkoutNotificationDeliverySchema, checkoutPaymentSessionTargetSchema, checkoutProviderStartInputSchema, checkoutProviderStartResultSchema, checkoutReminderRunListQuerySchema, checkoutReminderRunListResponseSchema, checkoutReminderRunSchema, initiateCheckoutCollectionSchema, initiatedCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./validation.js";
package/dist/routes.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ import type { Module } from "@voyantjs/core";
2
+ import type { HonoModule } from "@voyantjs/hono/module";
1
3
  import type { NotificationProvider } from "@voyantjs/notifications";
2
4
  import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
3
- import { type CheckoutPolicyOptions } from "./service.js";
5
+ import { type CheckoutBankTransferDetails, type CheckoutPaymentStarter, type CheckoutPolicyOptions } from "./service.js";
4
6
  type Env = {
5
7
  Bindings: Record<string, unknown>;
6
8
  Variables: {
@@ -12,6 +14,10 @@ export declare function createCheckoutRoutes(options?: {
12
14
  policy?: CheckoutPolicyOptions;
13
15
  providers?: ReadonlyArray<NotificationProvider>;
14
16
  resolveProviders?: (bindings: Record<string, unknown>) => ReadonlyArray<NotificationProvider>;
17
+ paymentStarters?: Record<string, CheckoutPaymentStarter>;
18
+ resolvePaymentStarters?: (bindings: Record<string, unknown>) => Record<string, CheckoutPaymentStarter>;
19
+ bankTransferDetails?: CheckoutBankTransferDetails | null;
20
+ resolveBankTransferDetails?: (bindings: Record<string, unknown>) => CheckoutBankTransferDetails | null;
15
21
  }): import("hono/hono-base").HonoBase<Env, {
16
22
  "/v1/checkout/bookings/:bookingId/collection-plan": {
17
23
  $post: {
@@ -280,25 +286,25 @@ export declare function createCheckoutRoutes(options?: {
280
286
  } | null;
281
287
  channel: "email" | "sms";
282
288
  provider: string;
283
- targetType: "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "payment_session" | "person" | "organization";
289
+ targetType: "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "organization" | "person" | "payment_session";
284
290
  targetId: string | null;
285
291
  templateId: string | null;
286
292
  invoiceId: string | null;
287
293
  failedAt: string | null;
288
294
  errorMessage: string | null;
295
+ subject: string | null;
296
+ sentAt: string | null;
289
297
  fromAddress: string | null;
290
298
  templateSlug: string | null;
291
299
  paymentSessionId: string | null;
292
300
  providerMessageId: string | null;
293
301
  toAddress: string;
294
- subject: string | null;
295
302
  htmlBody: string | null;
296
303
  textBody: string | null;
297
304
  payloadData: {
298
305
  [x: string]: import("hono/utils/types").JSONValue;
299
306
  } | null;
300
307
  scheduledFor: string | null;
301
- sentAt: string | null;
302
308
  } | null;
303
309
  paymentSessionNotification: {
304
310
  id: string;
@@ -313,25 +319,49 @@ export declare function createCheckoutRoutes(options?: {
313
319
  } | null;
314
320
  channel: "email" | "sms";
315
321
  provider: string;
316
- targetType: "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "payment_session" | "person" | "organization";
322
+ targetType: "other" | "booking" | "invoice" | "booking_payment_schedule" | "booking_guarantee" | "organization" | "person" | "payment_session";
317
323
  targetId: string | null;
318
324
  templateId: string | null;
319
325
  invoiceId: string | null;
320
326
  failedAt: string | null;
321
327
  errorMessage: string | null;
328
+ subject: string | null;
329
+ sentAt: string | null;
322
330
  fromAddress: string | null;
323
331
  templateSlug: string | null;
324
332
  paymentSessionId: string | null;
325
333
  providerMessageId: string | null;
326
334
  toAddress: string;
327
- subject: string | null;
328
335
  htmlBody: string | null;
329
336
  textBody: string | null;
330
337
  payloadData: {
331
338
  [x: string]: import("hono/utils/types").JSONValue;
332
339
  } | null;
333
340
  scheduledFor: string | null;
334
- sentAt: string | null;
341
+ } | null;
342
+ bankTransferInstructions: {
343
+ provider: string | null;
344
+ invoiceId: string;
345
+ invoiceNumber: string;
346
+ documentType: "invoice" | "proforma";
347
+ amountCents: number;
348
+ currency: string;
349
+ dueDate: string | null;
350
+ beneficiary: string;
351
+ iban: string;
352
+ bankName: string | null;
353
+ notes: string | null;
354
+ } | null;
355
+ providerStart: {
356
+ provider: string;
357
+ paymentSessionId: string;
358
+ redirectUrl: string | null;
359
+ externalReference: string | null;
360
+ providerSessionId: string | null;
361
+ providerPaymentId: string | null;
362
+ response: {
363
+ [x: string]: import("hono/utils/types").JSONValue;
364
+ } | null;
335
365
  } | null;
336
366
  };
337
367
  };
@@ -351,5 +381,46 @@ export declare function createCheckoutRoutes(options?: {
351
381
  };
352
382
  };
353
383
  }, "/", "/v1/checkout/bookings/:bookingId/initiate-collection">;
384
+ export declare function createCheckoutAdminRoutes(): import("hono/hono-base").HonoBase<Env, {
385
+ "/bookings/:bookingId/reminder-runs": {
386
+ $get: {
387
+ input: {
388
+ param: {
389
+ bookingId: string;
390
+ };
391
+ };
392
+ output: {
393
+ data: {
394
+ id: string;
395
+ reminderRuleId: string;
396
+ reminderRuleSlug: string | null;
397
+ reminderRuleName: string | null;
398
+ targetType: "booking_payment_schedule" | "invoice";
399
+ targetId: string;
400
+ bookingId: string | null;
401
+ paymentSessionId: string | null;
402
+ notificationDeliveryId: string | null;
403
+ status: "processing" | "sent" | "skipped" | "failed";
404
+ deliveryStatus: "pending" | "sent" | "failed" | "cancelled" | null;
405
+ channel: "email" | "sms" | null;
406
+ provider: string | null;
407
+ recipient: string | null;
408
+ scheduledFor: string;
409
+ processedAt: string;
410
+ errorMessage: string | null;
411
+ relativeDaysFromDueDate: number | null;
412
+ createdAt: string;
413
+ }[];
414
+ total: number;
415
+ limit: number;
416
+ offset: number;
417
+ };
418
+ outputFormat: "json";
419
+ status: import("hono/utils/http-status").ContentfulStatusCode;
420
+ };
421
+ };
422
+ }, "/", "/bookings/:bookingId/reminder-runs">;
423
+ export declare const checkoutModule: Module;
424
+ export declare function createCheckoutHonoModule(options?: Parameters<typeof createCheckoutRoutes>[0]): HonoModule;
354
425
  export {};
355
426
  //# sourceMappingURL=routes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,cAAc,CAAA;AAGrB,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC/C,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAC,oBAAoB,CAAC,CAAA;CACzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAkDP"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAEnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAI3B,MAAM,cAAc,CAAA;AAOrB,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC/C,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC7F,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;CACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAyDP;AAED,wBAAgB,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAQxC;AAED,eAAO,MAAM,cAAc,EAAE,MAE5B,CAAA;AAED,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,GACnD,UAAU,CAMZ"}
package/dist/routes.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createNotificationService } from "@voyantjs/notifications";
2
2
  import { Hono } from "hono";
3
- import { initiateCheckoutCollection, previewCheckoutCollection, } from "./service.js";
4
- import { initiateCheckoutCollectionSchema, previewCheckoutCollectionSchema } from "./validation.js";
3
+ import { initiateCheckoutCollection, listBookingReminderRuns, previewCheckoutCollection, } from "./service.js";
4
+ import { checkoutReminderRunListQuerySchema, initiateCheckoutCollectionSchema, previewCheckoutCollectionSchema, } from "./validation.js";
5
5
  export function createCheckoutRoutes(options = {}) {
6
6
  return new Hono()
7
7
  .post("/v1/checkout/bookings/:bookingId/collection-plan", async (c) => {
@@ -20,7 +20,11 @@ export function createCheckoutRoutes(options = {}) {
20
20
  .post("/v1/checkout/bookings/:bookingId/initiate-collection", async (c) => {
21
21
  try {
22
22
  const dispatcher = createNotificationService(options.resolveProviders?.(c.env) ?? options.providers ?? []);
23
- const result = await initiateCheckoutCollection(c.get("db"), c.req.param("bookingId"), initiateCheckoutCollectionSchema.parse(await c.req.json()), options.policy, dispatcher);
23
+ const result = await initiateCheckoutCollection(c.get("db"), c.req.param("bookingId"), initiateCheckoutCollectionSchema.parse(await c.req.json()), options.policy, dispatcher, {
24
+ bindings: c.env,
25
+ paymentStarters: options.resolvePaymentStarters?.(c.env) ?? options.paymentStarters ?? {},
26
+ bankTransferDetails: options.resolveBankTransferDetails?.(c.env) ?? options.bankTransferDetails ?? null,
27
+ });
24
28
  if (!result) {
25
29
  return c.json({ error: "Booking not found" }, 404);
26
30
  }
@@ -35,3 +39,19 @@ export function createCheckoutRoutes(options = {}) {
35
39
  }
36
40
  });
37
41
  }
42
+ export function createCheckoutAdminRoutes() {
43
+ return new Hono().get("/bookings/:bookingId/reminder-runs", async (c) => {
44
+ const query = checkoutReminderRunListQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
45
+ return c.json(await listBookingReminderRuns(c.get("db"), c.req.param("bookingId"), query));
46
+ });
47
+ }
48
+ export const checkoutModule = {
49
+ name: "checkout",
50
+ };
51
+ export function createCheckoutHonoModule(options) {
52
+ return {
53
+ module: checkoutModule,
54
+ routes: createCheckoutRoutes(options),
55
+ adminRoutes: createCheckoutAdminRoutes(),
56
+ };
57
+ }
package/dist/service.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { bookingPaymentSchedules, invoices, type PaymentSession } from "@voyantjs/finance";
2
2
  import type { NotificationDelivery, NotificationService } from "@voyantjs/notifications";
3
3
  import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
4
- import type { InitiateCheckoutCollectionInput, PreviewCheckoutCollectionInput } from "./validation.js";
4
+ import type { CheckoutBankTransferInstructionsRecord, CheckoutProviderStartInput, CheckoutReminderRunListQuery, InitiateCheckoutCollectionInput, PreviewCheckoutCollectionInput } from "./validation.js";
5
5
  export interface CheckoutPolicyOptions {
6
6
  defaultCardCollectionTarget?: "schedule" | "invoice";
7
7
  defaultReminderCardCollectionTarget?: "schedule" | "invoice";
@@ -29,14 +29,77 @@ export interface CheckoutCollectionPlan {
29
29
  currency: string;
30
30
  recommendedAction: "create_bank_transfer_document" | "create_payment_session" | "create_invoice_then_payment_session" | "none";
31
31
  }
32
+ export interface CheckoutBankTransferDetails {
33
+ provider?: string | null;
34
+ beneficiary: string;
35
+ iban: string;
36
+ bankName?: string | null;
37
+ currency?: string | null;
38
+ notes?: string | null;
39
+ }
40
+ export interface CheckoutProviderStartResult {
41
+ provider: string;
42
+ paymentSessionId: string;
43
+ redirectUrl: string | null;
44
+ externalReference: string | null;
45
+ providerSessionId: string | null;
46
+ providerPaymentId: string | null;
47
+ response: Record<string, unknown> | null;
48
+ }
49
+ export interface CheckoutPaymentStarterContext {
50
+ db: PostgresJsDatabase;
51
+ bookingId: string;
52
+ plan: CheckoutCollectionPlan;
53
+ invoice: typeof invoices.$inferSelect | null;
54
+ paymentSession: PaymentSession;
55
+ input: InitiateCheckoutCollectionInput;
56
+ startProvider: CheckoutProviderStartInput;
57
+ bindings: Record<string, unknown>;
58
+ }
59
+ export type CheckoutPaymentStarter = (context: CheckoutPaymentStarterContext) => Promise<CheckoutProviderStartResult>;
32
60
  export interface InitiatedCheckoutCollection {
33
61
  plan: CheckoutCollectionPlan;
34
62
  invoice: typeof invoices.$inferSelect | null;
35
63
  paymentSession: PaymentSession | null;
36
64
  invoiceNotification: NotificationDelivery | null;
37
65
  paymentSessionNotification: NotificationDelivery | null;
66
+ bankTransferInstructions: CheckoutBankTransferInstructionsRecord | null;
67
+ providerStart: CheckoutProviderStartResult | null;
68
+ }
69
+ export interface CheckoutRuntimeOptions {
70
+ bindings?: Record<string, unknown>;
71
+ bankTransferDetails?: CheckoutBankTransferDetails | null;
72
+ paymentStarters?: Record<string, CheckoutPaymentStarter>;
73
+ }
74
+ export interface CheckoutReminderRunSummary {
75
+ id: string;
76
+ reminderRuleId: string;
77
+ reminderRuleSlug: string | null;
78
+ reminderRuleName: string | null;
79
+ targetType: "booking_payment_schedule" | "invoice";
80
+ targetId: string;
81
+ bookingId: string | null;
82
+ paymentSessionId: string | null;
83
+ notificationDeliveryId: string | null;
84
+ status: "processing" | "sent" | "skipped" | "failed";
85
+ deliveryStatus: "pending" | "sent" | "failed" | "cancelled" | null;
86
+ channel: "email" | "sms" | null;
87
+ provider: string | null;
88
+ recipient: string | null;
89
+ scheduledFor: string;
90
+ processedAt: string;
91
+ errorMessage: string | null;
92
+ relativeDaysFromDueDate: number | null;
93
+ createdAt: string;
94
+ }
95
+ export interface CheckoutReminderRunList {
96
+ data: CheckoutReminderRunSummary[];
97
+ total: number;
98
+ limit: number;
99
+ offset: number;
38
100
  }
39
101
  export declare function resolvePaymentSessionTarget(method: "card" | "bank_transfer", stage: "initial" | "reminder" | "manual", override: "schedule" | "invoice" | undefined, options: CheckoutPolicyOptions): "invoice" | "schedule";
40
102
  export declare function previewCheckoutCollection(db: PostgresJsDatabase, bookingId: string, input: PreviewCheckoutCollectionInput, options?: CheckoutPolicyOptions): Promise<CheckoutCollectionPlan | null>;
41
- export declare function initiateCheckoutCollection(db: PostgresJsDatabase, bookingId: string, input: InitiateCheckoutCollectionInput, options?: CheckoutPolicyOptions, dispatcher?: NotificationService): Promise<InitiatedCheckoutCollection | null>;
103
+ export declare function initiateCheckoutCollection(db: PostgresJsDatabase, bookingId: string, input: InitiateCheckoutCollectionInput, options?: CheckoutPolicyOptions, dispatcher?: NotificationService, runtime?: CheckoutRuntimeOptions): Promise<InitiatedCheckoutCollection | null>;
104
+ export declare function listBookingReminderRuns(db: PostgresJsDatabase, bookingId: string, query: CheckoutReminderRunListQuery): Promise<CheckoutReminderRunList>;
42
105
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EAIvB,QAAQ,EACR,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAGxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,KAAK,EACV,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,iBAAiB,CAAA;AAExB,MAAM,WAAW,qBAAqB;IACpC,2BAA2B,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IACpD,mCAAmC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IAC5D,+BAA+B,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IACxD,kBAAkB,CAAC,EAAE;QACnB,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,cAAc,CAAA;QACnD,YAAY,EAAE,MAAM,CAAA;QACpB,yBAAyB,EAAE,MAAM,CAAA;QACjC,oBAAoB,EAAE,OAAO,CAAA;QAC7B,eAAe,EAAE,OAAO,CAAA;QACxB,aAAa,EACT,SAAS,GACT,aAAa,GACb,SAAS,GACT,cAAc,GACd,eAAe,GACf,SAAS,GACT,eAAe,CAAA;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB,CAAA;CACF;AAUD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,eAAe,CAAA;IAChC,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAA;IACxC,oBAAoB,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAAA;IACnD,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAAA;IAC3C,4BAA4B,EAAE,OAAO,CAAA;IACrC,gBAAgB,EAAE,OAAO,uBAAuB,CAAC,YAAY,GAAG,IAAI,CAAA;IACpE,eAAe,EAAE,OAAO,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAA;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB,EACb,+BAA+B,GAC/B,wBAAwB,GACxB,qCAAqC,GACrC,MAAM,CAAA;CACX;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,sBAAsB,CAAA;IAC5B,OAAO,EAAE,OAAO,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAA;IAC5C,cAAc,EAAE,cAAc,GAAG,IAAI,CAAA;IACrC,mBAAmB,EAAE,oBAAoB,GAAG,IAAI,CAAA;IAChD,0BAA0B,EAAE,oBAAoB,GAAG,IAAI,CAAA;CACxD;AAwBD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,GAAG,eAAe,EAChC,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,EACxC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,EAC5C,OAAO,EAAE,qBAAqB,0BAM/B;AAwJD,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,8BAA8B,EACrC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAyDxC;AAkED,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,+BAA+B,EACtC,OAAO,GAAE,qBAA0B,EACnC,UAAU,CAAC,EAAE,mBAAmB,GAC/B,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAiG7C"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/dist/service.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { bookingItems, bookingParticipants, bookings } from "@voyantjs/bookings";
2
2
  import { bookingPaymentSchedules, financeService, invoiceLineItems, invoiceNumberSeries, invoices, } from "@voyantjs/finance";
3
- import { notificationsService } from "@voyantjs/notifications";
4
- import { and, asc, desc, eq, gt, inArray } from "drizzle-orm";
3
+ import { notificationDeliveries, notificationReminderRules, notificationReminderRuns, notificationsService, } from "@voyantjs/notifications";
4
+ import { and, asc, desc, eq, gt, inArray, sql } from "drizzle-orm";
5
5
  const OUTSTANDING_SCHEDULE_STATUSES = ["pending", "due"];
6
6
  const OUTSTANDING_INVOICE_STATUSES = [
7
7
  "draft",
@@ -9,6 +9,9 @@ const OUTSTANDING_INVOICE_STATUSES = [
9
9
  "partially_paid",
10
10
  "overdue",
11
11
  ];
12
+ function normalizeRequiredDateTime(value) {
13
+ return value instanceof Date ? value.toISOString() : value;
14
+ }
12
15
  function defaultPaymentPlan(options) {
13
16
  return {
14
17
  depositMode: options.defaultPaymentPlan?.depositMode ?? "percentage",
@@ -53,6 +56,32 @@ function lineDescription(booking, schedule, stage) {
53
56
  }
54
57
  return `Booking ${booking.bookingNumber} ${kind}`;
55
58
  }
59
+ function normalizeExactAmountCents(amountCents) {
60
+ return typeof amountCents === "number" && Number.isFinite(amountCents) && amountCents > 0
61
+ ? Math.round(amountCents)
62
+ : null;
63
+ }
64
+ function toInvoiceDueDateTime(value) {
65
+ return value ? `${value}T00:00:00.000Z` : null;
66
+ }
67
+ function buildBankTransferInstructions(invoice, details) {
68
+ if (!details) {
69
+ return null;
70
+ }
71
+ return {
72
+ provider: details.provider ?? null,
73
+ invoiceId: invoice.id,
74
+ invoiceNumber: invoice.invoiceNumber,
75
+ documentType: invoice.invoiceType === "proforma" ? "proforma" : "invoice",
76
+ amountCents: invoice.balanceDueCents,
77
+ currency: details.currency ?? invoice.currency,
78
+ dueDate: toInvoiceDueDateTime(invoice.dueDate),
79
+ beneficiary: details.beneficiary,
80
+ iban: details.iban,
81
+ bankName: details.bankName ?? null,
82
+ notes: details.notes ?? null,
83
+ };
84
+ }
56
85
  async function loadBookingContext(db, bookingId) {
57
86
  const [booking] = await db.select().from(bookings).where(eq(bookings.id, bookingId)).limit(1);
58
87
  if (!booking)
@@ -130,12 +159,30 @@ export async function previewCheckoutCollection(db, bookingId, input, options =
130
159
  if (!context)
131
160
  return null;
132
161
  const schedules = await ensurePaymentPlanIfNeeded(db, bookingId, context.schedules, input, options);
133
- const paymentSessionTarget = resolvePaymentSessionTarget(input.method, input.stage, input.paymentSessionTarget, options);
134
- const documentType = resolveDocumentType(input.method, paymentSessionTarget, options);
135
- const selectedSchedule = pickSchedule(schedules, input.scheduleId);
136
- const selectedInvoice = pickInvoice(context.outstandingInvoices, input.invoiceId);
162
+ let paymentSessionTarget = resolvePaymentSessionTarget(input.method, input.stage, input.paymentSessionTarget, options);
163
+ let documentType = resolveDocumentType(input.method, paymentSessionTarget, options);
164
+ let selectedSchedule = pickSchedule(schedules, input.scheduleId);
165
+ let selectedInvoice = pickInvoice(context.outstandingInvoices, input.invoiceId);
166
+ const requestedAmountCents = normalizeExactAmountCents(input.amountCents);
137
167
  let amountCents = 0;
138
- if (paymentSessionTarget === "invoice") {
168
+ if (requestedAmountCents !== null) {
169
+ amountCents = requestedAmountCents;
170
+ if (paymentSessionTarget === "schedule" &&
171
+ selectedSchedule &&
172
+ selectedSchedule.amountCents === requestedAmountCents) {
173
+ selectedInvoice = null;
174
+ }
175
+ else {
176
+ paymentSessionTarget = "invoice";
177
+ documentType = resolveDocumentType(input.method, paymentSessionTarget, options);
178
+ selectedInvoice =
179
+ selectedInvoice && selectedInvoice.balanceDueCents === requestedAmountCents
180
+ ? selectedInvoice
181
+ : null;
182
+ selectedSchedule = null;
183
+ }
184
+ }
185
+ else if (paymentSessionTarget === "invoice") {
139
186
  amountCents =
140
187
  selectedInvoice?.balanceDueCents ??
141
188
  selectedSchedule?.amountCents ??
@@ -220,7 +267,7 @@ async function createCollectionInvoice(db, context, plan, notes) {
220
267
  });
221
268
  return invoice;
222
269
  }
223
- export async function initiateCheckoutCollection(db, bookingId, input, options = {}, dispatcher) {
270
+ export async function initiateCheckoutCollection(db, bookingId, input, options = {}, dispatcher, runtime = {}) {
224
271
  const context = await loadBookingContext(db, bookingId);
225
272
  if (!context)
226
273
  return null;
@@ -234,8 +281,11 @@ export async function initiateCheckoutCollection(db, bookingId, input, options =
234
281
  let paymentSession = null;
235
282
  let invoiceNotification = null;
236
283
  let paymentSessionNotification = null;
284
+ let bankTransferInstructions = null;
285
+ let providerStart = null;
237
286
  if (input.method === "bank_transfer") {
238
287
  invoice = await createCollectionInvoice(db, context, plan, input.notes ?? null);
288
+ bankTransferInstructions = buildBankTransferInstructions(invoice, runtime.bankTransferDetails ?? null);
239
289
  if (dispatcher && input.invoiceNotification) {
240
290
  invoiceNotification = await notificationsService.sendInvoiceNotification(db, dispatcher, invoice.id, input.invoiceNotification);
241
291
  }
@@ -273,11 +323,105 @@ export async function initiateCheckoutCollection(db, bookingId, input, options =
273
323
  paymentSessionNotification = await notificationsService.sendPaymentSessionNotification(db, dispatcher, paymentSession.id, input.paymentSessionNotification);
274
324
  }
275
325
  }
326
+ if (input.startProvider) {
327
+ if (input.method !== "card") {
328
+ throw new Error("Provider start is only available for card collections");
329
+ }
330
+ if (!paymentSession) {
331
+ throw new Error("No payment session available for provider start");
332
+ }
333
+ const starter = runtime.paymentStarters?.[input.startProvider.provider];
334
+ if (!starter) {
335
+ throw new Error(`Payment provider "${input.startProvider.provider}" is not configured`);
336
+ }
337
+ providerStart = await starter({
338
+ db,
339
+ bookingId,
340
+ plan,
341
+ invoice: invoice ?? null,
342
+ paymentSession,
343
+ input,
344
+ startProvider: input.startProvider,
345
+ bindings: runtime.bindings ?? {},
346
+ });
347
+ if (providerStart.paymentSessionId !== paymentSession.id) {
348
+ const updatedSession = await financeService.getPaymentSessionById(db, providerStart.paymentSessionId);
349
+ paymentSession = updatedSession ?? paymentSession;
350
+ }
351
+ else {
352
+ const updatedSession = await financeService.getPaymentSessionById(db, paymentSession.id);
353
+ paymentSession = updatedSession ?? paymentSession;
354
+ }
355
+ }
276
356
  return {
277
357
  plan,
278
358
  invoice: invoice ?? null,
279
359
  paymentSession,
280
360
  invoiceNotification,
281
361
  paymentSessionNotification,
362
+ bankTransferInstructions,
363
+ providerStart,
364
+ };
365
+ }
366
+ export async function listBookingReminderRuns(db, bookingId, query) {
367
+ const where = and(eq(notificationReminderRuns.bookingId, bookingId), ...(query.status ? [eq(notificationReminderRuns.status, query.status)] : []));
368
+ const [rows, countResult] = await Promise.all([
369
+ db
370
+ .select({
371
+ id: notificationReminderRuns.id,
372
+ reminderRuleId: notificationReminderRuns.reminderRuleId,
373
+ targetType: notificationReminderRuns.targetType,
374
+ targetId: notificationReminderRuns.targetId,
375
+ bookingId: notificationReminderRuns.bookingId,
376
+ paymentSessionId: notificationReminderRuns.paymentSessionId,
377
+ notificationDeliveryId: notificationReminderRuns.notificationDeliveryId,
378
+ status: notificationReminderRuns.status,
379
+ recipient: notificationReminderRuns.recipient,
380
+ scheduledFor: notificationReminderRuns.scheduledFor,
381
+ processedAt: notificationReminderRuns.processedAt,
382
+ errorMessage: notificationReminderRuns.errorMessage,
383
+ createdAt: notificationReminderRuns.createdAt,
384
+ reminderRuleSlug: notificationReminderRules.slug,
385
+ reminderRuleName: notificationReminderRules.name,
386
+ relativeDaysFromDueDate: notificationReminderRules.relativeDaysFromDueDate,
387
+ channel: notificationReminderRules.channel,
388
+ ruleProvider: notificationReminderRules.provider,
389
+ deliveryStatus: notificationDeliveries.status,
390
+ deliveryProvider: notificationDeliveries.provider,
391
+ })
392
+ .from(notificationReminderRuns)
393
+ .leftJoin(notificationReminderRules, eq(notificationReminderRules.id, notificationReminderRuns.reminderRuleId))
394
+ .leftJoin(notificationDeliveries, eq(notificationDeliveries.id, notificationReminderRuns.notificationDeliveryId))
395
+ .where(where)
396
+ .orderBy(desc(notificationReminderRuns.createdAt))
397
+ .limit(query.limit)
398
+ .offset(query.offset),
399
+ db.select({ count: sql `count(*)::int` }).from(notificationReminderRuns).where(where),
400
+ ]);
401
+ return {
402
+ data: rows.map((row) => ({
403
+ id: row.id,
404
+ reminderRuleId: row.reminderRuleId,
405
+ reminderRuleSlug: row.reminderRuleSlug ?? null,
406
+ reminderRuleName: row.reminderRuleName ?? null,
407
+ targetType: row.targetType,
408
+ targetId: row.targetId,
409
+ bookingId: row.bookingId ?? null,
410
+ paymentSessionId: row.paymentSessionId ?? null,
411
+ notificationDeliveryId: row.notificationDeliveryId ?? null,
412
+ status: row.status,
413
+ deliveryStatus: row.deliveryStatus ?? null,
414
+ channel: row.channel ?? null,
415
+ provider: row.deliveryProvider ?? row.ruleProvider ?? null,
416
+ recipient: row.recipient ?? null,
417
+ scheduledFor: normalizeRequiredDateTime(row.scheduledFor),
418
+ processedAt: normalizeRequiredDateTime(row.processedAt),
419
+ errorMessage: row.errorMessage ?? null,
420
+ relativeDaysFromDueDate: row.relativeDaysFromDueDate ?? null,
421
+ createdAt: normalizeRequiredDateTime(row.createdAt),
422
+ })),
423
+ total: countResult[0]?.count ?? 0,
424
+ limit: query.limit,
425
+ offset: query.offset,
282
426
  };
283
427
  }
@@ -16,6 +16,10 @@ export declare const checkoutInvoiceDocumentTypeSchema: z.ZodEnum<{
16
16
  invoice: "invoice";
17
17
  proforma: "proforma";
18
18
  }>;
19
+ export declare const checkoutProviderStartInputSchema: z.ZodObject<{
20
+ provider: z.ZodString;
21
+ payload: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
22
+ }, z.core.$strip>;
19
23
  export declare const previewCheckoutCollectionSchema: z.ZodObject<{
20
24
  method: z.ZodEnum<{
21
25
  bank_transfer: "bank_transfer";
@@ -28,6 +32,7 @@ export declare const previewCheckoutCollectionSchema: z.ZodObject<{
28
32
  }>>;
29
33
  scheduleId: z.ZodOptional<z.ZodString>;
30
34
  invoiceId: z.ZodOptional<z.ZodString>;
35
+ amountCents: z.ZodOptional<z.ZodNumber>;
31
36
  ensureDefaultPaymentPlan: z.ZodDefault<z.ZodBoolean>;
32
37
  paymentSessionTarget: z.ZodOptional<z.ZodEnum<{
33
38
  invoice: "invoice";
@@ -69,6 +74,7 @@ export declare const initiateCheckoutCollectionSchema: z.ZodObject<{
69
74
  }>>;
70
75
  scheduleId: z.ZodOptional<z.ZodString>;
71
76
  invoiceId: z.ZodOptional<z.ZodString>;
77
+ amountCents: z.ZodOptional<z.ZodNumber>;
72
78
  ensureDefaultPaymentPlan: z.ZodDefault<z.ZodBoolean>;
73
79
  paymentSessionTarget: z.ZodOptional<z.ZodEnum<{
74
80
  invoice: "invoice";
@@ -165,6 +171,17 @@ export declare const initiateCheckoutCollectionSchema: z.ZodObject<{
165
171
  subject: z.ZodNullable<z.ZodOptional<z.ZodString>>;
166
172
  html: z.ZodNullable<z.ZodOptional<z.ZodString>>;
167
173
  text: z.ZodNullable<z.ZodOptional<z.ZodString>>;
174
+ attachments: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
175
+ filename: z.ZodString;
176
+ contentBase64: z.ZodNullable<z.ZodOptional<z.ZodString>>;
177
+ path: z.ZodNullable<z.ZodOptional<z.ZodString>>;
178
+ contentType: z.ZodNullable<z.ZodOptional<z.ZodString>>;
179
+ disposition: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
180
+ attachment: "attachment";
181
+ inline: "inline";
182
+ }>>>;
183
+ contentId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
184
+ }, z.core.$strip>>>>;
168
185
  data: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
169
186
  metadata: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
170
187
  scheduledFor: z.ZodNullable<z.ZodOptional<z.ZodString>>;
@@ -182,12 +199,451 @@ export declare const initiateCheckoutCollectionSchema: z.ZodObject<{
182
199
  subject: z.ZodNullable<z.ZodOptional<z.ZodString>>;
183
200
  html: z.ZodNullable<z.ZodOptional<z.ZodString>>;
184
201
  text: z.ZodNullable<z.ZodOptional<z.ZodString>>;
202
+ attachments: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
203
+ filename: z.ZodString;
204
+ contentBase64: z.ZodNullable<z.ZodOptional<z.ZodString>>;
205
+ path: z.ZodNullable<z.ZodOptional<z.ZodString>>;
206
+ contentType: z.ZodNullable<z.ZodOptional<z.ZodString>>;
207
+ disposition: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
208
+ attachment: "attachment";
209
+ inline: "inline";
210
+ }>>>;
211
+ contentId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
212
+ }, z.core.$strip>>>>;
185
213
  data: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
186
214
  metadata: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
187
215
  scheduledFor: z.ZodNullable<z.ZodOptional<z.ZodString>>;
188
216
  }, z.core.$strip>>;
217
+ startProvider: z.ZodOptional<z.ZodObject<{
218
+ provider: z.ZodString;
219
+ payload: z.ZodNullable<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
220
+ }, z.core.$strip>>;
189
221
  notes: z.ZodNullable<z.ZodOptional<z.ZodString>>;
190
222
  }, z.core.$strip>;
223
+ export declare const checkoutCollectionScheduleSchema: z.ZodObject<{
224
+ id: z.ZodString;
225
+ bookingId: z.ZodString;
226
+ bookingItemId: z.ZodNullable<z.ZodString>;
227
+ scheduleType: z.ZodString;
228
+ status: z.ZodString;
229
+ dueDate: z.ZodString;
230
+ currency: z.ZodString;
231
+ amountCents: z.ZodNumber;
232
+ notes: z.ZodNullable<z.ZodString>;
233
+ }, z.core.$strip>;
234
+ export declare const checkoutCollectionInvoiceSchema: z.ZodObject<{
235
+ id: z.ZodString;
236
+ invoiceNumber: z.ZodString;
237
+ invoiceType: z.ZodString;
238
+ bookingId: z.ZodString;
239
+ personId: z.ZodNullable<z.ZodString>;
240
+ organizationId: z.ZodNullable<z.ZodString>;
241
+ status: z.ZodString;
242
+ currency: z.ZodString;
243
+ totalCents: z.ZodNumber;
244
+ paidCents: z.ZodNumber;
245
+ balanceDueCents: z.ZodNumber;
246
+ issueDate: z.ZodString;
247
+ dueDate: z.ZodString;
248
+ notes: z.ZodNullable<z.ZodString>;
249
+ createdAt: z.ZodString;
250
+ updatedAt: z.ZodString;
251
+ }, z.core.$strip>;
252
+ export declare const checkoutNotificationDeliverySchema: z.ZodObject<{
253
+ id: z.ZodString;
254
+ templateSlug: z.ZodNullable<z.ZodString>;
255
+ channel: z.ZodEnum<{
256
+ email: "email";
257
+ sms: "sms";
258
+ }>;
259
+ provider: z.ZodString;
260
+ status: z.ZodEnum<{
261
+ cancelled: "cancelled";
262
+ pending: "pending";
263
+ failed: "failed";
264
+ sent: "sent";
265
+ }>;
266
+ toAddress: z.ZodString;
267
+ subject: z.ZodNullable<z.ZodString>;
268
+ sentAt: z.ZodNullable<z.ZodString>;
269
+ failedAt: z.ZodNullable<z.ZodString>;
270
+ errorMessage: z.ZodNullable<z.ZodString>;
271
+ }, z.core.$strip>;
272
+ export declare const checkoutBankTransferInstructionsSchema: z.ZodObject<{
273
+ provider: z.ZodNullable<z.ZodString>;
274
+ invoiceId: z.ZodString;
275
+ invoiceNumber: z.ZodString;
276
+ documentType: z.ZodEnum<{
277
+ invoice: "invoice";
278
+ proforma: "proforma";
279
+ }>;
280
+ amountCents: z.ZodNumber;
281
+ currency: z.ZodString;
282
+ dueDate: z.ZodNullable<z.ZodString>;
283
+ beneficiary: z.ZodString;
284
+ iban: z.ZodString;
285
+ bankName: z.ZodNullable<z.ZodString>;
286
+ notes: z.ZodNullable<z.ZodString>;
287
+ }, z.core.$strip>;
288
+ export declare const checkoutProviderStartResultSchema: z.ZodObject<{
289
+ provider: z.ZodString;
290
+ paymentSessionId: z.ZodString;
291
+ redirectUrl: z.ZodNullable<z.ZodString>;
292
+ externalReference: z.ZodNullable<z.ZodString>;
293
+ providerSessionId: z.ZodNullable<z.ZodString>;
294
+ providerPaymentId: z.ZodNullable<z.ZodString>;
295
+ response: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
296
+ }, z.core.$strip>;
297
+ export declare const checkoutCollectionPlanSchema: z.ZodObject<{
298
+ bookingId: z.ZodString;
299
+ method: z.ZodEnum<{
300
+ bank_transfer: "bank_transfer";
301
+ card: "card";
302
+ }>;
303
+ stage: z.ZodEnum<{
304
+ manual: "manual";
305
+ initial: "initial";
306
+ reminder: "reminder";
307
+ }>;
308
+ paymentSessionTarget: z.ZodNullable<z.ZodEnum<{
309
+ invoice: "invoice";
310
+ schedule: "schedule";
311
+ }>>;
312
+ documentType: z.ZodNullable<z.ZodEnum<{
313
+ invoice: "invoice";
314
+ proforma: "proforma";
315
+ }>>;
316
+ willCreateDefaultPaymentPlan: z.ZodBoolean;
317
+ selectedSchedule: z.ZodNullable<z.ZodObject<{
318
+ id: z.ZodString;
319
+ bookingId: z.ZodString;
320
+ bookingItemId: z.ZodNullable<z.ZodString>;
321
+ scheduleType: z.ZodString;
322
+ status: z.ZodString;
323
+ dueDate: z.ZodString;
324
+ currency: z.ZodString;
325
+ amountCents: z.ZodNumber;
326
+ notes: z.ZodNullable<z.ZodString>;
327
+ }, z.core.$strip>>;
328
+ selectedInvoice: z.ZodNullable<z.ZodObject<{
329
+ id: z.ZodString;
330
+ invoiceNumber: z.ZodString;
331
+ invoiceType: z.ZodString;
332
+ bookingId: z.ZodString;
333
+ personId: z.ZodNullable<z.ZodString>;
334
+ organizationId: z.ZodNullable<z.ZodString>;
335
+ status: z.ZodString;
336
+ currency: z.ZodString;
337
+ totalCents: z.ZodNumber;
338
+ paidCents: z.ZodNumber;
339
+ balanceDueCents: z.ZodNumber;
340
+ issueDate: z.ZodString;
341
+ dueDate: z.ZodString;
342
+ notes: z.ZodNullable<z.ZodString>;
343
+ createdAt: z.ZodString;
344
+ updatedAt: z.ZodString;
345
+ }, z.core.$strip>>;
346
+ amountCents: z.ZodNumber;
347
+ currency: z.ZodString;
348
+ recommendedAction: z.ZodEnum<{
349
+ none: "none";
350
+ create_bank_transfer_document: "create_bank_transfer_document";
351
+ create_payment_session: "create_payment_session";
352
+ create_invoice_then_payment_session: "create_invoice_then_payment_session";
353
+ }>;
354
+ }, z.core.$strip>;
355
+ export declare const initiatedCheckoutCollectionSchema: z.ZodObject<{
356
+ plan: z.ZodObject<{
357
+ bookingId: z.ZodString;
358
+ method: z.ZodEnum<{
359
+ bank_transfer: "bank_transfer";
360
+ card: "card";
361
+ }>;
362
+ stage: z.ZodEnum<{
363
+ manual: "manual";
364
+ initial: "initial";
365
+ reminder: "reminder";
366
+ }>;
367
+ paymentSessionTarget: z.ZodNullable<z.ZodEnum<{
368
+ invoice: "invoice";
369
+ schedule: "schedule";
370
+ }>>;
371
+ documentType: z.ZodNullable<z.ZodEnum<{
372
+ invoice: "invoice";
373
+ proforma: "proforma";
374
+ }>>;
375
+ willCreateDefaultPaymentPlan: z.ZodBoolean;
376
+ selectedSchedule: z.ZodNullable<z.ZodObject<{
377
+ id: z.ZodString;
378
+ bookingId: z.ZodString;
379
+ bookingItemId: z.ZodNullable<z.ZodString>;
380
+ scheduleType: z.ZodString;
381
+ status: z.ZodString;
382
+ dueDate: z.ZodString;
383
+ currency: z.ZodString;
384
+ amountCents: z.ZodNumber;
385
+ notes: z.ZodNullable<z.ZodString>;
386
+ }, z.core.$strip>>;
387
+ selectedInvoice: z.ZodNullable<z.ZodObject<{
388
+ id: z.ZodString;
389
+ invoiceNumber: z.ZodString;
390
+ invoiceType: z.ZodString;
391
+ bookingId: z.ZodString;
392
+ personId: z.ZodNullable<z.ZodString>;
393
+ organizationId: z.ZodNullable<z.ZodString>;
394
+ status: z.ZodString;
395
+ currency: z.ZodString;
396
+ totalCents: z.ZodNumber;
397
+ paidCents: z.ZodNumber;
398
+ balanceDueCents: z.ZodNumber;
399
+ issueDate: z.ZodString;
400
+ dueDate: z.ZodString;
401
+ notes: z.ZodNullable<z.ZodString>;
402
+ createdAt: z.ZodString;
403
+ updatedAt: z.ZodString;
404
+ }, z.core.$strip>>;
405
+ amountCents: z.ZodNumber;
406
+ currency: z.ZodString;
407
+ recommendedAction: z.ZodEnum<{
408
+ none: "none";
409
+ create_bank_transfer_document: "create_bank_transfer_document";
410
+ create_payment_session: "create_payment_session";
411
+ create_invoice_then_payment_session: "create_invoice_then_payment_session";
412
+ }>;
413
+ }, z.core.$strip>;
414
+ invoice: z.ZodNullable<z.ZodObject<{
415
+ id: z.ZodString;
416
+ invoiceNumber: z.ZodString;
417
+ invoiceType: z.ZodString;
418
+ bookingId: z.ZodString;
419
+ personId: z.ZodNullable<z.ZodString>;
420
+ organizationId: z.ZodNullable<z.ZodString>;
421
+ status: z.ZodString;
422
+ currency: z.ZodString;
423
+ totalCents: z.ZodNumber;
424
+ paidCents: z.ZodNumber;
425
+ balanceDueCents: z.ZodNumber;
426
+ issueDate: z.ZodString;
427
+ dueDate: z.ZodString;
428
+ notes: z.ZodNullable<z.ZodString>;
429
+ createdAt: z.ZodString;
430
+ updatedAt: z.ZodString;
431
+ }, z.core.$strip>>;
432
+ paymentSession: z.ZodNullable<z.ZodObject<{
433
+ id: z.ZodString;
434
+ targetType: z.ZodEnum<{
435
+ other: "other";
436
+ booking: "booking";
437
+ order: "order";
438
+ invoice: "invoice";
439
+ booking_payment_schedule: "booking_payment_schedule";
440
+ booking_guarantee: "booking_guarantee";
441
+ }>;
442
+ targetId: z.ZodNullable<z.ZodString>;
443
+ bookingId: z.ZodNullable<z.ZodString>;
444
+ invoiceId: z.ZodNullable<z.ZodString>;
445
+ bookingPaymentScheduleId: z.ZodNullable<z.ZodString>;
446
+ bookingGuaranteeId: z.ZodNullable<z.ZodString>;
447
+ status: z.ZodEnum<{
448
+ expired: "expired";
449
+ cancelled: "cancelled";
450
+ pending: "pending";
451
+ failed: "failed";
452
+ paid: "paid";
453
+ requires_redirect: "requires_redirect";
454
+ processing: "processing";
455
+ authorized: "authorized";
456
+ }>;
457
+ provider: z.ZodNullable<z.ZodString>;
458
+ providerSessionId: z.ZodNullable<z.ZodString>;
459
+ providerPaymentId: z.ZodNullable<z.ZodString>;
460
+ externalReference: z.ZodNullable<z.ZodString>;
461
+ clientReference: z.ZodNullable<z.ZodString>;
462
+ currency: z.ZodString;
463
+ amountCents: z.ZodNumber;
464
+ paymentMethod: z.ZodNullable<z.ZodEnum<{
465
+ other: "other";
466
+ voucher: "voucher";
467
+ wallet: "wallet";
468
+ bank_transfer: "bank_transfer";
469
+ credit_card: "credit_card";
470
+ debit_card: "debit_card";
471
+ cash: "cash";
472
+ cheque: "cheque";
473
+ direct_bill: "direct_bill";
474
+ }>>;
475
+ payerEmail: z.ZodNullable<z.ZodString>;
476
+ payerName: z.ZodNullable<z.ZodString>;
477
+ redirectUrl: z.ZodNullable<z.ZodString>;
478
+ returnUrl: z.ZodNullable<z.ZodString>;
479
+ cancelUrl: z.ZodNullable<z.ZodString>;
480
+ expiresAt: z.ZodNullable<z.ZodString>;
481
+ completedAt: z.ZodNullable<z.ZodString>;
482
+ failureCode: z.ZodNullable<z.ZodString>;
483
+ failureMessage: z.ZodNullable<z.ZodString>;
484
+ }, z.core.$strip>>;
485
+ invoiceNotification: z.ZodNullable<z.ZodObject<{
486
+ id: z.ZodString;
487
+ templateSlug: z.ZodNullable<z.ZodString>;
488
+ channel: z.ZodEnum<{
489
+ email: "email";
490
+ sms: "sms";
491
+ }>;
492
+ provider: z.ZodString;
493
+ status: z.ZodEnum<{
494
+ cancelled: "cancelled";
495
+ pending: "pending";
496
+ failed: "failed";
497
+ sent: "sent";
498
+ }>;
499
+ toAddress: z.ZodString;
500
+ subject: z.ZodNullable<z.ZodString>;
501
+ sentAt: z.ZodNullable<z.ZodString>;
502
+ failedAt: z.ZodNullable<z.ZodString>;
503
+ errorMessage: z.ZodNullable<z.ZodString>;
504
+ }, z.core.$strip>>;
505
+ paymentSessionNotification: z.ZodNullable<z.ZodObject<{
506
+ id: z.ZodString;
507
+ templateSlug: z.ZodNullable<z.ZodString>;
508
+ channel: z.ZodEnum<{
509
+ email: "email";
510
+ sms: "sms";
511
+ }>;
512
+ provider: z.ZodString;
513
+ status: z.ZodEnum<{
514
+ cancelled: "cancelled";
515
+ pending: "pending";
516
+ failed: "failed";
517
+ sent: "sent";
518
+ }>;
519
+ toAddress: z.ZodString;
520
+ subject: z.ZodNullable<z.ZodString>;
521
+ sentAt: z.ZodNullable<z.ZodString>;
522
+ failedAt: z.ZodNullable<z.ZodString>;
523
+ errorMessage: z.ZodNullable<z.ZodString>;
524
+ }, z.core.$strip>>;
525
+ bankTransferInstructions: z.ZodNullable<z.ZodObject<{
526
+ provider: z.ZodNullable<z.ZodString>;
527
+ invoiceId: z.ZodString;
528
+ invoiceNumber: z.ZodString;
529
+ documentType: z.ZodEnum<{
530
+ invoice: "invoice";
531
+ proforma: "proforma";
532
+ }>;
533
+ amountCents: z.ZodNumber;
534
+ currency: z.ZodString;
535
+ dueDate: z.ZodNullable<z.ZodString>;
536
+ beneficiary: z.ZodString;
537
+ iban: z.ZodString;
538
+ bankName: z.ZodNullable<z.ZodString>;
539
+ notes: z.ZodNullable<z.ZodString>;
540
+ }, z.core.$strip>>;
541
+ providerStart: z.ZodNullable<z.ZodObject<{
542
+ provider: z.ZodString;
543
+ paymentSessionId: z.ZodString;
544
+ redirectUrl: z.ZodNullable<z.ZodString>;
545
+ externalReference: z.ZodNullable<z.ZodString>;
546
+ providerSessionId: z.ZodNullable<z.ZodString>;
547
+ providerPaymentId: z.ZodNullable<z.ZodString>;
548
+ response: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
549
+ }, z.core.$strip>>;
550
+ }, z.core.$strip>;
551
+ export declare const checkoutReminderRunListQuerySchema: z.ZodObject<{
552
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
553
+ offset: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
554
+ status: z.ZodOptional<z.ZodEnum<{
555
+ failed: "failed";
556
+ sent: "sent";
557
+ processing: "processing";
558
+ skipped: "skipped";
559
+ }>>;
560
+ }, z.core.$strip>;
561
+ export declare const checkoutReminderRunSchema: z.ZodObject<{
562
+ id: z.ZodString;
563
+ reminderRuleId: z.ZodString;
564
+ reminderRuleSlug: z.ZodNullable<z.ZodString>;
565
+ reminderRuleName: z.ZodNullable<z.ZodString>;
566
+ targetType: z.ZodEnum<{
567
+ invoice: "invoice";
568
+ booking_payment_schedule: "booking_payment_schedule";
569
+ }>;
570
+ targetId: z.ZodString;
571
+ bookingId: z.ZodNullable<z.ZodString>;
572
+ paymentSessionId: z.ZodNullable<z.ZodString>;
573
+ notificationDeliveryId: z.ZodNullable<z.ZodString>;
574
+ status: z.ZodEnum<{
575
+ failed: "failed";
576
+ sent: "sent";
577
+ processing: "processing";
578
+ skipped: "skipped";
579
+ }>;
580
+ deliveryStatus: z.ZodNullable<z.ZodEnum<{
581
+ cancelled: "cancelled";
582
+ pending: "pending";
583
+ failed: "failed";
584
+ sent: "sent";
585
+ }>>;
586
+ channel: z.ZodNullable<z.ZodEnum<{
587
+ email: "email";
588
+ sms: "sms";
589
+ }>>;
590
+ provider: z.ZodNullable<z.ZodString>;
591
+ recipient: z.ZodNullable<z.ZodString>;
592
+ scheduledFor: z.ZodString;
593
+ processedAt: z.ZodString;
594
+ errorMessage: z.ZodNullable<z.ZodString>;
595
+ relativeDaysFromDueDate: z.ZodNullable<z.ZodNumber>;
596
+ createdAt: z.ZodString;
597
+ }, z.core.$strip>;
598
+ export declare const checkoutReminderRunListResponseSchema: z.ZodObject<{
599
+ data: z.ZodArray<z.ZodObject<{
600
+ id: z.ZodString;
601
+ reminderRuleId: z.ZodString;
602
+ reminderRuleSlug: z.ZodNullable<z.ZodString>;
603
+ reminderRuleName: z.ZodNullable<z.ZodString>;
604
+ targetType: z.ZodEnum<{
605
+ invoice: "invoice";
606
+ booking_payment_schedule: "booking_payment_schedule";
607
+ }>;
608
+ targetId: z.ZodString;
609
+ bookingId: z.ZodNullable<z.ZodString>;
610
+ paymentSessionId: z.ZodNullable<z.ZodString>;
611
+ notificationDeliveryId: z.ZodNullable<z.ZodString>;
612
+ status: z.ZodEnum<{
613
+ failed: "failed";
614
+ sent: "sent";
615
+ processing: "processing";
616
+ skipped: "skipped";
617
+ }>;
618
+ deliveryStatus: z.ZodNullable<z.ZodEnum<{
619
+ cancelled: "cancelled";
620
+ pending: "pending";
621
+ failed: "failed";
622
+ sent: "sent";
623
+ }>>;
624
+ channel: z.ZodNullable<z.ZodEnum<{
625
+ email: "email";
626
+ sms: "sms";
627
+ }>>;
628
+ provider: z.ZodNullable<z.ZodString>;
629
+ recipient: z.ZodNullable<z.ZodString>;
630
+ scheduledFor: z.ZodString;
631
+ processedAt: z.ZodString;
632
+ errorMessage: z.ZodNullable<z.ZodString>;
633
+ relativeDaysFromDueDate: z.ZodNullable<z.ZodNumber>;
634
+ createdAt: z.ZodString;
635
+ }, z.core.$strip>>;
636
+ total: z.ZodNumber;
637
+ limit: z.ZodNumber;
638
+ offset: z.ZodNumber;
639
+ }, z.core.$strip>;
191
640
  export type PreviewCheckoutCollectionInput = z.infer<typeof previewCheckoutCollectionSchema>;
192
641
  export type InitiateCheckoutCollectionInput = z.infer<typeof initiateCheckoutCollectionSchema>;
642
+ export type CheckoutCollectionPlanRecord = z.infer<typeof checkoutCollectionPlanSchema>;
643
+ export type InitiatedCheckoutCollectionRecord = z.infer<typeof initiatedCheckoutCollectionSchema>;
644
+ export type CheckoutProviderStartInput = z.infer<typeof checkoutProviderStartInputSchema>;
645
+ export type CheckoutBankTransferInstructionsRecord = z.infer<typeof checkoutBankTransferInstructionsSchema>;
646
+ export type CheckoutProviderStartResultRecord = z.infer<typeof checkoutProviderStartResultSchema>;
647
+ export type CheckoutReminderRunListQuery = z.infer<typeof checkoutReminderRunListQuerySchema>;
648
+ export type CheckoutReminderRunRecord = z.infer<typeof checkoutReminderRunSchema>;
193
649
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,8BAA8B;;;EAAoC,CAAA;AAC/E,eAAO,MAAM,6BAA6B;;;;EAA4C,CAAA;AACtF,eAAO,MAAM,kCAAkC;;;EAAkC,CAAA;AACjF,eAAO,MAAM,iCAAiC;;;EAAkC,CAAA;AAIhF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQ1C,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAO3C,CAAA;AAEF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAC5F,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,8BAA8B;;;EAAoC,CAAA;AAC/E,eAAO,MAAM,6BAA6B;;;;EAA4C,CAAA;AACtF,eAAO,MAAM,kCAAkC;;;EAAkC,CAAA;AACjF,eAAO,MAAM,iCAAiC;;;EAAkC,CAAA;AAChF,eAAO,MAAM,gCAAgC;;;iBAG3C,CAAA;AAQF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS1C,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQ3C,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;iBAU3C,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAiB1C,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;iBAW7C,CAAA;AAEF,eAAO,MAAM,sCAAsC;;;;;;;;;;;;;;;iBAYjD,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;iBAQ5C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBvC,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQ5C,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;iBAE7C,CAAA;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoBpC,CAAA;AAEF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKhD,CAAA;AAEF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAA;AAC5F,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAC9F,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AACvF,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAA;AACjG,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AACzF,MAAM,MAAM,sCAAsC,GAAG,CAAC,CAAC,KAAK,CAC1D,OAAO,sCAAsC,CAC9C,CAAA;AACD,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAA;AACjG,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAA;AAC7F,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA"}
@@ -1,16 +1,25 @@
1
- import { applyDefaultBookingPaymentPlanSchema, createPaymentSessionFromInvoiceSchema, createPaymentSessionFromScheduleSchema, } from "@voyantjs/finance";
2
- import { sendInvoiceNotificationSchema, sendPaymentSessionNotificationSchema, } from "@voyantjs/notifications";
1
+ import { applyDefaultBookingPaymentPlanSchema, createPaymentSessionFromInvoiceSchema, createPaymentSessionFromScheduleSchema, publicPaymentSessionSchema, } from "@voyantjs/finance";
2
+ import { notificationChannelSchema, notificationDeliveryStatusSchema, notificationReminderRunStatusSchema, notificationReminderTargetTypeSchema, sendInvoiceNotificationSchema, sendPaymentSessionNotificationSchema, } from "@voyantjs/notifications";
3
3
  import { z } from "zod";
4
4
  export const checkoutCollectionMethodSchema = z.enum(["card", "bank_transfer"]);
5
5
  export const checkoutCollectionStageSchema = z.enum(["initial", "reminder", "manual"]);
6
6
  export const checkoutPaymentSessionTargetSchema = z.enum(["schedule", "invoice"]);
7
7
  export const checkoutInvoiceDocumentTypeSchema = z.enum(["proforma", "invoice"]);
8
+ export const checkoutProviderStartInputSchema = z.object({
9
+ provider: z.string().min(1).max(255),
10
+ payload: z.record(z.string(), z.unknown()).optional().nullable(),
11
+ });
8
12
  const planOverrideSchema = applyDefaultBookingPaymentPlanSchema.partial();
13
+ const paginationSchema = z.object({
14
+ limit: z.coerce.number().int().min(1).max(100).default(20),
15
+ offset: z.coerce.number().int().min(0).default(0),
16
+ });
9
17
  export const previewCheckoutCollectionSchema = z.object({
10
18
  method: checkoutCollectionMethodSchema,
11
19
  stage: checkoutCollectionStageSchema.default("initial"),
12
20
  scheduleId: z.string().optional(),
13
21
  invoiceId: z.string().optional(),
22
+ amountCents: z.number().int().min(1).optional(),
14
23
  ensureDefaultPaymentPlan: z.boolean().default(true),
15
24
  paymentSessionTarget: checkoutPaymentSessionTargetSchema.optional(),
16
25
  paymentPlan: planOverrideSchema.optional(),
@@ -21,5 +30,126 @@ export const initiateCheckoutCollectionSchema = previewCheckoutCollectionSchema.
21
30
  .optional(),
22
31
  paymentSessionNotification: sendPaymentSessionNotificationSchema.optional(),
23
32
  invoiceNotification: sendInvoiceNotificationSchema.optional(),
33
+ startProvider: checkoutProviderStartInputSchema.optional(),
24
34
  notes: z.string().optional().nullable(),
25
35
  });
36
+ export const checkoutCollectionScheduleSchema = z.object({
37
+ id: z.string(),
38
+ bookingId: z.string(),
39
+ bookingItemId: z.string().nullable(),
40
+ scheduleType: z.string(),
41
+ status: z.string(),
42
+ dueDate: z.string(),
43
+ currency: z.string(),
44
+ amountCents: z.number().int(),
45
+ notes: z.string().nullable(),
46
+ });
47
+ export const checkoutCollectionInvoiceSchema = z.object({
48
+ id: z.string(),
49
+ invoiceNumber: z.string(),
50
+ invoiceType: z.string(),
51
+ bookingId: z.string(),
52
+ personId: z.string().nullable(),
53
+ organizationId: z.string().nullable(),
54
+ status: z.string(),
55
+ currency: z.string(),
56
+ totalCents: z.number().int(),
57
+ paidCents: z.number().int(),
58
+ balanceDueCents: z.number().int(),
59
+ issueDate: z.string(),
60
+ dueDate: z.string(),
61
+ notes: z.string().nullable(),
62
+ createdAt: z.string(),
63
+ updatedAt: z.string(),
64
+ });
65
+ export const checkoutNotificationDeliverySchema = z.object({
66
+ id: z.string(),
67
+ templateSlug: z.string().nullable(),
68
+ channel: notificationChannelSchema,
69
+ provider: z.string(),
70
+ status: notificationDeliveryStatusSchema,
71
+ toAddress: z.string(),
72
+ subject: z.string().nullable(),
73
+ sentAt: z.string().nullable(),
74
+ failedAt: z.string().nullable(),
75
+ errorMessage: z.string().nullable(),
76
+ });
77
+ export const checkoutBankTransferInstructionsSchema = z.object({
78
+ provider: z.string().nullable(),
79
+ invoiceId: z.string(),
80
+ invoiceNumber: z.string(),
81
+ documentType: checkoutInvoiceDocumentTypeSchema,
82
+ amountCents: z.number().int(),
83
+ currency: z.string(),
84
+ dueDate: z.string().nullable(),
85
+ beneficiary: z.string(),
86
+ iban: z.string(),
87
+ bankName: z.string().nullable(),
88
+ notes: z.string().nullable(),
89
+ });
90
+ export const checkoutProviderStartResultSchema = z.object({
91
+ provider: z.string(),
92
+ paymentSessionId: z.string(),
93
+ redirectUrl: z.string().nullable(),
94
+ externalReference: z.string().nullable(),
95
+ providerSessionId: z.string().nullable(),
96
+ providerPaymentId: z.string().nullable(),
97
+ response: z.record(z.string(), z.unknown()).nullable(),
98
+ });
99
+ export const checkoutCollectionPlanSchema = z.object({
100
+ bookingId: z.string(),
101
+ method: checkoutCollectionMethodSchema,
102
+ stage: checkoutCollectionStageSchema,
103
+ paymentSessionTarget: checkoutPaymentSessionTargetSchema.nullable(),
104
+ documentType: checkoutInvoiceDocumentTypeSchema.nullable(),
105
+ willCreateDefaultPaymentPlan: z.boolean(),
106
+ selectedSchedule: checkoutCollectionScheduleSchema.nullable(),
107
+ selectedInvoice: checkoutCollectionInvoiceSchema.nullable(),
108
+ amountCents: z.number().int(),
109
+ currency: z.string(),
110
+ recommendedAction: z.enum([
111
+ "create_bank_transfer_document",
112
+ "create_payment_session",
113
+ "create_invoice_then_payment_session",
114
+ "none",
115
+ ]),
116
+ });
117
+ export const initiatedCheckoutCollectionSchema = z.object({
118
+ plan: checkoutCollectionPlanSchema,
119
+ invoice: checkoutCollectionInvoiceSchema.nullable(),
120
+ paymentSession: publicPaymentSessionSchema.nullable(),
121
+ invoiceNotification: checkoutNotificationDeliverySchema.nullable(),
122
+ paymentSessionNotification: checkoutNotificationDeliverySchema.nullable(),
123
+ bankTransferInstructions: checkoutBankTransferInstructionsSchema.nullable(),
124
+ providerStart: checkoutProviderStartResultSchema.nullable(),
125
+ });
126
+ export const checkoutReminderRunListQuerySchema = paginationSchema.extend({
127
+ status: notificationReminderRunStatusSchema.optional(),
128
+ });
129
+ export const checkoutReminderRunSchema = z.object({
130
+ id: z.string(),
131
+ reminderRuleId: z.string(),
132
+ reminderRuleSlug: z.string().nullable(),
133
+ reminderRuleName: z.string().nullable(),
134
+ targetType: notificationReminderTargetTypeSchema,
135
+ targetId: z.string(),
136
+ bookingId: z.string().nullable(),
137
+ paymentSessionId: z.string().nullable(),
138
+ notificationDeliveryId: z.string().nullable(),
139
+ status: notificationReminderRunStatusSchema,
140
+ deliveryStatus: notificationDeliveryStatusSchema.nullable(),
141
+ channel: notificationChannelSchema.nullable(),
142
+ provider: z.string().nullable(),
143
+ recipient: z.string().nullable(),
144
+ scheduledFor: z.string(),
145
+ processedAt: z.string(),
146
+ errorMessage: z.string().nullable(),
147
+ relativeDaysFromDueDate: z.number().int().nullable(),
148
+ createdAt: z.string(),
149
+ });
150
+ export const checkoutReminderRunListResponseSchema = z.object({
151
+ data: z.array(checkoutReminderRunSchema),
152
+ total: z.number().int(),
153
+ limit: z.number().int(),
154
+ offset: z.number().int(),
155
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/checkout",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "license": "FSL-1.1-Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,11 +25,11 @@
25
25
  "drizzle-orm": "^0.45.2",
26
26
  "hono": "^4.12.10",
27
27
  "zod": "^4.3.6",
28
- "@voyantjs/bookings": "0.3.0",
29
- "@voyantjs/core": "0.3.0",
30
- "@voyantjs/finance": "0.3.0",
31
- "@voyantjs/hono": "0.3.0",
32
- "@voyantjs/notifications": "0.3.0"
28
+ "@voyantjs/bookings": "0.4.0",
29
+ "@voyantjs/core": "0.4.0",
30
+ "@voyantjs/finance": "0.4.0",
31
+ "@voyantjs/hono": "0.4.0",
32
+ "@voyantjs/notifications": "0.4.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "^6.0.2",