@voyantjs/finance 0.52.1 → 0.52.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/action-ledger-drift.d.ts +29 -0
  2. package/dist/action-ledger-drift.d.ts.map +1 -0
  3. package/dist/action-ledger-drift.js +163 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -0
  6. package/dist/routes-action-ledger.d.ts +181 -0
  7. package/dist/routes-action-ledger.d.ts.map +1 -0
  8. package/dist/routes-action-ledger.js +142 -0
  9. package/dist/routes-documents.d.ts +8 -8
  10. package/dist/routes-public.d.ts +48 -48
  11. package/dist/routes-settlement.d.ts +1 -1
  12. package/dist/routes-shared.d.ts +12 -0
  13. package/dist/routes-shared.d.ts.map +1 -1
  14. package/dist/routes.d.ts +288 -217
  15. package/dist/routes.d.ts.map +1 -1
  16. package/dist/routes.js +280 -46
  17. package/dist/schema.d.ts +22 -22
  18. package/dist/service-action-ledger-accounting.d.ts +77 -0
  19. package/dist/service-action-ledger-accounting.d.ts.map +1 -0
  20. package/dist/service-action-ledger-accounting.js +307 -0
  21. package/dist/service-action-ledger-booking-payments.d.ts +48 -0
  22. package/dist/service-action-ledger-booking-payments.d.ts.map +1 -0
  23. package/dist/service-action-ledger-booking-payments.js +178 -0
  24. package/dist/service-action-ledger-payment-authorizations.d.ts +48 -0
  25. package/dist/service-action-ledger-payment-authorizations.d.ts.map +1 -0
  26. package/dist/service-action-ledger-payment-authorizations.js +209 -0
  27. package/dist/service-action-ledger-payment-sessions.d.ts +83 -0
  28. package/dist/service-action-ledger-payment-sessions.d.ts.map +1 -0
  29. package/dist/service-action-ledger-payment-sessions.js +294 -0
  30. package/dist/service-action-ledger-supplier-payments.d.ts +21 -0
  31. package/dist/service-action-ledger-supplier-payments.d.ts.map +1 -0
  32. package/dist/service-action-ledger-supplier-payments.js +70 -0
  33. package/dist/service-action-ledger.d.ts +6 -0
  34. package/dist/service-action-ledger.d.ts.map +1 -0
  35. package/dist/service-action-ledger.js +5 -0
  36. package/dist/service-booking-create.d.ts +50 -8
  37. package/dist/service-booking-create.d.ts.map +1 -1
  38. package/dist/service-booking-create.js +58 -1
  39. package/dist/service-bookings-dual-create.d.ts +50 -8
  40. package/dist/service-bookings-dual-create.d.ts.map +1 -1
  41. package/dist/service-issue.d.ts +42 -12
  42. package/dist/service-issue.d.ts.map +1 -1
  43. package/dist/service-issue.js +141 -4
  44. package/dist/service-public.d.ts +13 -13
  45. package/dist/service-vouchers.d.ts +10 -10
  46. package/dist/service.d.ts +291 -279
  47. package/dist/service.d.ts.map +1 -1
  48. package/dist/service.js +753 -238
  49. package/dist/validation-billing.d.ts +37 -37
  50. package/dist/validation-payments.d.ts +102 -102
  51. package/dist/validation-public.d.ts +45 -45
  52. package/dist/validation-shared.d.ts +32 -32
  53. package/dist/validation-vouchers.d.ts +2 -2
  54. package/package.json +13 -7
package/dist/service.js CHANGED
@@ -1,9 +1,12 @@
1
+ import { appendActionLedgerMutation, } from "@voyantjs/action-ledger";
1
2
  import { bookingItems, bookings } from "@voyantjs/bookings/schema";
2
3
  import { renderStructuredTemplate } from "@voyantjs/utils/template-renderer";
3
4
  import { and, asc, desc, eq, gte, ilike, lte, ne, or, sql } from "drizzle-orm";
4
5
  import { bookingGuarantees, bookingItemCommissions, bookingItemTaxLines, bookingPaymentSchedules, creditNoteLineItems, creditNotes, financeNotes, invoiceAttachments, invoiceExternalRefs, invoiceLineItems, invoiceNumberSeries, invoiceRenditions, invoices, invoiceTemplates, paymentAuthorizations, paymentCaptures, paymentInstruments, paymentSessions, payments, supplierPayments, taxClasses, taxPolicyProfiles, taxPolicyRules, taxRegimes, } from "./schema.js";
6
+ import { buildBookingGuaranteeCreateActionLedgerInput, buildBookingGuaranteeDeleteActionLedgerInput, buildBookingGuaranteeUpdateActionLedgerInput, buildBookingPaymentScheduleCreateActionLedgerInput, buildBookingPaymentScheduleDeleteActionLedgerInput, buildBookingPaymentScheduleUpdateActionLedgerInput, buildCreditNoteCreationActionLedgerInput, buildCreditNoteLineItemCreateActionLedgerInput, buildCreditNoteUpdateActionLedgerInput, buildInvoiceDeleteActionLedgerInput, buildInvoiceLineItemCreateActionLedgerInput, buildInvoiceLineItemDeleteActionLedgerInput, buildInvoiceLineItemUpdateActionLedgerInput, buildInvoiceUpdateActionLedgerInput, buildPaymentAuthorizationCreateActionLedgerInput, buildPaymentAuthorizationDeleteActionLedgerInput, buildPaymentAuthorizationUpdateActionLedgerInput, buildPaymentCaptureCreateActionLedgerInput, buildPaymentCaptureDeleteActionLedgerInput, buildPaymentCaptureUpdateActionLedgerInput, buildPaymentInstrumentCreateActionLedgerInput, buildPaymentInstrumentDeleteActionLedgerInput, buildPaymentInstrumentUpdateActionLedgerInput, buildPaymentSessionCancelledActionLedgerInput, buildPaymentSessionCompletionActionLedgerInput, buildPaymentSessionCreateActionLedgerInput, buildPaymentSessionExpiredActionLedgerInput, buildPaymentSessionFailedActionLedgerInput, buildPaymentSessionRequiresRedirectActionLedgerInput, buildPaymentSessionUpdateActionLedgerInput, buildRecordPaymentActionLedgerInput, buildSupplierPaymentCreateActionLedgerInput, buildSupplierPaymentUpdateActionLedgerInput, } from "./service-action-ledger.js";
5
7
  import { getFinanceAggregates } from "./service-aggregates.js";
6
8
  import { vouchersService } from "./service-vouchers.js";
9
+ export { buildBookingGuaranteeCreateActionLedgerInput, buildBookingGuaranteeDeleteActionLedgerInput, buildBookingGuaranteeUpdateActionLedgerInput, buildBookingPaymentScheduleCreateActionLedgerInput, buildBookingPaymentScheduleDeleteActionLedgerInput, buildBookingPaymentScheduleUpdateActionLedgerInput, buildCreditNoteCreationActionLedgerInput, buildCreditNoteLineItemCreateActionLedgerInput, buildCreditNoteUpdateActionLedgerInput, buildInvoiceDeleteActionLedgerInput, buildInvoiceIssuedActionLedgerInput, buildInvoiceLineItemCreateActionLedgerInput, buildInvoiceLineItemDeleteActionLedgerInput, buildInvoiceLineItemUpdateActionLedgerInput, buildInvoiceUpdateActionLedgerInput, buildPaymentAuthorizationCreateActionLedgerInput, buildPaymentAuthorizationDeleteActionLedgerInput, buildPaymentAuthorizationUpdateActionLedgerInput, buildPaymentCaptureCreateActionLedgerInput, buildPaymentCaptureDeleteActionLedgerInput, buildPaymentCaptureUpdateActionLedgerInput, buildPaymentInstrumentCreateActionLedgerInput, buildPaymentInstrumentDeleteActionLedgerInput, buildPaymentInstrumentUpdateActionLedgerInput, buildPaymentSessionCancelledActionLedgerInput, buildPaymentSessionCompletionActionLedgerInput, buildPaymentSessionCreateActionLedgerInput, buildPaymentSessionExpiredActionLedgerInput, buildPaymentSessionFailedActionLedgerInput, buildPaymentSessionRequiresRedirectActionLedgerInput, buildPaymentSessionUpdateActionLedgerInput, buildRecordPaymentActionLedgerInput, buildSupplierPaymentCreateActionLedgerInput, buildSupplierPaymentUpdateActionLedgerInput, } from "./service-action-ledger.js";
7
10
  export class PaymentValidationError extends Error {
8
11
  status = 400;
9
12
  code = "invalid_request";
@@ -136,6 +139,24 @@ export function buildPaymentCompletedEvent(session) {
136
139
  provider: session.provider,
137
140
  };
138
141
  }
142
+ /**
143
+ * Normalize `db.execute(sql)` results across drizzle drivers.
144
+ * `drizzle-orm/postgres-js` returns rows directly (an array), while
145
+ * `drizzle-orm/node-postgres` (used by the operator template against a
146
+ * local pg server) and `drizzle-orm/neon-serverless` return pg's
147
+ * `QueryResult<T>` wrapper with `.rows`. Casting to `Array<T>` and
148
+ * calling `.map` blows up under the wrapper shape — surface the rows
149
+ * regardless of which driver is bound.
150
+ */
151
+ function toRows(result) {
152
+ if (Array.isArray(result))
153
+ return result;
154
+ if (result && typeof result === "object" && "rows" in result) {
155
+ const rows = result.rows;
156
+ return Array.isArray(rows) ? rows : [];
157
+ }
158
+ return [];
159
+ }
139
160
  function mapRawPayment(row) {
140
161
  // Person display name: "First Last", trimmed. Falls back to null when both
141
162
  // halves are missing so the UI can swap to organization or hide the field.
@@ -235,19 +256,59 @@ export const financeService = {
235
256
  .limit(1);
236
257
  return row ?? null;
237
258
  },
238
- async createPaymentInstrument(db, data) {
239
- const [row] = await db.insert(paymentInstruments).values(data).returning();
259
+ async createPaymentInstrument(db, data, runtime = {}) {
260
+ const createInstrument = (writer) => writer.insert(paymentInstruments).values(data).returning();
261
+ const actionLedgerContext = runtime.actionLedgerContext;
262
+ if (actionLedgerContext) {
263
+ const [row] = await db.transaction(async (tx) => {
264
+ const created = await createInstrument(tx);
265
+ if (created[0]) {
266
+ await appendActionLedgerMutation(tx, buildPaymentInstrumentCreateActionLedgerInput(actionLedgerContext, { instrument: created[0] }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
267
+ }
268
+ return created;
269
+ });
270
+ return row ?? null;
271
+ }
272
+ const [row] = await createInstrument(db);
240
273
  return row ?? null;
241
274
  },
242
- async updatePaymentInstrument(db, id, data) {
243
- const [row] = await db
275
+ async updatePaymentInstrument(db, id, data, runtime = {}) {
276
+ const updateInstrument = (writer) => writer
244
277
  .update(paymentInstruments)
245
278
  .set({ ...data, updatedAt: new Date() })
246
279
  .where(eq(paymentInstruments.id, id))
247
280
  .returning();
281
+ const actionLedgerContext = runtime.actionLedgerContext;
282
+ if (actionLedgerContext) {
283
+ const [row] = await db.transaction(async (tx) => {
284
+ const updated = await updateInstrument(tx);
285
+ if (updated[0]) {
286
+ await appendActionLedgerMutation(tx, buildPaymentInstrumentUpdateActionLedgerInput(actionLedgerContext, { instrument: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
287
+ }
288
+ return updated;
289
+ });
290
+ return row ?? null;
291
+ }
292
+ const [row] = await updateInstrument(db);
248
293
  return row ?? null;
249
294
  },
250
- async deletePaymentInstrument(db, id) {
295
+ async deletePaymentInstrument(db, id, runtime = {}) {
296
+ const actionLedgerContext = runtime.actionLedgerContext;
297
+ if (actionLedgerContext) {
298
+ return db.transaction(async (tx) => {
299
+ const [existing] = await tx
300
+ .select()
301
+ .from(paymentInstruments)
302
+ .where(eq(paymentInstruments.id, id))
303
+ .limit(1);
304
+ if (!existing) {
305
+ return null;
306
+ }
307
+ await tx.delete(paymentInstruments).where(eq(paymentInstruments.id, id));
308
+ await appendActionLedgerMutation(tx, buildPaymentInstrumentDeleteActionLedgerInput(actionLedgerContext, { instrument: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
309
+ return { id: existing.id };
310
+ });
311
+ }
251
312
  const [row] = await db
252
313
  .delete(paymentInstruments)
253
314
  .where(eq(paymentInstruments.id, id))
@@ -302,7 +363,7 @@ export const financeService = {
302
363
  const [row] = await db.select().from(paymentSessions).where(eq(paymentSessions.id, id)).limit(1);
303
364
  return row ?? null;
304
365
  },
305
- async createPaymentSession(db, data) {
366
+ async createPaymentSession(db, data, runtime = {}) {
306
367
  if (data.idempotencyKey) {
307
368
  const [existing] = await db
308
369
  .select()
@@ -314,7 +375,7 @@ export const financeService = {
314
375
  }
315
376
  }
316
377
  const target = derivePaymentSessionTarget(data);
317
- const [row] = await db
378
+ const createSession = (writer) => writer
318
379
  .insert(paymentSessions)
319
380
  .values({
320
381
  ...data,
@@ -330,11 +391,23 @@ export const financeService = {
330
391
  expiresAt: toTimestamp(data.expiresAt),
331
392
  })
332
393
  .returning();
394
+ const actionLedgerContext = runtime.actionLedgerContext;
395
+ if (actionLedgerContext) {
396
+ const [row] = await db.transaction(async (tx) => {
397
+ const created = await createSession(tx);
398
+ if (created[0]) {
399
+ await appendActionLedgerMutation(tx, await buildPaymentSessionCreateActionLedgerInput(actionLedgerContext, { session: created[0] }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
400
+ }
401
+ return created;
402
+ });
403
+ return row ?? null;
404
+ }
405
+ const [row] = await createSession(db);
333
406
  return row ?? null;
334
407
  },
335
- async updatePaymentSession(db, id, data) {
408
+ async updatePaymentSession(db, id, data, runtime = {}) {
336
409
  const target = derivePaymentSessionTarget(data);
337
- const [row] = await db
410
+ const updateSession = (writer) => writer
338
411
  .update(paymentSessions)
339
412
  .set({
340
413
  ...data,
@@ -354,10 +427,22 @@ export const financeService = {
354
427
  })
355
428
  .where(eq(paymentSessions.id, id))
356
429
  .returning();
430
+ const actionLedgerContext = runtime.actionLedgerContext;
431
+ if (actionLedgerContext) {
432
+ const [row] = await db.transaction(async (tx) => {
433
+ const updated = await updateSession(tx);
434
+ if (updated[0]) {
435
+ await appendActionLedgerMutation(tx, buildPaymentSessionUpdateActionLedgerInput(actionLedgerContext, { session: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
436
+ }
437
+ return updated;
438
+ });
439
+ return row ?? null;
440
+ }
441
+ const [row] = await updateSession(db);
357
442
  return row ?? null;
358
443
  },
359
- async markPaymentSessionRequiresRedirect(db, id, data) {
360
- const [row] = await db
444
+ async markPaymentSessionRequiresRedirect(db, id, data, runtime = {}) {
445
+ const markRequiresRedirect = (writer) => writer
361
446
  .update(paymentSessions)
362
447
  .set({
363
448
  status: "requires_redirect",
@@ -377,10 +462,22 @@ export const financeService = {
377
462
  })
378
463
  .where(eq(paymentSessions.id, id))
379
464
  .returning();
465
+ const actionLedgerContext = runtime.actionLedgerContext;
466
+ if (actionLedgerContext) {
467
+ const [row] = await db.transaction(async (tx) => {
468
+ const updated = await markRequiresRedirect(tx);
469
+ if (updated[0]) {
470
+ await appendActionLedgerMutation(tx, buildPaymentSessionRequiresRedirectActionLedgerInput(actionLedgerContext, { session: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
471
+ }
472
+ return updated;
473
+ });
474
+ return row ?? null;
475
+ }
476
+ const [row] = await markRequiresRedirect(db);
380
477
  return row ?? null;
381
478
  },
382
- async failPaymentSession(db, id, data) {
383
- const [row] = await db
479
+ async failPaymentSession(db, id, data, runtime = {}) {
480
+ const failSession = (writer) => writer
384
481
  .update(paymentSessions)
385
482
  .set({
386
483
  status: "failed",
@@ -397,10 +494,22 @@ export const financeService = {
397
494
  })
398
495
  .where(eq(paymentSessions.id, id))
399
496
  .returning();
497
+ const actionLedgerContext = runtime.actionLedgerContext;
498
+ if (actionLedgerContext) {
499
+ const [row] = await db.transaction(async (tx) => {
500
+ const updated = await failSession(tx);
501
+ if (updated[0]) {
502
+ await appendActionLedgerMutation(tx, buildPaymentSessionFailedActionLedgerInput(actionLedgerContext, { session: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
503
+ }
504
+ return updated;
505
+ });
506
+ return row ?? null;
507
+ }
508
+ const [row] = await failSession(db);
400
509
  return row ?? null;
401
510
  },
402
- async cancelPaymentSession(db, id, data) {
403
- const [row] = await db
511
+ async cancelPaymentSession(db, id, data, runtime = {}) {
512
+ const cancelSession = (writer) => writer
404
513
  .update(paymentSessions)
405
514
  .set({
406
515
  status: "cancelled",
@@ -412,10 +521,22 @@ export const financeService = {
412
521
  })
413
522
  .where(eq(paymentSessions.id, id))
414
523
  .returning();
524
+ const actionLedgerContext = runtime.actionLedgerContext;
525
+ if (actionLedgerContext) {
526
+ const [row] = await db.transaction(async (tx) => {
527
+ const updated = await cancelSession(tx);
528
+ if (updated[0]) {
529
+ await appendActionLedgerMutation(tx, buildPaymentSessionCancelledActionLedgerInput(actionLedgerContext, { session: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
530
+ }
531
+ return updated;
532
+ });
533
+ return row ?? null;
534
+ }
535
+ const [row] = await cancelSession(db);
415
536
  return row ?? null;
416
537
  },
417
- async expirePaymentSession(db, id, data) {
418
- const [row] = await db
538
+ async expirePaymentSession(db, id, data, runtime = {}) {
539
+ const expireSession = (writer) => writer
419
540
  .update(paymentSessions)
420
541
  .set({
421
542
  status: "expired",
@@ -427,6 +548,18 @@ export const financeService = {
427
548
  })
428
549
  .where(eq(paymentSessions.id, id))
429
550
  .returning();
551
+ const actionLedgerContext = runtime.actionLedgerContext;
552
+ if (actionLedgerContext) {
553
+ const [row] = await db.transaction(async (tx) => {
554
+ const updated = await expireSession(tx);
555
+ if (updated[0]) {
556
+ await appendActionLedgerMutation(tx, buildPaymentSessionExpiredActionLedgerInput(actionLedgerContext, { session: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
557
+ }
558
+ return updated;
559
+ });
560
+ return row ?? null;
561
+ }
562
+ const [row] = await expireSession(db);
430
563
  return row ?? null;
431
564
  },
432
565
  async completePaymentSession(db, id, data, runtime = {}) {
@@ -610,6 +743,15 @@ export const financeService = {
610
743
  })
611
744
  .where(eq(paymentSessions.id, id))
612
745
  .returning();
746
+ if (updated && runtime.actionLedgerContext) {
747
+ await appendActionLedgerMutation(tx, await buildPaymentSessionCompletionActionLedgerInput(runtime.actionLedgerContext, {
748
+ session: updated,
749
+ status: data.status,
750
+ paymentId,
751
+ }, {
752
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
753
+ }));
754
+ }
613
755
  return {
614
756
  updated: updated ?? null,
615
757
  settlement: settlementForEmit,
@@ -674,8 +816,8 @@ export const financeService = {
674
816
  .limit(1);
675
817
  return row ?? null;
676
818
  },
677
- async createPaymentAuthorization(db, data) {
678
- const [row] = await db
819
+ async createPaymentAuthorization(db, data, runtime = {}) {
820
+ const createAuthorization = (writer) => writer
679
821
  .insert(paymentAuthorizations)
680
822
  .values({
681
823
  ...data,
@@ -684,10 +826,22 @@ export const financeService = {
684
826
  voidedAt: toTimestamp(data.voidedAt),
685
827
  })
686
828
  .returning();
829
+ const actionLedgerContext = runtime.actionLedgerContext;
830
+ if (actionLedgerContext) {
831
+ const [row] = await db.transaction(async (tx) => {
832
+ const created = await createAuthorization(tx);
833
+ if (created[0]) {
834
+ await appendActionLedgerMutation(tx, await buildPaymentAuthorizationCreateActionLedgerInput(actionLedgerContext, { authorization: created[0] }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
835
+ }
836
+ return created;
837
+ });
838
+ return row ?? null;
839
+ }
840
+ const [row] = await createAuthorization(db);
687
841
  return row ?? null;
688
842
  },
689
- async updatePaymentAuthorization(db, id, data) {
690
- const [row] = await db
843
+ async updatePaymentAuthorization(db, id, data, runtime = {}) {
844
+ const updateAuthorization = (writer) => writer
691
845
  .update(paymentAuthorizations)
692
846
  .set({
693
847
  ...data,
@@ -698,9 +852,37 @@ export const financeService = {
698
852
  })
699
853
  .where(eq(paymentAuthorizations.id, id))
700
854
  .returning();
855
+ const actionLedgerContext = runtime.actionLedgerContext;
856
+ if (actionLedgerContext) {
857
+ const [row] = await db.transaction(async (tx) => {
858
+ const updated = await updateAuthorization(tx);
859
+ if (updated[0]) {
860
+ await appendActionLedgerMutation(tx, buildPaymentAuthorizationUpdateActionLedgerInput(actionLedgerContext, { authorization: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
861
+ }
862
+ return updated;
863
+ });
864
+ return row ?? null;
865
+ }
866
+ const [row] = await updateAuthorization(db);
701
867
  return row ?? null;
702
868
  },
703
- async deletePaymentAuthorization(db, id) {
869
+ async deletePaymentAuthorization(db, id, runtime = {}) {
870
+ const actionLedgerContext = runtime.actionLedgerContext;
871
+ if (actionLedgerContext) {
872
+ return db.transaction(async (tx) => {
873
+ const [existing] = await tx
874
+ .select()
875
+ .from(paymentAuthorizations)
876
+ .where(eq(paymentAuthorizations.id, id))
877
+ .limit(1);
878
+ if (!existing) {
879
+ return null;
880
+ }
881
+ await tx.delete(paymentAuthorizations).where(eq(paymentAuthorizations.id, id));
882
+ await appendActionLedgerMutation(tx, buildPaymentAuthorizationDeleteActionLedgerInput(actionLedgerContext, { authorization: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
883
+ return { id: existing.id };
884
+ });
885
+ }
704
886
  const [row] = await db
705
887
  .delete(paymentAuthorizations)
706
888
  .where(eq(paymentAuthorizations.id, id))
@@ -728,8 +910,8 @@ export const financeService = {
728
910
  const [row] = await db.select().from(paymentCaptures).where(eq(paymentCaptures.id, id)).limit(1);
729
911
  return row ?? null;
730
912
  },
731
- async createPaymentCapture(db, data) {
732
- const [row] = await db
913
+ async createPaymentCapture(db, data, runtime = {}) {
914
+ const createCapture = (writer) => writer
733
915
  .insert(paymentCaptures)
734
916
  .values({
735
917
  ...data,
@@ -737,10 +919,22 @@ export const financeService = {
737
919
  settledAt: toTimestamp(data.settledAt),
738
920
  })
739
921
  .returning();
922
+ const actionLedgerContext = runtime.actionLedgerContext;
923
+ if (actionLedgerContext) {
924
+ const [row] = await db.transaction(async (tx) => {
925
+ const created = await createCapture(tx);
926
+ if (created[0]) {
927
+ await appendActionLedgerMutation(tx, await buildPaymentCaptureCreateActionLedgerInput(actionLedgerContext, { capture: created[0] }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
928
+ }
929
+ return created;
930
+ });
931
+ return row ?? null;
932
+ }
933
+ const [row] = await createCapture(db);
740
934
  return row ?? null;
741
935
  },
742
- async updatePaymentCapture(db, id, data) {
743
- const [row] = await db
936
+ async updatePaymentCapture(db, id, data, runtime = {}) {
937
+ const updateCapture = (writer) => writer
744
938
  .update(paymentCaptures)
745
939
  .set({
746
940
  ...data,
@@ -750,9 +944,37 @@ export const financeService = {
750
944
  })
751
945
  .where(eq(paymentCaptures.id, id))
752
946
  .returning();
947
+ const actionLedgerContext = runtime.actionLedgerContext;
948
+ if (actionLedgerContext) {
949
+ const [row] = await db.transaction(async (tx) => {
950
+ const updated = await updateCapture(tx);
951
+ if (updated[0]) {
952
+ await appendActionLedgerMutation(tx, buildPaymentCaptureUpdateActionLedgerInput(actionLedgerContext, { capture: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
953
+ }
954
+ return updated;
955
+ });
956
+ return row ?? null;
957
+ }
958
+ const [row] = await updateCapture(db);
753
959
  return row ?? null;
754
960
  },
755
- async deletePaymentCapture(db, id) {
961
+ async deletePaymentCapture(db, id, runtime = {}) {
962
+ const actionLedgerContext = runtime.actionLedgerContext;
963
+ if (actionLedgerContext) {
964
+ return db.transaction(async (tx) => {
965
+ const [existing] = await tx
966
+ .select()
967
+ .from(paymentCaptures)
968
+ .where(eq(paymentCaptures.id, id))
969
+ .limit(1);
970
+ if (!existing) {
971
+ return null;
972
+ }
973
+ await tx.delete(paymentCaptures).where(eq(paymentCaptures.id, id));
974
+ await appendActionLedgerMutation(tx, buildPaymentCaptureDeleteActionLedgerInput(actionLedgerContext, { capture: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
975
+ return { id: existing.id };
976
+ });
977
+ }
756
978
  const [row] = await db
757
979
  .delete(paymentCaptures)
758
980
  .where(eq(paymentCaptures.id, id))
@@ -766,20 +988,33 @@ export const financeService = {
766
988
  .where(eq(bookingPaymentSchedules.bookingId, bookingId))
767
989
  .orderBy(asc(bookingPaymentSchedules.dueDate), asc(bookingPaymentSchedules.createdAt));
768
990
  },
769
- async createBookingPaymentSchedule(db, bookingId, data) {
770
- const [booking] = await db
771
- .select({ id: bookings.id })
772
- .from(bookings)
773
- .where(eq(bookings.id, bookingId))
774
- .limit(1);
775
- if (!booking) {
776
- return null;
991
+ async createBookingPaymentSchedule(db, bookingId, data, runtime = {}) {
992
+ const createSchedule = async (writer) => {
993
+ const [booking] = await writer
994
+ .select({ id: bookings.id })
995
+ .from(bookings)
996
+ .where(eq(bookings.id, bookingId))
997
+ .limit(1);
998
+ if (!booking) {
999
+ return null;
1000
+ }
1001
+ const [row] = await writer
1002
+ .insert(bookingPaymentSchedules)
1003
+ .values({ ...data, bookingId })
1004
+ .returning();
1005
+ return row ?? null;
1006
+ };
1007
+ const actionLedgerContext = runtime.actionLedgerContext;
1008
+ if (actionLedgerContext) {
1009
+ return db.transaction(async (tx) => {
1010
+ const row = await createSchedule(tx);
1011
+ if (row) {
1012
+ await appendActionLedgerMutation(tx, buildBookingPaymentScheduleCreateActionLedgerInput(actionLedgerContext, { schedule: row }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1013
+ }
1014
+ return row;
1015
+ });
777
1016
  }
778
- const [row] = await db
779
- .insert(bookingPaymentSchedules)
780
- .values({ ...data, bookingId })
781
- .returning();
782
- return row ?? null;
1017
+ return createSchedule(db);
783
1018
  },
784
1019
  /**
785
1020
  * Persist a payment schedule that was already computed elsewhere
@@ -831,116 +1066,183 @@ export const financeService = {
831
1066
  });
832
1067
  return db.insert(bookingPaymentSchedules).values(rows).returning();
833
1068
  },
834
- async applyDefaultBookingPaymentPlan(db, bookingId, data) {
835
- const [booking] = await db.select().from(bookings).where(eq(bookings.id, bookingId)).limit(1);
836
- if (!booking) {
837
- return null;
838
- }
839
- const totalAmountCents = booking.sellAmountCents ?? 0;
840
- if (totalAmountCents <= 0) {
841
- return [];
842
- }
843
- const today = startOfUtcDay(new Date());
844
- const depositDueDate = data.depositDueDate ? parseDateString(data.depositDueDate) : today;
845
- const startDate = booking.startDate ? parseDateString(booking.startDate) : null;
846
- const rawBalanceDueDate = startDate
847
- ? new Date(startDate.getTime() - data.balanceDueDaysBeforeStart * 24 * 60 * 60 * 1000)
848
- : today;
849
- const balanceDueDate = rawBalanceDueDate < today ? today : rawBalanceDueDate;
850
- let depositAmountCents = 0;
851
- if (data.depositMode === "fixed_amount") {
852
- depositAmountCents = Math.min(totalAmountCents, data.depositValue);
853
- }
854
- else if (data.depositMode === "percentage") {
855
- depositAmountCents = Math.min(totalAmountCents, Math.round((totalAmountCents * data.depositValue) / 100));
856
- }
857
- if (data.clearExistingPending) {
858
- await db
859
- .delete(bookingPaymentSchedules)
860
- .where(and(eq(bookingPaymentSchedules.bookingId, bookingId), or(eq(bookingPaymentSchedules.status, "pending"), eq(bookingPaymentSchedules.status, "due"))));
861
- }
862
- const scheduleRows = [];
863
- if (depositAmountCents > 0 && depositAmountCents < totalAmountCents) {
864
- scheduleRows.push({
865
- bookingItemId: null,
866
- scheduleType: "deposit",
867
- status: depositDueDate <= today ? "due" : "pending",
868
- dueDate: toDateString(depositDueDate),
869
- currency: booking.sellCurrency,
870
- amountCents: depositAmountCents,
871
- notes: data.notes ?? null,
872
- });
873
- scheduleRows.push({
874
- bookingItemId: null,
875
- scheduleType: "balance",
876
- status: balanceDueDate <= today ? "due" : "pending",
877
- dueDate: toDateString(balanceDueDate),
878
- currency: booking.sellCurrency,
879
- amountCents: Math.max(0, totalAmountCents - depositAmountCents),
880
- notes: data.notes ?? null,
881
- });
882
- }
883
- else {
884
- const singleDueDate = balanceDueDate <= today ? today : balanceDueDate;
885
- scheduleRows.push({
886
- bookingItemId: null,
887
- scheduleType: "balance",
888
- status: singleDueDate <= today ? "due" : "pending",
889
- dueDate: toDateString(singleDueDate),
890
- currency: booking.sellCurrency,
891
- amountCents: totalAmountCents,
892
- notes: data.notes ?? null,
893
- });
894
- }
895
- const createdSchedules = await db
896
- .insert(bookingPaymentSchedules)
897
- .values(scheduleRows.map((row) => ({
898
- ...row,
899
- bookingId,
900
- bookingItemId: row.bookingItemId ?? null,
901
- notes: row.notes ?? null,
902
- })))
903
- .returning();
904
- if (data.createGuarantee) {
905
- const depositSchedule = createdSchedules.find((schedule) => schedule.scheduleType === "deposit");
906
- if (depositSchedule) {
907
- await db.insert(bookingGuarantees).values({
908
- bookingId,
909
- bookingPaymentScheduleId: depositSchedule.id,
1069
+ async applyDefaultBookingPaymentPlan(db, bookingId, data, runtime = {}) {
1070
+ const applyPlan = async (writer) => {
1071
+ const [booking] = await writer
1072
+ .select()
1073
+ .from(bookings)
1074
+ .where(eq(bookings.id, bookingId))
1075
+ .limit(1);
1076
+ if (!booking) {
1077
+ return null;
1078
+ }
1079
+ const totalAmountCents = booking.sellAmountCents ?? 0;
1080
+ if (totalAmountCents <= 0) {
1081
+ return {
1082
+ createdSchedules: [],
1083
+ deletedSchedules: [],
1084
+ createdGuarantee: null,
1085
+ };
1086
+ }
1087
+ const today = startOfUtcDay(new Date());
1088
+ const depositDueDate = data.depositDueDate ? parseDateString(data.depositDueDate) : today;
1089
+ const startDate = booking.startDate ? parseDateString(booking.startDate) : null;
1090
+ const rawBalanceDueDate = startDate
1091
+ ? new Date(startDate.getTime() - data.balanceDueDaysBeforeStart * 24 * 60 * 60 * 1000)
1092
+ : today;
1093
+ const balanceDueDate = rawBalanceDueDate < today ? today : rawBalanceDueDate;
1094
+ let depositAmountCents = 0;
1095
+ if (data.depositMode === "fixed_amount") {
1096
+ depositAmountCents = Math.min(totalAmountCents, data.depositValue);
1097
+ }
1098
+ else if (data.depositMode === "percentage") {
1099
+ depositAmountCents = Math.min(totalAmountCents, Math.round((totalAmountCents * data.depositValue) / 100));
1100
+ }
1101
+ const clearableScheduleWhere = and(eq(bookingPaymentSchedules.bookingId, bookingId), or(eq(bookingPaymentSchedules.status, "pending"), eq(bookingPaymentSchedules.status, "due")));
1102
+ const deletedSchedules = data.clearExistingPending
1103
+ ? await writer.select().from(bookingPaymentSchedules).where(clearableScheduleWhere)
1104
+ : [];
1105
+ if (data.clearExistingPending) {
1106
+ await writer.delete(bookingPaymentSchedules).where(clearableScheduleWhere);
1107
+ }
1108
+ const scheduleRows = [];
1109
+ if (depositAmountCents > 0 && depositAmountCents < totalAmountCents) {
1110
+ scheduleRows.push({
1111
+ bookingItemId: null,
1112
+ scheduleType: "deposit",
1113
+ status: depositDueDate <= today ? "due" : "pending",
1114
+ dueDate: toDateString(depositDueDate),
1115
+ currency: booking.sellCurrency,
1116
+ amountCents: depositAmountCents,
1117
+ notes: data.notes ?? null,
1118
+ });
1119
+ scheduleRows.push({
1120
+ bookingItemId: null,
1121
+ scheduleType: "balance",
1122
+ status: balanceDueDate <= today ? "due" : "pending",
1123
+ dueDate: toDateString(balanceDueDate),
1124
+ currency: booking.sellCurrency,
1125
+ amountCents: Math.max(0, totalAmountCents - depositAmountCents),
1126
+ notes: data.notes ?? null,
1127
+ });
1128
+ }
1129
+ else {
1130
+ const singleDueDate = balanceDueDate <= today ? today : balanceDueDate;
1131
+ scheduleRows.push({
910
1132
  bookingItemId: null,
911
- guaranteeType: data.guaranteeType,
912
- status: "pending",
913
- paymentInstrumentId: null,
914
- paymentAuthorizationId: null,
915
- currency: depositSchedule.currency,
916
- amountCents: depositSchedule.amountCents,
917
- provider: null,
918
- referenceNumber: null,
919
- guaranteedAt: null,
920
- expiresAt: null,
921
- releasedAt: null,
1133
+ scheduleType: "balance",
1134
+ status: singleDueDate <= today ? "due" : "pending",
1135
+ dueDate: toDateString(singleDueDate),
1136
+ currency: booking.sellCurrency,
1137
+ amountCents: totalAmountCents,
922
1138
  notes: data.notes ?? null,
923
1139
  });
924
1140
  }
1141
+ const createdSchedules = await writer
1142
+ .insert(bookingPaymentSchedules)
1143
+ .values(scheduleRows.map((row) => ({
1144
+ ...row,
1145
+ bookingId,
1146
+ bookingItemId: row.bookingItemId ?? null,
1147
+ notes: row.notes ?? null,
1148
+ })))
1149
+ .returning();
1150
+ let createdGuarantee = null;
1151
+ if (data.createGuarantee) {
1152
+ const depositSchedule = createdSchedules.find((schedule) => schedule.scheduleType === "deposit");
1153
+ if (depositSchedule) {
1154
+ const [guarantee] = await writer
1155
+ .insert(bookingGuarantees)
1156
+ .values({
1157
+ bookingId,
1158
+ bookingPaymentScheduleId: depositSchedule.id,
1159
+ bookingItemId: null,
1160
+ guaranteeType: data.guaranteeType,
1161
+ status: "pending",
1162
+ paymentInstrumentId: null,
1163
+ paymentAuthorizationId: null,
1164
+ currency: depositSchedule.currency,
1165
+ amountCents: depositSchedule.amountCents,
1166
+ provider: null,
1167
+ referenceNumber: null,
1168
+ guaranteedAt: null,
1169
+ expiresAt: null,
1170
+ releasedAt: null,
1171
+ notes: data.notes ?? null,
1172
+ })
1173
+ .returning();
1174
+ createdGuarantee = guarantee ?? null;
1175
+ }
1176
+ }
1177
+ return { createdSchedules, deletedSchedules, createdGuarantee };
1178
+ };
1179
+ const actionLedgerContext = runtime.actionLedgerContext;
1180
+ if (actionLedgerContext) {
1181
+ const result = await db.transaction(async (tx) => {
1182
+ const applied = await applyPlan(tx);
1183
+ if (!applied) {
1184
+ return null;
1185
+ }
1186
+ for (const schedule of applied.deletedSchedules) {
1187
+ await appendActionLedgerMutation(tx, buildBookingPaymentScheduleDeleteActionLedgerInput(actionLedgerContext, { schedule }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1188
+ }
1189
+ for (const schedule of applied.createdSchedules) {
1190
+ await appendActionLedgerMutation(tx, buildBookingPaymentScheduleCreateActionLedgerInput(actionLedgerContext, { schedule }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1191
+ }
1192
+ if (applied.createdGuarantee) {
1193
+ await appendActionLedgerMutation(tx, await buildBookingGuaranteeCreateActionLedgerInput(actionLedgerContext, { guarantee: applied.createdGuarantee }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1194
+ }
1195
+ return applied.createdSchedules;
1196
+ });
1197
+ return result;
925
1198
  }
926
- return createdSchedules;
1199
+ const result = await applyPlan(db);
1200
+ return result?.createdSchedules ?? null;
927
1201
  },
928
- async updateBookingPaymentSchedule(db, scheduleId, data) {
929
- const [row] = await db
1202
+ async updateBookingPaymentSchedule(db, scheduleId, data, runtime = {}) {
1203
+ const updateSchedule = (writer) => writer
930
1204
  .update(bookingPaymentSchedules)
931
1205
  .set({ ...data, updatedAt: new Date() })
932
1206
  .where(eq(bookingPaymentSchedules.id, scheduleId))
933
1207
  .returning();
1208
+ const actionLedgerContext = runtime.actionLedgerContext;
1209
+ if (actionLedgerContext) {
1210
+ const [row] = await db.transaction(async (tx) => {
1211
+ const updated = await updateSchedule(tx);
1212
+ if (updated[0]) {
1213
+ await appendActionLedgerMutation(tx, buildBookingPaymentScheduleUpdateActionLedgerInput(actionLedgerContext, { schedule: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1214
+ }
1215
+ return updated;
1216
+ });
1217
+ return row ?? null;
1218
+ }
1219
+ const [row] = await updateSchedule(db);
934
1220
  return row ?? null;
935
1221
  },
936
- async deleteBookingPaymentSchedule(db, scheduleId) {
1222
+ async deleteBookingPaymentSchedule(db, scheduleId, runtime = {}) {
1223
+ const actionLedgerContext = runtime.actionLedgerContext;
1224
+ if (actionLedgerContext) {
1225
+ return db.transaction(async (tx) => {
1226
+ const [existing] = await tx
1227
+ .select()
1228
+ .from(bookingPaymentSchedules)
1229
+ .where(eq(bookingPaymentSchedules.id, scheduleId))
1230
+ .limit(1);
1231
+ if (!existing) {
1232
+ return null;
1233
+ }
1234
+ await tx.delete(bookingPaymentSchedules).where(eq(bookingPaymentSchedules.id, scheduleId));
1235
+ await appendActionLedgerMutation(tx, buildBookingPaymentScheduleDeleteActionLedgerInput(actionLedgerContext, { schedule: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1236
+ return { id: existing.id };
1237
+ });
1238
+ }
937
1239
  const [row] = await db
938
1240
  .delete(bookingPaymentSchedules)
939
1241
  .where(eq(bookingPaymentSchedules.id, scheduleId))
940
1242
  .returning({ id: bookingPaymentSchedules.id });
941
1243
  return row ?? null;
942
1244
  },
943
- async createPaymentSessionFromBookingSchedule(db, scheduleId, data) {
1245
+ async createPaymentSessionFromBookingSchedule(db, scheduleId, data, runtime = {}) {
944
1246
  const [schedule] = await db
945
1247
  .select()
946
1248
  .from(bookingPaymentSchedules)
@@ -981,9 +1283,9 @@ export const financeService = {
981
1283
  scheduleType: schedule.scheduleType,
982
1284
  dueDate: schedule.dueDate,
983
1285
  },
984
- });
1286
+ }, runtime);
985
1287
  },
986
- async createPaymentSessionFromInvoice(db, invoiceId, data) {
1288
+ async createPaymentSessionFromInvoice(db, invoiceId, data, runtime = {}) {
987
1289
  const [invoice] = await db.select().from(invoices).where(eq(invoices.id, invoiceId)).limit(1);
988
1290
  if (!invoice) {
989
1291
  return null;
@@ -1022,7 +1324,7 @@ export const financeService = {
1022
1324
  invoiceType: invoice.invoiceType,
1023
1325
  dueDate: invoice.dueDate,
1024
1326
  },
1025
- });
1327
+ }, runtime);
1026
1328
  },
1027
1329
  listBookingGuarantees(db, bookingId) {
1028
1330
  return db
@@ -1031,38 +1333,51 @@ export const financeService = {
1031
1333
  .where(eq(bookingGuarantees.bookingId, bookingId))
1032
1334
  .orderBy(desc(bookingGuarantees.createdAt));
1033
1335
  },
1034
- async createBookingGuarantee(db, bookingId, data) {
1035
- const [booking] = await db
1036
- .select({ id: bookings.id })
1037
- .from(bookings)
1038
- .where(eq(bookings.id, bookingId))
1039
- .limit(1);
1040
- if (!booking) {
1041
- return null;
1336
+ async createBookingGuarantee(db, bookingId, data, runtime = {}) {
1337
+ const createGuarantee = async (writer) => {
1338
+ const [booking] = await writer
1339
+ .select({ id: bookings.id })
1340
+ .from(bookings)
1341
+ .where(eq(bookings.id, bookingId))
1342
+ .limit(1);
1343
+ if (!booking) {
1344
+ return null;
1345
+ }
1346
+ const [row] = await writer
1347
+ .insert(bookingGuarantees)
1348
+ .values({
1349
+ bookingId,
1350
+ bookingPaymentScheduleId: data.bookingPaymentScheduleId ?? null,
1351
+ bookingItemId: data.bookingItemId ?? null,
1352
+ guaranteeType: data.guaranteeType,
1353
+ status: data.status,
1354
+ paymentInstrumentId: data.paymentInstrumentId ?? null,
1355
+ paymentAuthorizationId: data.paymentAuthorizationId ?? null,
1356
+ currency: data.currency ?? null,
1357
+ amountCents: data.amountCents ?? null,
1358
+ provider: data.provider ?? null,
1359
+ referenceNumber: data.referenceNumber ?? null,
1360
+ guaranteedAt: toTimestamp(data.guaranteedAt),
1361
+ expiresAt: toTimestamp(data.expiresAt),
1362
+ releasedAt: toTimestamp(data.releasedAt),
1363
+ notes: data.notes ?? null,
1364
+ })
1365
+ .returning();
1366
+ return row ?? null;
1367
+ };
1368
+ const actionLedgerContext = runtime.actionLedgerContext;
1369
+ if (actionLedgerContext) {
1370
+ return db.transaction(async (tx) => {
1371
+ const row = await createGuarantee(tx);
1372
+ if (row) {
1373
+ await appendActionLedgerMutation(tx, await buildBookingGuaranteeCreateActionLedgerInput(actionLedgerContext, { guarantee: row }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1374
+ }
1375
+ return row;
1376
+ });
1042
1377
  }
1043
- const [row] = await db
1044
- .insert(bookingGuarantees)
1045
- .values({
1046
- bookingId,
1047
- bookingPaymentScheduleId: data.bookingPaymentScheduleId ?? null,
1048
- bookingItemId: data.bookingItemId ?? null,
1049
- guaranteeType: data.guaranteeType,
1050
- status: data.status,
1051
- paymentInstrumentId: data.paymentInstrumentId ?? null,
1052
- paymentAuthorizationId: data.paymentAuthorizationId ?? null,
1053
- currency: data.currency ?? null,
1054
- amountCents: data.amountCents ?? null,
1055
- provider: data.provider ?? null,
1056
- referenceNumber: data.referenceNumber ?? null,
1057
- guaranteedAt: toTimestamp(data.guaranteedAt),
1058
- expiresAt: toTimestamp(data.expiresAt),
1059
- releasedAt: toTimestamp(data.releasedAt),
1060
- notes: data.notes ?? null,
1061
- })
1062
- .returning();
1063
- return row ?? null;
1378
+ return createGuarantee(db);
1064
1379
  },
1065
- async createPaymentSessionFromBookingGuarantee(db, guaranteeId, data) {
1380
+ async createPaymentSessionFromBookingGuarantee(db, guaranteeId, data, runtime = {}) {
1066
1381
  const [guarantee] = await db
1067
1382
  .select()
1068
1383
  .from(bookingGuarantees)
@@ -1109,10 +1424,10 @@ export const financeService = {
1109
1424
  metadata: data.metadata ?? {
1110
1425
  guaranteeType: guarantee.guaranteeType,
1111
1426
  },
1112
- });
1427
+ }, runtime);
1113
1428
  },
1114
- async updateBookingGuarantee(db, guaranteeId, data) {
1115
- const [row] = await db
1429
+ async updateBookingGuarantee(db, guaranteeId, data, runtime = {}) {
1430
+ const updateGuarantee = (writer) => writer
1116
1431
  .update(bookingGuarantees)
1117
1432
  .set({
1118
1433
  ...data,
@@ -1123,9 +1438,37 @@ export const financeService = {
1123
1438
  })
1124
1439
  .where(eq(bookingGuarantees.id, guaranteeId))
1125
1440
  .returning();
1441
+ const actionLedgerContext = runtime.actionLedgerContext;
1442
+ if (actionLedgerContext) {
1443
+ const [row] = await db.transaction(async (tx) => {
1444
+ const updated = await updateGuarantee(tx);
1445
+ if (updated[0]) {
1446
+ await appendActionLedgerMutation(tx, buildBookingGuaranteeUpdateActionLedgerInput(actionLedgerContext, { guarantee: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1447
+ }
1448
+ return updated;
1449
+ });
1450
+ return row ?? null;
1451
+ }
1452
+ const [row] = await updateGuarantee(db);
1126
1453
  return row ?? null;
1127
1454
  },
1128
- async deleteBookingGuarantee(db, guaranteeId) {
1455
+ async deleteBookingGuarantee(db, guaranteeId, runtime = {}) {
1456
+ const actionLedgerContext = runtime.actionLedgerContext;
1457
+ if (actionLedgerContext) {
1458
+ return db.transaction(async (tx) => {
1459
+ const [existing] = await tx
1460
+ .select()
1461
+ .from(bookingGuarantees)
1462
+ .where(eq(bookingGuarantees.id, guaranteeId))
1463
+ .limit(1);
1464
+ if (!existing) {
1465
+ return null;
1466
+ }
1467
+ await tx.delete(bookingGuarantees).where(eq(bookingGuarantees.id, guaranteeId));
1468
+ await appendActionLedgerMutation(tx, buildBookingGuaranteeDeleteActionLedgerInput(actionLedgerContext, { guarantee: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1469
+ return { id: existing.id };
1470
+ });
1471
+ }
1129
1472
  const [row] = await db
1130
1473
  .delete(bookingGuarantees)
1131
1474
  .where(eq(bookingGuarantees.id, guaranteeId))
@@ -1311,19 +1654,43 @@ export const financeService = {
1311
1654
  offset: query.offset,
1312
1655
  };
1313
1656
  },
1314
- async createSupplierPayment(db, data) {
1315
- const [row] = await db
1657
+ async createSupplierPayment(db, data, runtime = {}) {
1658
+ const createPayment = (writer) => writer
1316
1659
  .insert(supplierPayments)
1317
1660
  .values({ ...data, paymentInstrumentId: data.paymentInstrumentId ?? null })
1318
1661
  .returning();
1662
+ const actionLedgerContext = runtime.actionLedgerContext;
1663
+ if (actionLedgerContext) {
1664
+ const [row] = await db.transaction(async (tx) => {
1665
+ const created = await createPayment(tx);
1666
+ if (created[0]) {
1667
+ await appendActionLedgerMutation(tx, await buildSupplierPaymentCreateActionLedgerInput(actionLedgerContext, { payment: created[0] }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1668
+ }
1669
+ return created;
1670
+ });
1671
+ return row;
1672
+ }
1673
+ const [row] = await createPayment(db);
1319
1674
  return row;
1320
1675
  },
1321
- async updateSupplierPayment(db, id, data) {
1322
- const [row] = await db
1676
+ async updateSupplierPayment(db, id, data, runtime = {}) {
1677
+ const updatePayment = (writer) => writer
1323
1678
  .update(supplierPayments)
1324
1679
  .set({ ...data, updatedAt: new Date() })
1325
1680
  .where(eq(supplierPayments.id, id))
1326
1681
  .returning();
1682
+ const actionLedgerContext = runtime.actionLedgerContext;
1683
+ if (actionLedgerContext) {
1684
+ const [row] = await db.transaction(async (tx) => {
1685
+ const updated = await updatePayment(tx);
1686
+ if (updated[0]) {
1687
+ await appendActionLedgerMutation(tx, buildSupplierPaymentUpdateActionLedgerInput(actionLedgerContext, { payment: updated[0], changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1688
+ }
1689
+ return updated;
1690
+ });
1691
+ return row ?? null;
1692
+ }
1693
+ const [row] = await updatePayment(db);
1327
1694
  return row ?? null;
1328
1695
  },
1329
1696
  async listInvoices(db, query) {
@@ -1504,15 +1871,41 @@ export const financeService = {
1504
1871
  const [row] = await db.select().from(invoices).where(eq(invoices.id, id)).limit(1);
1505
1872
  return row ?? null;
1506
1873
  },
1507
- async updateInvoice(db, id, data) {
1508
- const [row] = await db
1874
+ async updateInvoice(db, id, data, runtime = {}) {
1875
+ const updateInvoiceRow = (writer) => writer
1509
1876
  .update(invoices)
1510
1877
  .set({ ...data, updatedAt: new Date() })
1511
1878
  .where(eq(invoices.id, id))
1512
1879
  .returning();
1880
+ const actionLedgerContext = runtime.actionLedgerContext;
1881
+ if (actionLedgerContext) {
1882
+ return db.transaction(async (tx) => {
1883
+ const [row] = await updateInvoiceRow(tx);
1884
+ if (row) {
1885
+ await appendActionLedgerMutation(tx, buildInvoiceUpdateActionLedgerInput(actionLedgerContext, { invoice: row, changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1886
+ }
1887
+ return row ?? null;
1888
+ });
1889
+ }
1890
+ const [row] = await updateInvoiceRow(db);
1513
1891
  return row ?? null;
1514
1892
  },
1515
- async deleteInvoice(db, id) {
1893
+ async deleteInvoice(db, id, runtime = {}) {
1894
+ const actionLedgerContext = runtime.actionLedgerContext;
1895
+ if (actionLedgerContext) {
1896
+ return db.transaction(async (tx) => {
1897
+ const [existing] = await tx.select().from(invoices).where(eq(invoices.id, id)).limit(1);
1898
+ if (!existing) {
1899
+ return { status: "not_found" };
1900
+ }
1901
+ if (existing.status !== "draft") {
1902
+ return { status: "not_draft" };
1903
+ }
1904
+ await tx.delete(invoices).where(eq(invoices.id, id));
1905
+ await appendActionLedgerMutation(tx, buildInvoiceDeleteActionLedgerInput(actionLedgerContext, { invoice: existing }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1906
+ return { status: "deleted" };
1907
+ });
1908
+ }
1516
1909
  const [existing] = await db
1517
1910
  .select({ id: invoices.id, status: invoices.status })
1518
1911
  .from(invoices)
@@ -1534,35 +1927,97 @@ export const financeService = {
1534
1927
  .where(eq(invoiceLineItems.invoiceId, invoiceId))
1535
1928
  .orderBy(asc(invoiceLineItems.sortOrder));
1536
1929
  },
1537
- async createInvoiceLineItem(db, invoiceId, data) {
1538
- const [invoice] = await db
1539
- .select({ id: invoices.id })
1540
- .from(invoices)
1541
- .where(eq(invoices.id, invoiceId))
1542
- .limit(1);
1543
- if (!invoice) {
1544
- return null;
1930
+ async createInvoiceLineItem(db, invoiceId, data, runtime = {}) {
1931
+ const createLineItem = async (writer) => {
1932
+ const [invoice] = await writer
1933
+ .select()
1934
+ .from(invoices)
1935
+ .where(eq(invoices.id, invoiceId))
1936
+ .limit(1);
1937
+ if (!invoice) {
1938
+ return null;
1939
+ }
1940
+ const [row] = await writer
1941
+ .insert(invoiceLineItems)
1942
+ .values({ ...data, invoiceId })
1943
+ .returning();
1944
+ return row ? { invoice, lineItem: row } : null;
1945
+ };
1946
+ const actionLedgerContext = runtime.actionLedgerContext;
1947
+ if (actionLedgerContext) {
1948
+ const result = await db.transaction(async (tx) => {
1949
+ const created = await createLineItem(tx);
1950
+ if (created) {
1951
+ await appendActionLedgerMutation(tx, buildInvoiceLineItemCreateActionLedgerInput(actionLedgerContext, created, {
1952
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
1953
+ }));
1954
+ }
1955
+ return created;
1956
+ });
1957
+ return result?.lineItem ?? null;
1545
1958
  }
1546
- const [row] = await db
1547
- .insert(invoiceLineItems)
1548
- .values({ ...data, invoiceId })
1549
- .returning();
1550
- return row;
1959
+ return (await createLineItem(db))?.lineItem ?? null;
1551
1960
  },
1552
- async updateInvoiceLineItem(db, lineId, data) {
1553
- const [row] = await db
1554
- .update(invoiceLineItems)
1555
- .set(data)
1556
- .where(eq(invoiceLineItems.id, lineId))
1557
- .returning();
1558
- return row ?? null;
1961
+ async updateInvoiceLineItem(db, lineId, data, runtime = {}) {
1962
+ const updateLineItem = async (writer) => {
1963
+ const [row] = await writer
1964
+ .update(invoiceLineItems)
1965
+ .set(data)
1966
+ .where(eq(invoiceLineItems.id, lineId))
1967
+ .returning();
1968
+ if (!row) {
1969
+ return null;
1970
+ }
1971
+ const [invoice] = await writer
1972
+ .select()
1973
+ .from(invoices)
1974
+ .where(eq(invoices.id, row.invoiceId))
1975
+ .limit(1);
1976
+ return invoice ? { invoice, lineItem: row } : null;
1977
+ };
1978
+ const actionLedgerContext = runtime.actionLedgerContext;
1979
+ if (actionLedgerContext) {
1980
+ const result = await db.transaction(async (tx) => {
1981
+ const updated = await updateLineItem(tx);
1982
+ if (updated) {
1983
+ await appendActionLedgerMutation(tx, buildInvoiceLineItemUpdateActionLedgerInput(actionLedgerContext, { ...updated, changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
1984
+ }
1985
+ return updated;
1986
+ });
1987
+ return result?.lineItem ?? null;
1988
+ }
1989
+ return (await updateLineItem(db))?.lineItem ?? null;
1559
1990
  },
1560
- async deleteInvoiceLineItem(db, lineId) {
1561
- const [row] = await db
1562
- .delete(invoiceLineItems)
1563
- .where(eq(invoiceLineItems.id, lineId))
1564
- .returning({ id: invoiceLineItems.id });
1565
- return row ?? null;
1991
+ async deleteInvoiceLineItem(db, lineId, runtime = {}) {
1992
+ const deleteLineItem = async (writer) => {
1993
+ const [row] = await writer
1994
+ .delete(invoiceLineItems)
1995
+ .where(eq(invoiceLineItems.id, lineId))
1996
+ .returning();
1997
+ if (!row) {
1998
+ return null;
1999
+ }
2000
+ const [invoice] = await writer
2001
+ .select()
2002
+ .from(invoices)
2003
+ .where(eq(invoices.id, row.invoiceId))
2004
+ .limit(1);
2005
+ return invoice ? { invoice, lineItem: row } : null;
2006
+ };
2007
+ const actionLedgerContext = runtime.actionLedgerContext;
2008
+ if (actionLedgerContext) {
2009
+ const result = await db.transaction(async (tx) => {
2010
+ const deleted = await deleteLineItem(tx);
2011
+ if (deleted) {
2012
+ await appendActionLedgerMutation(tx, buildInvoiceLineItemDeleteActionLedgerInput(actionLedgerContext, deleted, {
2013
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
2014
+ }));
2015
+ }
2016
+ return deleted;
2017
+ });
2018
+ return result?.lineItem ?? null;
2019
+ }
2020
+ return (await deleteLineItem(db))?.lineItem ?? null;
1566
2021
  },
1567
2022
  listPayments(db, invoiceId) {
1568
2023
  return db
@@ -1708,8 +2163,8 @@ export const financeService = {
1708
2163
  const countResult = await db.execute(sql `
1709
2164
  SELECT COUNT(*)::int AS count FROM (${unioned}) all_payments
1710
2165
  `);
1711
- const rows = dataResult;
1712
- const total = countResult[0]?.count ?? 0;
2166
+ const rows = toRows(dataResult);
2167
+ const total = toRows(countResult)[0]?.count ?? 0;
1713
2168
  const data = rows.map(mapRawPayment);
1714
2169
  return {
1715
2170
  data,
@@ -1758,7 +2213,7 @@ export const financeService = {
1758
2213
  WHERE sp.id = ${id}
1759
2214
  LIMIT 1
1760
2215
  `);
1761
- const row = result[0];
2216
+ const row = toRows(result)[0];
1762
2217
  return row ? mapRawPayment(row) : null;
1763
2218
  }
1764
2219
  const result = await db.execute(sql `
@@ -1794,10 +2249,10 @@ export const financeService = {
1794
2249
  WHERE p.id = ${id}
1795
2250
  LIMIT 1
1796
2251
  `);
1797
- const row = result[0];
2252
+ const row = toRows(result)[0];
1798
2253
  return row ? mapRawPayment(row) : null;
1799
2254
  },
1800
- async createPayment(db, invoiceId, data) {
2255
+ async createPayment(db, invoiceId, data, runtime = {}) {
1801
2256
  const [invoice] = await db.select().from(invoices).where(eq(invoices.id, invoiceId)).limit(1);
1802
2257
  if (!invoice) {
1803
2258
  return null;
@@ -1831,6 +2286,14 @@ export const financeService = {
1831
2286
  .update(invoices)
1832
2287
  .set({ paidCents, balanceDueCents, status: newStatus, updatedAt: new Date() })
1833
2288
  .where(eq(invoices.id, invoiceId));
2289
+ if (payment && runtime.actionLedgerContext) {
2290
+ await appendActionLedgerMutation(tx, await buildRecordPaymentActionLedgerInput(runtime.actionLedgerContext, {
2291
+ invoice,
2292
+ payment,
2293
+ }, {
2294
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
2295
+ }));
2296
+ }
1834
2297
  return payment;
1835
2298
  });
1836
2299
  },
@@ -1841,28 +2304,56 @@ export const financeService = {
1841
2304
  .where(eq(creditNotes.invoiceId, invoiceId))
1842
2305
  .orderBy(desc(creditNotes.createdAt));
1843
2306
  },
1844
- async createCreditNote(db, invoiceId, data) {
1845
- const [invoice] = await db
1846
- .select({ id: invoices.id })
1847
- .from(invoices)
1848
- .where(eq(invoices.id, invoiceId))
1849
- .limit(1);
2307
+ async createCreditNote(db, invoiceId, data, runtime = {}) {
2308
+ const [invoice] = await db.select().from(invoices).where(eq(invoices.id, invoiceId)).limit(1);
1850
2309
  if (!invoice) {
1851
2310
  return null;
1852
2311
  }
1853
- const [row] = await db
1854
- .insert(creditNotes)
1855
- .values({ ...data, invoiceId })
1856
- .returning();
1857
- return row;
2312
+ return db.transaction(async (tx) => {
2313
+ const [row] = await tx
2314
+ .insert(creditNotes)
2315
+ .values({ ...data, invoiceId })
2316
+ .returning();
2317
+ if (row && runtime.actionLedgerContext) {
2318
+ await appendActionLedgerMutation(tx, await buildCreditNoteCreationActionLedgerInput(runtime.actionLedgerContext, {
2319
+ invoice,
2320
+ creditNote: row,
2321
+ }, {
2322
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
2323
+ }));
2324
+ }
2325
+ return row;
2326
+ });
1858
2327
  },
1859
- async updateCreditNote(db, creditNoteId, data) {
1860
- const [row] = await db
1861
- .update(creditNotes)
1862
- .set({ ...data, updatedAt: new Date() })
1863
- .where(eq(creditNotes.id, creditNoteId))
1864
- .returning();
1865
- return row ?? null;
2328
+ async updateCreditNote(db, creditNoteId, data, runtime = {}) {
2329
+ const updateCreditNoteRow = async (writer) => {
2330
+ const [row] = await writer
2331
+ .update(creditNotes)
2332
+ .set({ ...data, updatedAt: new Date() })
2333
+ .where(eq(creditNotes.id, creditNoteId))
2334
+ .returning();
2335
+ if (!row) {
2336
+ return null;
2337
+ }
2338
+ const [invoice] = await writer
2339
+ .select()
2340
+ .from(invoices)
2341
+ .where(eq(invoices.id, row.invoiceId))
2342
+ .limit(1);
2343
+ return invoice ? { invoice, creditNote: row } : null;
2344
+ };
2345
+ const actionLedgerContext = runtime.actionLedgerContext;
2346
+ if (actionLedgerContext) {
2347
+ const result = await db.transaction(async (tx) => {
2348
+ const updated = await updateCreditNoteRow(tx);
2349
+ if (updated) {
2350
+ await appendActionLedgerMutation(tx, buildCreditNoteUpdateActionLedgerInput(actionLedgerContext, { ...updated, changes: data }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
2351
+ }
2352
+ return updated;
2353
+ });
2354
+ return result?.creditNote ?? null;
2355
+ }
2356
+ return (await updateCreditNoteRow(db))?.creditNote ?? null;
1866
2357
  },
1867
2358
  listCreditNoteLineItems(db, creditNoteId) {
1868
2359
  return db
@@ -1871,20 +2362,44 @@ export const financeService = {
1871
2362
  .where(eq(creditNoteLineItems.creditNoteId, creditNoteId))
1872
2363
  .orderBy(asc(creditNoteLineItems.sortOrder));
1873
2364
  },
1874
- async createCreditNoteLineItem(db, creditNoteId, data) {
1875
- const [creditNote] = await db
1876
- .select({ id: creditNotes.id })
1877
- .from(creditNotes)
1878
- .where(eq(creditNotes.id, creditNoteId))
1879
- .limit(1);
1880
- if (!creditNote) {
1881
- return null;
2365
+ async createCreditNoteLineItem(db, creditNoteId, data, runtime = {}) {
2366
+ const createLineItem = async (writer) => {
2367
+ const [creditNote] = await writer
2368
+ .select()
2369
+ .from(creditNotes)
2370
+ .where(eq(creditNotes.id, creditNoteId))
2371
+ .limit(1);
2372
+ if (!creditNote) {
2373
+ return null;
2374
+ }
2375
+ const [invoice] = await writer
2376
+ .select()
2377
+ .from(invoices)
2378
+ .where(eq(invoices.id, creditNote.invoiceId))
2379
+ .limit(1);
2380
+ if (!invoice) {
2381
+ return null;
2382
+ }
2383
+ const [row] = await writer
2384
+ .insert(creditNoteLineItems)
2385
+ .values({ ...data, creditNoteId })
2386
+ .returning();
2387
+ return row ? { invoice, creditNote, lineItem: row } : null;
2388
+ };
2389
+ const actionLedgerContext = runtime.actionLedgerContext;
2390
+ if (actionLedgerContext) {
2391
+ const result = await db.transaction(async (tx) => {
2392
+ const created = await createLineItem(tx);
2393
+ if (created) {
2394
+ await appendActionLedgerMutation(tx, buildCreditNoteLineItemCreateActionLedgerInput(actionLedgerContext, created, {
2395
+ authorizationSource: runtime.actionLedgerAuthorizationSource,
2396
+ }));
2397
+ }
2398
+ return created;
2399
+ });
2400
+ return result?.lineItem ?? null;
1882
2401
  }
1883
- const [row] = await db
1884
- .insert(creditNoteLineItems)
1885
- .values({ ...data, creditNoteId })
1886
- .returning();
1887
- return row;
2402
+ return (await createLineItem(db))?.lineItem ?? null;
1888
2403
  },
1889
2404
  listNotes(db, invoiceId) {
1890
2405
  return db