@saasicat/core 1.0.0-rc.25 → 1.0.0-rc.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -198,7 +198,7 @@ interface CapabilityCatalogEntryRow {
198
198
  * `CORE` < `ADVANCED` < `PRO` < `ENTERPRISE`. Apps may add further
199
199
  * tiers; sorting then happens via `FeatureCatalogEntry.sortOrder`.
200
200
  */
201
- type FeatureTier = 'CORE' | 'ADVANCED' | 'PRO' | 'ENTERPRISE' | string;
201
+ type FeatureTier = 'CORE' | 'ADVANCED' | 'PRO' | 'ENTERPRISE' | (string & {});
202
202
  /**
203
203
  * SuperAdmin projection of a feature (aggregation of capabilities that declare
204
204
  * `feature: 'XYZ'` in the decorator). The short marketing form lives here;
@@ -646,6 +646,44 @@ type PaymentGatewayEvent = {
646
646
  occurredAt: Date;
647
647
  sessionRef: string;
648
648
  subject: PaymentMethodSetupSubject;
649
+ } | {
650
+ /**
651
+ * What became of a collection, reported by the gateway on its own:
652
+ * the same outcome `findCollection` answers, for the attempt its key
653
+ * names. Each report reads the payment as it stands when the adapter
654
+ * translates it, so reports arriving out of order never take an
655
+ * attempt back to an earlier state.
656
+ */
657
+ kind: 'collection-reported';
658
+ eventId: string;
659
+ occurredAt: Date;
660
+ attemptKey: string;
661
+ outcome: CollectionOutcome;
662
+ } | {
663
+ /**
664
+ * A refund the operator made in the gateway, of a payment an attempt
665
+ * of SaaSiCat's collected, as it stands when the adapter translates
666
+ * the report: created, settled, failed or canceled.
667
+ */
668
+ kind: 'refund-reported';
669
+ eventId: string;
670
+ occurredAt: Date;
671
+ /** The attempt that collected the payment it pays back. */
672
+ attemptKey: string;
673
+ refund: GatewayRefund;
674
+ } | {
675
+ /**
676
+ * Money the gateway took back from the operator for a payment an
677
+ * attempt of SaaSiCat's collected — a direct debit the bank returned,
678
+ * a chargeback — and what it gave back of it, both as they stand
679
+ * when the adapter translates the report.
680
+ */
681
+ kind: 'reversal-reported';
682
+ eventId: string;
683
+ occurredAt: Date;
684
+ /** The attempt that collected the payment it takes back. */
685
+ attemptKey: string;
686
+ reversal: GatewayReversal;
649
687
  } | {
650
688
  /** Genuine, and nothing SaaSiCat acts on. */
651
689
  kind: 'unhandled';
@@ -654,6 +692,107 @@ type PaymentGatewayEvent = {
654
692
  /** The gateway's own name for the event, for the log. */
655
693
  type: string;
656
694
  };
695
+ /**
696
+ * Why a collection failed, in SaaSiCat's words; the gateway's own code is kept
697
+ * beside it. Whether a second try can pass follows from the reason alone
698
+ * (`isRetryableCollectionFailure`):
699
+ *
700
+ * - `insufficient-funds` — the account or the card does not cover the amount;
701
+ * - `declined` — refused without a reason that rules out a second try, or the
702
+ * bank or issuer could not be reached;
703
+ * - `authentication-required` — the card's bank asks the subscriber to confirm
704
+ * the payment, which nobody can do while they are not present;
705
+ * - `payment-method-unusable` — the card is lost, stolen, blocked or expired,
706
+ * or the account is closed or restricted;
707
+ * - `mandate-invalid` — the direct debit's mandate was revoked, does not match
708
+ * or was disputed;
709
+ * - `other` — anything the gateway names that is none of these.
710
+ */
711
+ type CollectionFailureReason = 'insufficient-funds' | 'declined' | 'authentication-required' | 'payment-method-unusable' | 'mandate-invalid' | 'other';
712
+ /** The collection of one invoice, as the platform asks a gateway to make it. */
713
+ interface CollectInvoiceInput {
714
+ /**
715
+ * The same for this invoice and attempt across every repeat of the
716
+ * request, and kept by the gateway with what it creates, so
717
+ * `findCollection` finds it again. Never a second charge for one key.
718
+ */
719
+ attemptKey: string;
720
+ invoiceId: string;
721
+ /** The invoice's number, which the subscriber's statement names. */
722
+ invoiceNumber: string;
723
+ /** The invoice's gross amount in cents, of `currency`. */
724
+ amountCents: number;
725
+ /** As `config/saas.yaml#currency` writes it, e.g. `EUR`. */
726
+ currency: string;
727
+ /** The customer the payment method is kept for at the gateway. */
728
+ customerRef: string;
729
+ paymentMethodRef: string;
730
+ type: PaymentMethodType;
731
+ }
732
+ /**
733
+ * What became of a collection: collected, still on its way — a direct debit
734
+ * is submitted to the bank and settles days later —, or failed.
735
+ * `paymentRef` is the gateway's reference to what it created for the attempt.
736
+ */
737
+ type CollectionOutcome = {
738
+ status: 'succeeded';
739
+ paymentRef: string;
740
+ /** What the gateway received, in cents of `currency`. */
741
+ amountCents: number;
742
+ /** As `config/saas.yaml#currency` writes it, e.g. `EUR`. */
743
+ currency: string;
744
+ } | {
745
+ status: 'pending';
746
+ paymentRef: string;
747
+ } | {
748
+ status: 'failed';
749
+ /** `null` where the gateway refused before it created anything. */
750
+ paymentRef: string | null;
751
+ reason: CollectionFailureReason;
752
+ /** The gateway's own code for the reason, for the operator. */
753
+ gatewayCode: string | null;
754
+ };
755
+ /**
756
+ * A refund as the gateway reports it. `pending` and `succeeded` pay the money
757
+ * out; `failed` and `canceled` gave it back to the operator.
758
+ */
759
+ interface GatewayRefund {
760
+ /** The gateway's reference to the refund, unique within its account. */
761
+ refundRef: string;
762
+ /** The gateway's reference to the payment it pays back. */
763
+ paymentRef: string;
764
+ amountCents: number;
765
+ /** As `config/saas.yaml#currency` writes it, e.g. `EUR`. */
766
+ currency: string;
767
+ status: 'pending' | 'succeeded' | 'failed' | 'canceled';
768
+ }
769
+ /**
770
+ * A reversal as the gateway reports it: what it withdrew from the operator and
771
+ * what it gave back, each in total so far, so a report delivered late or twice
772
+ * says what stands rather than what changed. A dispute that withdraws nothing
773
+ * yet, such as an inquiry, is no reversal.
774
+ */
775
+ interface GatewayReversal {
776
+ /** The gateway's reference to it, such as a dispute's, unique within its account. */
777
+ reversalRef: string;
778
+ /** The gateway's reference to the payment it takes back. */
779
+ paymentRef: string;
780
+ /** What it withdrew so far, in cents of `currency`. */
781
+ withdrawnCents: number;
782
+ /** What the gateway gave back of it so far, in cents of `currency`: a dispute won. */
783
+ reinstatedCents: number;
784
+ /** As `config/saas.yaml#currency` writes it, e.g. `EUR`. */
785
+ currency: string;
786
+ }
787
+ /** Which attempt the gateway is asked about. */
788
+ interface FindCollectionInput {
789
+ attemptKey: string;
790
+ customerRef: string;
791
+ /** The gateway's reference, where an earlier answer named one. */
792
+ paymentRef: string | null;
793
+ /** When the attempt was first submitted: nothing created before it is its. */
794
+ submittedAt: Date;
795
+ }
657
796
  /**
658
797
  * One account at a payment gateway: its keys, its form and its callbacks.
659
798
  *
@@ -681,7 +820,34 @@ interface PaymentGateway {
681
820
  * an `immediateCallback` is read for.
682
821
  */
683
822
  readCallback(callback: PaymentGatewayCallback): Promise<PaymentGatewayEvent>;
823
+ /**
824
+ * Collects an invoice with the payment method it announced, without the
825
+ * subscriber present, under `attemptKey`: a repeat of the request with the
826
+ * same key creates nothing new.
827
+ *
828
+ * Answers a refusal — a declined card, a debit the bank turned down — as a
829
+ * `failed` outcome. Throws only where the answer is unknown: the request
830
+ * may or may not have reached the gateway, and the platform asks
831
+ * `findCollection` before it sends anything again.
832
+ */
833
+ collect(input: CollectInvoiceInput): Promise<CollectionOutcome>;
834
+ /**
835
+ * What became of the attempt `attemptKey` names, read from the gateway
836
+ * itself; `null` where the gateway holds nothing under it, so the request
837
+ * never arrived and may be sent again. Throws where the gateway cannot be
838
+ * asked. The platform relies on `null`: where the invoice was paid
839
+ * meanwhile the attempt is settled rather than sent again, and only the
840
+ * gateway's own report could still record a payment it took after all.
841
+ */
842
+ findCollection(input: FindCollectionInput): Promise<CollectionOutcome | null>;
684
843
  }
844
+ /**
845
+ * Whether a collection that failed for `reason` can pass on a second try: an
846
+ * account short of funds and a refusal without a cause can; a closed account,
847
+ * a revoked mandate, a lost card or a payment the subscriber has to confirm
848
+ * cannot, and asks the subscriber to act instead.
849
+ */
850
+ declare function isRetryableCollectionFailure(reason: CollectionFailureReason): boolean;
685
851
  /**
686
852
  * A callback that is not the gateway's: a missing or wrong signature, a stale
687
853
  * timestamp, a body that was altered. Nothing is read from it.
@@ -859,6 +1025,27 @@ interface PlanCatalogSubscribers {
859
1025
  */
860
1026
  customerNumberPrefix?: string;
861
1027
  }
1028
+ /** `config/saas.yaml#invoicing`: how the invoices issued from the charge journal are numbered and when they are due. */
1029
+ interface PlanCatalogInvoicing {
1030
+ /** Put in front of every invoice number: `AHP` gives `AHP-2026-000123`. */
1031
+ numberPrefix: string;
1032
+ /**
1033
+ * Days from an invoice's issue date to the day it is due (`SC-PRIC-046`),
1034
+ * unless it is collected by direct debit.
1035
+ */
1036
+ paymentTermDays: number;
1037
+ /**
1038
+ * Calendar days between an invoice collected by direct debit and the day
1039
+ * it is collected, which the invoice announces and falls due on
1040
+ * (`SC-PRIC-028`). `DIRECT_DEBIT_LEAD_DAYS` where it is not set.
1041
+ */
1042
+ directDebitLeadDays?: number;
1043
+ /**
1044
+ * What a business letter of the issuer states beyond the invoice's own
1045
+ * content, line by line — copied onto every invoice issued (`SC-PRIC-077`).
1046
+ */
1047
+ footer?: string[];
1048
+ }
862
1049
  /** One account at a payment gateway, by the name `PlanCatalogPayments.accounts` gives it. */
863
1050
  interface PlanCatalogPaymentAccount {
864
1051
  /** The provider its bound adapter names itself as, e.g. `stripe`. */
@@ -916,6 +1103,8 @@ interface PlanCatalogSettings {
916
1103
  issuer?: PlanCatalogIssuer;
917
1104
  /** How subscribers are numbered. Optional. */
918
1105
  subscribers?: PlanCatalogSubscribers;
1106
+ /** How invoices are numbered and when they are due; named exactly where invoices are issued. */
1107
+ invoicing?: PlanCatalogInvoicing;
919
1108
  /** The payment gateway accounts. Optional until payment methods are taken. */
920
1109
  payments?: PlanCatalogPayments;
921
1110
  }
@@ -2143,7 +2332,7 @@ interface AdminManifest {
2143
2332
  actions?: AuditActionDef[];
2144
2333
  };
2145
2334
  }
2146
- type StandardPageKey = 'dashboard' | 'tenants' | 'subscriptions' | 'promoCodes' | 'plans' | 'audit' | 'users' | 'pilots' | 'discovery' | 'bundles' | 'marketingCatalog' | 'platformEmail' | 'platformEmailHistory' | 'settings' | 'maintenance';
2335
+ type StandardPageKey = 'dashboard' | 'tenants' | 'subscriptions' | 'promoCodes' | 'plans' | 'audit' | 'users' | 'pilots' | 'discovery' | 'bundles' | 'marketingCatalog' | 'platformEmail' | 'platformEmailHistory' | 'settings' | 'maintenance' | 'featureWithdrawals' | 'reconciliation';
2147
2336
  interface StandardPageDef {
2148
2337
  enabled: boolean;
2149
2338
  requiredCapability?: CapabilityKey;
@@ -2431,6 +2620,35 @@ declare function grossFromNet(net: number, vatRate: number): number;
2431
2620
  declare function netFromGross(gross: number, vatRate: number): number;
2432
2621
  /** The tax a gross amount includes at a rate in per cent: gross × rate / (100 + rate). */
2433
2622
  declare function computeIncludedVat(gross: number, vatRate: number): number;
2623
+ /** One tax rate's part of an invoice: the net of its lines and the tax on that net. */
2624
+ interface TaxAtRate {
2625
+ /** In per cent. */
2626
+ rate: number;
2627
+ net: number;
2628
+ tax: number;
2629
+ }
2630
+ /** An invoice's tax, rate by rate, and the totals it states. */
2631
+ interface TaxPerRate {
2632
+ /** One entry per rate the lines carry, the lowest rate first. */
2633
+ rates: TaxAtRate[];
2634
+ net: number;
2635
+ tax: number;
2636
+ gross: number;
2637
+ }
2638
+ /**
2639
+ * An invoice's tax by the rule of EN 16931: the lines' net is summed per rate,
2640
+ * the rate is applied to each sum and rounded once, and the gross is the net
2641
+ * plus that tax.
2642
+ *
2643
+ * Never the sum of the lines' own rounded taxes, which can differ by cents —
2644
+ * ten lines of 12.34 at 19 % carry 2.34 each, 23.40 together, while 19 % of
2645
+ * 123.40 is 23.45 — and an electronic invoice whose stated tax differs from
2646
+ * the one its format computes is rejected.
2647
+ */
2648
+ declare function taxPerRate(lines: readonly {
2649
+ net: number;
2650
+ rate: number;
2651
+ }[]): TaxPerRate;
2434
2652
 
2435
2653
  type CheckoutOfferLineItemKind = 'plan' | 'bundle' | 'discount';
2436
2654
  /** Frozen billable line item in the offer. */
@@ -2894,6 +3112,23 @@ interface FeatureUiMeta {
2894
3112
  plannedOnly?: boolean;
2895
3113
  /** true = base infrastructure, included in every plan (not bookable). */
2896
3114
  core?: boolean;
3115
+ /**
3116
+ * Set where the feature is withdrawn now or from a date ahead: each
3117
+ * withdrawal of it not over yet, the earliest first — why, from when, and
3118
+ * until when where it is lifted from a date ahead. A feature withdrawn
3119
+ * again from the day it returns carries both. A page that shows the
3120
+ * feature as part of a plan or an add-on shows this beside it, so whoever
3121
+ * concludes knows before they do.
3122
+ */
3123
+ withdrawn?: readonly FeatureWithdrawalMark[];
3124
+ }
3125
+ /** One withdrawal of a feature, as a catalogue marks it beside the feature. */
3126
+ interface FeatureWithdrawalMark {
3127
+ readonly reason: string;
3128
+ /** ISO 8601. */
3129
+ readonly effectiveFrom: string;
3130
+ /** ISO 8601, where it is lifted from a date ahead. */
3131
+ readonly liftedFrom: string | null;
2897
3132
  }
2898
3133
  /** Map FeatureKey → UI metadata. Consumer apps supply a complete table. */
2899
3134
  type FeatureUiRegistry = Record<string, FeatureUiMeta>;
@@ -3220,8 +3455,312 @@ interface BundleVersionSwitchResult {
3220
3455
  readonly takesEffectAt: string;
3221
3456
  }
3222
3457
 
3458
+ /** What a reduction is named for: a plan, or an add-on, by its key. */
3459
+ type FeatureWithdrawalLineKind = 'plan' | 'bundle';
3460
+ /**
3461
+ * The net amount the price of a plan, or of an add-on, is reduced by for one
3462
+ * whole period of `billingCycle` without the feature. A plan or an add-on that
3463
+ * grants the feature and is not named is not reduced.
3464
+ */
3465
+ interface FeatureWithdrawalReduction {
3466
+ readonly kind: FeatureWithdrawalLineKind;
3467
+ /** The plan key, or the add-on's (bundle's) key. */
3468
+ readonly key: string;
3469
+ readonly billingCycle: BillingCycle;
3470
+ readonly amountNet: number;
3471
+ }
3472
+ /** The longest reason a withdrawal carries: the operator's words to the subscribers, not a document. */
3473
+ declare const FEATURE_WITHDRAWAL_REASON_MAX_LENGTH = 1000;
3474
+ /** A withdrawal as it is kept: one per announcement. */
3475
+ interface FeatureWithdrawalRecord {
3476
+ readonly id: string;
3477
+ readonly featureKey: string;
3478
+ /** Why, in the operator's words, as the subscribers are shown it. */
3479
+ readonly reason: string;
3480
+ /** From when the feature is granted to nobody. */
3481
+ readonly effectiveFrom: Date;
3482
+ /** From when it is granted again, once the operator has lifted the withdrawal. */
3483
+ readonly liftedFrom: Date | null;
3484
+ readonly reductions: readonly FeatureWithdrawalReduction[];
3485
+ readonly announcedAt: Date;
3486
+ /** Who announced it — an actor tag, as the audit log writes it. */
3487
+ readonly announcedBy: string;
3488
+ readonly liftedAt: Date | null;
3489
+ readonly liftedBy: string | null;
3490
+ /**
3491
+ * When the subscriptions it reaches were read and their notices recorded;
3492
+ * null until then. Announcing records the withdrawal first and reads who it
3493
+ * reaches once it is recorded, so that a change concluded while it was
3494
+ * being announced is not missed — the quarter-hourly run tells the ones
3495
+ * still null.
3496
+ */
3497
+ readonly toldAt: Date | null;
3498
+ }
3499
+ type NewFeatureWithdrawal = Pick<FeatureWithdrawalRecord, 'featureKey' | 'reason' | 'effectiveFrom' | 'reductions' | 'announcedAt' | 'announcedBy'>;
3500
+ /** What lifting a withdrawal records. */
3501
+ interface FeatureWithdrawalLift {
3502
+ readonly liftedFrom: Date;
3503
+ readonly liftedAt: Date;
3504
+ readonly liftedBy: string;
3505
+ }
3506
+ /**
3507
+ * Whether `withdrawal` takes its feature away at `at`. A withdrawal lifted
3508
+ * before its date never does.
3509
+ */
3510
+ declare function isFeatureWithdrawnAt(withdrawal: Pick<FeatureWithdrawalRecord, 'effectiveFrom' | 'liftedFrom'>, at: Date): boolean;
3511
+ /** The features `withdrawals` take away at `at`. */
3512
+ declare function featuresWithdrawnAt(withdrawals: readonly Pick<FeatureWithdrawalRecord, 'featureKey' | 'effectiveFrom' | 'liftedFrom'>[], at: Date): Set<string>;
3513
+ /**
3514
+ * The first moment after `at` at which what `withdrawals` take away changes —
3515
+ * one takes effect, or is lifted — or null where none is still to come.
3516
+ */
3517
+ declare function nextWithdrawalChange(withdrawals: readonly Pick<FeatureWithdrawalRecord, 'effectiveFrom' | 'liftedFrom'>[], at: Date): Date | null;
3518
+ /**
3519
+ * The manifest capability that announces withdrawing a feature. The platform
3520
+ * sets it where it serves the routes, and the admin UI offers the action only
3521
+ * where it is set.
3522
+ */
3523
+ declare const FEATURE_WITHDRAWAL_CAPABILITY = "features.withdraw";
3524
+ /**
3525
+ * A line of a subscription a withdrawal reaches: the plan in the rhythm it is
3526
+ * billed in, or one booking of an add-on.
3527
+ */
3528
+ interface FeatureWithdrawalLine {
3529
+ readonly line: FeatureWithdrawalLineKind;
3530
+ /** The plan key, or the add-on's key. */
3531
+ readonly key: string;
3532
+ /** The plan's or the add-on's name, as the subscriber reads it. */
3533
+ readonly label: string;
3534
+ /** The booking, where the line is an add-on's; null for the plan. */
3535
+ readonly subscriptionBundleId: string | null;
3536
+ readonly billingCycle: BillingCycle;
3537
+ }
3538
+ /** A line as the subscriber was told of it: with the reduction it carries, or null for none. */
3539
+ interface FeatureWithdrawalNoticeLine extends FeatureWithdrawalLine {
3540
+ readonly reductionNet: number | null;
3541
+ }
3542
+ /**
3543
+ * A feature the subscription holds is withdrawn. Sent once per subscription and
3544
+ * withdrawal, at the announcement, and kept as it was sent: it is the record of
3545
+ * which lines the withdrawal reached and what each is reduced by.
3546
+ */
3547
+ interface FeatureWithdrawnNotice {
3548
+ readonly kind: 'feature-withdrawn';
3549
+ readonly tenantId: string;
3550
+ readonly subscriptionId: string;
3551
+ readonly withdrawalId: string;
3552
+ readonly featureKey: string;
3553
+ readonly featureLabel: string;
3554
+ readonly reason: string;
3555
+ /** ISO 8601. */
3556
+ readonly effectiveFrom: string;
3557
+ readonly lines: readonly FeatureWithdrawalNoticeLine[];
3558
+ /**
3559
+ * Whether the subscription holds the feature through special terms its
3560
+ * contract records and through no line: then it may end at once, and no
3561
+ * reduction applies by itself.
3562
+ */
3563
+ readonly specialTerms: boolean;
3564
+ }
3565
+ /** A withdrawn feature is granted again. Sent once to every subscription told of the withdrawal. */
3566
+ interface FeatureWithdrawalLiftedNotice {
3567
+ readonly kind: 'feature-withdrawal-lifted';
3568
+ readonly tenantId: string;
3569
+ readonly subscriptionId: string;
3570
+ readonly withdrawalId: string;
3571
+ readonly featureKey: string;
3572
+ readonly featureLabel: string;
3573
+ /** ISO 8601. */
3574
+ readonly liftedFrom: string;
3575
+ }
3576
+ /**
3577
+ * The subscription, or one booking of it, ended at once while a feature it
3578
+ * holds was withdrawn: what the account credits the unused rest of the period
3579
+ * already charged from. Recorded by each attempt before it ends anything, so
3580
+ * the credit never lacks its record; an attempt whose end did not happen leaves
3581
+ * one behind, and only the one whose `endedAt` the subscription or the booking
3582
+ * records is sent, counted or credited (`endedAtOnceSubjectOf`).
3583
+ */
3584
+ interface EndedAtOnceNotice {
3585
+ readonly kind: 'ended-at-once';
3586
+ readonly tenantId: string;
3587
+ readonly subscriptionId: string;
3588
+ /** The booking that ended; null where the subscription did, and every booking with it. */
3589
+ readonly subscriptionBundleId: string | null;
3590
+ readonly withdrawalId: string;
3591
+ readonly featureKey: string;
3592
+ readonly featureLabel: string;
3593
+ /** ISO 8601. */
3594
+ readonly endedAt: string;
3595
+ }
3596
+ /** A blocker or a refusal a person reads: a stable code and the values its sentence names. */
3597
+ interface FeatureWithdrawalBlocker {
3598
+ readonly code: string;
3599
+ readonly message: string;
3600
+ readonly params: Record<string, string | number>;
3601
+ }
3602
+ /** A subscription a withdrawal reaches, as the operator previews it. */
3603
+ interface FeatureWithdrawalReachedRow {
3604
+ readonly tenantId: string;
3605
+ readonly subscriptionId: string;
3606
+ readonly status: string;
3607
+ /** Each line with its price per period in its rhythm, net, or null where none is known. */
3608
+ readonly lines: readonly (FeatureWithdrawalLine & {
3609
+ readonly priceNet: number | null;
3610
+ })[];
3611
+ /** Whether it holds the feature through special terms its contract records, and through no line. */
3612
+ readonly specialTerms: boolean;
3613
+ }
3614
+ /** A subscription holding the feature that the withdrawal does not reach: it ends by the date. */
3615
+ interface FeatureWithdrawalSkippedRow {
3616
+ readonly tenantId: string;
3617
+ readonly subscriptionId: string;
3618
+ readonly reason: 'ends-before';
3619
+ }
3620
+ /**
3621
+ * A plan or an add-on in a rhythm the withdrawal reaches, which the operator
3622
+ * may name a reduction for: how many lines it reaches and the lowest price
3623
+ * among them, which a reduction may not exceed.
3624
+ */
3625
+ interface FeatureWithdrawalTarget {
3626
+ readonly kind: FeatureWithdrawalLineKind;
3627
+ readonly key: string;
3628
+ readonly label: string;
3629
+ readonly billingCycle: BillingCycle;
3630
+ readonly lines: number;
3631
+ readonly lowestPriceNet: number | null;
3632
+ }
3633
+ /** What announcing a withdrawal now would do. */
3634
+ interface FeatureWithdrawalPreview {
3635
+ readonly feature: {
3636
+ readonly key: string;
3637
+ readonly label: string;
3638
+ };
3639
+ /** ISO 8601: the date it would take effect. */
3640
+ readonly effectiveFrom: string;
3641
+ /** ISO 8601: the moment it is computed for. */
3642
+ readonly asOf: string;
3643
+ readonly reached: readonly FeatureWithdrawalReachedRow[];
3644
+ readonly skipped: readonly FeatureWithdrawalSkippedRow[];
3645
+ readonly targets: readonly FeatureWithdrawalTarget[];
3646
+ /** Empty where it may be announced as it stands. */
3647
+ readonly blockers: readonly FeatureWithdrawalBlocker[];
3648
+ }
3649
+ /** A withdrawal as the administration reads it: the record, its dates as ISO 8601. */
3650
+ interface FeatureWithdrawalRow {
3651
+ readonly id: string;
3652
+ readonly featureKey: string;
3653
+ readonly reason: string;
3654
+ readonly effectiveFrom: string;
3655
+ readonly liftedFrom: string | null;
3656
+ readonly reductions: readonly FeatureWithdrawalReduction[];
3657
+ readonly announcedAt: string;
3658
+ readonly announcedBy: string;
3659
+ readonly liftedAt: string | null;
3660
+ readonly liftedBy: string | null;
3661
+ /** When the subscriptions it reaches were told; null until then. */
3662
+ readonly toldAt: string | null;
3663
+ }
3664
+ /** The row the administration reads for `record`. */
3665
+ declare function featureWithdrawalRowOf(record: FeatureWithdrawalRecord): FeatureWithdrawalRow;
3666
+ /** What an announcement did. */
3667
+ interface FeatureWithdrawalAnnounced {
3668
+ readonly withdrawal: FeatureWithdrawalRow;
3669
+ /** Notices sent now; the rest are sent by the next run. */
3670
+ readonly told: number;
3671
+ readonly failed: number;
3672
+ }
3673
+ /** What lifting a withdrawal did. */
3674
+ interface FeatureWithdrawalLifted {
3675
+ readonly withdrawal: FeatureWithdrawalRow;
3676
+ readonly told: number;
3677
+ readonly failed: number;
3678
+ }
3679
+ /** A withdrawal as the administration lists it, with how far it has come. */
3680
+ interface FeatureWithdrawalView extends FeatureWithdrawalRow {
3681
+ readonly featureLabel: string;
3682
+ readonly progress: {
3683
+ /** The subscriptions it reached. */
3684
+ readonly reached: number;
3685
+ /** Of those, the ones whose notice reached somebody. */
3686
+ readonly told: number;
3687
+ /** The subscriptions and bookings that ended at once under it. */
3688
+ readonly endedAtOnce: number;
3689
+ };
3690
+ }
3691
+ /** A line of the tenant's subscription a withdrawal reached, as the tenant sees it now. */
3692
+ interface TenantFeatureWithdrawalLine extends FeatureWithdrawalNoticeLine {
3693
+ /**
3694
+ * Whether the reduction still applies: the line runs as it was reached.
3695
+ * A change of plan or rhythm the subscriber made ends it.
3696
+ */
3697
+ readonly reduced: boolean;
3698
+ /**
3699
+ * Where a change scheduled before the announcement brings the line and has
3700
+ * not landed yet: when it lands, ISO 8601, from which the reduction
3701
+ * applies. Null otherwise.
3702
+ */
3703
+ readonly fromChange: string | null;
3704
+ }
3705
+ /** A withdrawal reaching the tenant's subscription, beside its plan and its add-ons. */
3706
+ interface TenantFeatureWithdrawal {
3707
+ readonly withdrawalId: string;
3708
+ readonly featureKey: string;
3709
+ readonly featureLabel: string;
3710
+ readonly reason: string;
3711
+ /** ISO 8601. */
3712
+ readonly effectiveFrom: string;
3713
+ /** ISO 8601, once the operator has lifted it. */
3714
+ readonly liftedFrom: string | null;
3715
+ /** Whether it takes the feature away now. */
3716
+ readonly inEffect: boolean;
3717
+ readonly lines: readonly TenantFeatureWithdrawalLine[];
3718
+ readonly specialTerms: boolean;
3719
+ /** What may be ended at once now: the subscription, and which bookings. */
3720
+ readonly endable: {
3721
+ readonly subscription: boolean;
3722
+ readonly subscriptionBundleIds: readonly string[];
3723
+ };
3724
+ }
3725
+ /**
3726
+ * The features `withdrawals` take away at `now` or from a date ahead, and not
3727
+ * lifted by then, the earliest first: what a catalogue marks beside every plan
3728
+ * and add-on that grants them. A withdrawal lifted before its own date takes
3729
+ * nothing away. One feature can appear twice — withdrawn until a date, and
3730
+ * again from it.
3731
+ */
3732
+ declare function withdrawnFeaturesOf(withdrawals: readonly FeatureWithdrawalRecord[], now: Date): WithdrawnFeature[];
3733
+ /**
3734
+ * A feature withdrawn now or from a date ahead, as a catalogue marks it beside
3735
+ * every plan and add-on that grants it, so whoever concludes is shown it first.
3736
+ */
3737
+ interface WithdrawnFeature extends FeatureWithdrawalMark {
3738
+ readonly featureKey: string;
3739
+ }
3740
+ /** What ending at once now would credit, before the subscriber confirms it. */
3741
+ interface EndAtOncePreview {
3742
+ /** ISO 8601: the moment it ends. */
3743
+ readonly endsAt: string;
3744
+ /** The unused rest of what was charged, net, as a positive amount; 0 where nothing was charged. */
3745
+ readonly creditNet: number;
3746
+ /** ISO 4217, where anything is credited. */
3747
+ readonly currency: string | null;
3748
+ }
3749
+ /** What ending at once did. */
3750
+ interface EndedAtOnce extends EndAtOncePreview {
3751
+ readonly withdrawalId: string;
3752
+ /** The booking that ended; null where the subscription did. */
3753
+ readonly subscriptionBundleId: string | null;
3754
+ }
3755
+ /**
3756
+ * The subject an end at once is recorded under: the subscription or the
3757
+ * booking, and the moment the attempt names, so a later attempt records its
3758
+ * own moment rather than inheriting one whose end never happened.
3759
+ */
3760
+ declare function endedAtOnceSubjectOf(subscriptionOrBookingId: string, at: Date): string;
3761
+
3223
3762
  /** What a notice is about. */
3224
- type SubscriptionNoticeKind = 'version-offered' | 'version-retired' | 'version-retirement-reminder' | 'bundle-version-retired' | 'bundle-version-retirement-reminder' | 'bundle-version-offered';
3763
+ type SubscriptionNoticeKind = 'version-offered' | 'version-retired' | 'version-retirement-reminder' | 'bundle-version-retired' | 'bundle-version-retirement-reminder' | 'bundle-version-offered' | 'feature-withdrawn' | 'feature-withdrawal-lifted' | 'ended-at-once' | 'collection-failed' | 'collection-announced' | 'collection-reversed';
3225
3764
  /** Which notice: there is one per subscription, kind and subject. */
3226
3765
  interface SubscriptionNoticeKey {
3227
3766
  readonly tenantId: string;
@@ -3239,7 +3778,13 @@ interface SubscriptionNoticeKey {
3239
3778
  * the retirement once. For `bundle-version-retirement-reminder`, the id of
3240
3779
  * the add-on version retired as well: that booking is reminded of it once.
3241
3780
  * For `bundle-version-offered`, the id of the add-on version offered: that
3242
- * booking is told of the version once.
3781
+ * booking is told of the version once. For `feature-withdrawn` and
3782
+ * `feature-withdrawal-lifted`, the id of the withdrawal: a subscription is
3783
+ * told of each once. For `ended-at-once`, the id of what ended — the
3784
+ * subscription, or the booking — which ends once. For `collection-failed`,
3785
+ * the key of the attempt that failed; for `collection-announced`, the key
3786
+ * of the attempt announced; for `collection-reversed`, the key of the
3787
+ * attempt whose payment was reversed: each is told once.
3243
3788
  */
3244
3789
  readonly subject: string;
3245
3790
  }
@@ -3292,7 +3837,7 @@ interface BundleVersionOfferedNotice {
3292
3837
  readonly offer: BundleVersionOfferView;
3293
3838
  }
3294
3839
  /** A notice handed to the application to send. */
3295
- type SubscriptionNotice = VersionOfferedNotice | VersionRetiredNotice | VersionRetirementReminder | BundleVersionRetiredNotice | BundleVersionRetirementReminder | BundleVersionOfferedNotice;
3840
+ type SubscriptionNotice = VersionOfferedNotice | VersionRetiredNotice | VersionRetirementReminder | BundleVersionRetiredNotice | BundleVersionRetirementReminder | BundleVersionOfferedNotice | FeatureWithdrawnNotice | FeatureWithdrawalLiftedNotice | EndedAtOnceNotice;
3296
3841
 
3297
3842
  /**
3298
3843
  * A `subscription_notices` row as either adapter reads it back. The two JSON
@@ -3391,6 +3936,31 @@ interface CanonicalBundleVersionRetirementRow {
3391
3936
  /** Reads a row back as a record, naming each column rather than spreading the row. */
3392
3937
  declare function toBundleVersionRetirementRecord(row: CanonicalBundleVersionRetirementRow): BundleVersionRetirementRecord;
3393
3938
 
3939
+ /**
3940
+ * A `feature_withdrawals` row as either adapter reads it back. `reductions` is
3941
+ * `unknown`: the database holds whatever was written to the column.
3942
+ */
3943
+ interface CanonicalFeatureWithdrawalRow {
3944
+ id: string;
3945
+ featureKey: string;
3946
+ reason: string;
3947
+ effectiveFrom: Date;
3948
+ liftedFrom: Date | null;
3949
+ reductions: unknown;
3950
+ announcedAt: Date;
3951
+ announcedBy: string;
3952
+ liftedAt: Date | null;
3953
+ liftedBy: string | null;
3954
+ toldAt: Date | null;
3955
+ }
3956
+ /**
3957
+ * Reads a row back as a record, naming each column rather than spreading the
3958
+ * row. The reductions are checked rather than cast: they are what every
3959
+ * subscription the withdrawal reached is charged less by, and a value nobody
3960
+ * can read must stop at the read and name its row.
3961
+ */
3962
+ declare function toFeatureWithdrawalRecord(row: CanonicalFeatureWithdrawalRow): FeatureWithdrawalRecord;
3963
+
3394
3964
  /** A scheduled change as a subscription row holds it. */
3395
3965
  interface ScheduledChangeColumns {
3396
3966
  readonly pendingPlan: string | null;
@@ -3479,6 +4049,28 @@ declare function maintenanceRetryAfterSeconds(window: MaintenanceWindowRecord, n
3479
4049
  */
3480
4050
  declare function parseZonedInstant(text: string): Date | null;
3481
4051
 
4052
+ /** A calendar day, `YYYY-MM-DD`. */
4053
+ type CalendarDay = string;
4054
+ /**
4055
+ * The day `at` falls on in `timeZone`. Throws a `RangeError` for a zone the
4056
+ * runtime does not know, and for no zone at all — without one `Intl` would
4057
+ * read the host's, and the day would depend on the machine.
4058
+ */
4059
+ declare function dayInZone(at: Date, timeZone: string): CalendarDay;
4060
+ /**
4061
+ * The last day a period covers in `timeZone`. A period ends before `until`, so
4062
+ * its last moment is one millisecond earlier: a month from 1 October to
4063
+ * 1 November covers 31 October as its last day.
4064
+ */
4065
+ declare function lastDayInZone(period: {
4066
+ from: Date;
4067
+ until: Date;
4068
+ }, timeZone: string): CalendarDay;
4069
+ /** The day `days` calendar days after `day`; months and years roll over as the calendar does. */
4070
+ declare function addDaysToDay(day: CalendarDay, days: number): CalendarDay;
4071
+ /** The year a day belongs to. */
4072
+ declare function yearOfDay(day: CalendarDay): number;
4073
+
3482
4074
  /**
3483
4075
  * The top-level blocks of `config/saas.yaml` that are the catalogue rather than
3484
4076
  * the configuration, and the format marker.
@@ -4102,8 +4694,20 @@ interface PromoCodeRepository {
4102
4694
  * together, and the second one's answer is the refusal, not a driver error.
4103
4695
  */
4104
4696
  create(data: CreatePromoCodeData): Promise<PromoCodeRecord>;
4105
- update(id: string, data: UpdatePromoCodeData): Promise<PromoCodeRecord>;
4106
- softDelete(id: string): Promise<void>;
4697
+ /**
4698
+ * Changes the code under `id` only while it is not deleted, in the one
4699
+ * write that changes it, and answers `null` where no such code is there —
4700
+ * none under `id`, or one deleted, even since the platform read it
4701
+ * (`SC-PROMO-032`).
4702
+ */
4703
+ update(id: string, data: UpdatePromoCodeData): Promise<PromoCodeRecord | null>;
4704
+ /**
4705
+ * Marks the code under `id` deleted only while it is not, in the one
4706
+ * write that marks it, and answers whether it did: a second delete,
4707
+ * however close behind the first, leaves the day it was deleted
4708
+ * (`SC-PROMO-032`).
4709
+ */
4710
+ softDelete(id: string): Promise<boolean>;
4107
4711
  /**
4108
4712
  * Atomic slot reservation: increments `redemptionsCount` and checks
4109
4713
  * `status === 'ACTIVE' && (maxRedemptions IS NULL || redemptionsCount + heldCount < maxRedemptions)`.
@@ -4275,76 +4879,527 @@ interface PromoRevenueDeductionAggregator {
4275
4879
  sumGrossForPromoCode(promoCodeId: string): Promise<string>;
4276
4880
  }
4277
4881
 
4278
- /** The adapter that gave an answer, recorded beside the answer. */
4279
- interface TaxAdapterIdentity {
4280
- /** The adapter's package name, such as `@saasicat/tax-de`. */
4281
- name: string;
4282
- /** The adapter's version as published, such as `1.0.0`. */
4283
- version: string;
4882
+ /** What follows a failed collection. */
4883
+ type CollectionFailureNext =
4884
+ /** The same card, or the card now in use, is charged on `on`. */
4885
+ {
4886
+ readonly action: 'charged-again';
4887
+ readonly on: CalendarDay;
4284
4888
  }
4285
- /** The kinds of tax treatment every adapter shares, in the order they are named. */
4286
- declare const TAX_TREATMENT_KINDS: readonly ["standard", "reduced", "exempt", "reverse-charge", "not-taxable", "small-business"];
4889
+ /** A direct debit is announced again, with its own day, in a notice of its own. */
4890
+ | {
4891
+ readonly action: 'announced-again';
4892
+ }
4893
+ /** Nothing is tried again until the subscriber replaces the payment method. */
4894
+ | {
4895
+ readonly action: 'replace-payment-method';
4896
+ };
4897
+ /** The invoice a collection notice is about, as it was issued. */
4898
+ interface CollectionNoticeInvoice {
4899
+ readonly tenantId: string;
4900
+ readonly subscriptionId: string;
4901
+ readonly subscriberId: string;
4902
+ readonly invoiceId: string;
4903
+ readonly invoiceNumber: string;
4904
+ /** What the invoice asks for, of `currency`. */
4905
+ readonly amount: number;
4906
+ readonly currency: string;
4907
+ }
4908
+ /** A collection failed. Told once per failed attempt. */
4909
+ interface CollectionFailedNotice extends CollectionNoticeInvoice {
4910
+ readonly kind: 'collection-failed';
4911
+ readonly paymentMethodType: PaymentMethodType;
4912
+ readonly reason: CollectionFailureReason;
4913
+ readonly next: CollectionFailureNext;
4914
+ }
4915
+ /**
4916
+ * A direct debit announced again, for a day of its own and under the mandate
4917
+ * of the payment method it is collected with. Told once per planned attempt;
4918
+ * it stands on its own and leaves the invoice as it was issued.
4919
+ */
4920
+ interface CollectionAnnouncedNotice extends CollectionNoticeInvoice {
4921
+ readonly kind: 'collection-announced';
4922
+ /** The day the account is debited. */
4923
+ readonly collectOn: CalendarDay;
4924
+ readonly mandateReference: string;
4925
+ /** The last four digits of the account's IBAN. */
4926
+ readonly last4: string;
4927
+ }
4928
+ /** What follows a reversal that opened an invoice again. */
4929
+ type CollectionReversedNext =
4930
+ /** It is collected with the payment method now in use, which replaced the reversed one. */
4931
+ {
4932
+ readonly action: 'collected-with-payment-method-in-use';
4933
+ }
4934
+ /** Nothing is collected until the subscriber replaces the payment method. */
4935
+ | {
4936
+ readonly action: 'replace-payment-method';
4937
+ };
4287
4938
  /**
4288
- * What a tax treatment is, in the words every adapter shares.
4289
- *
4290
- * - `standard` and `reduced`: the issuer's country taxes the charge at a rate.
4291
- * - `exempt`: the charge is exempt in the issuer's country.
4292
- * - `reverse-charge`: the subscriber, a business in another country, owes the
4293
- * tax instead of the issuer.
4294
- * - `not-taxable`: the charge is not taxable in the issuer's country at all,
4295
- * such as a service to a business outside the European Union.
4296
- * - `small-business`: the issuer charges no tax under a small business scheme.
4939
+ * A payment was reversed — a direct debit the bank returned, a chargeback —
4940
+ * and its invoice is open again. Told once per reversed attempt; nothing is
4941
+ * collected again with the payment method the payment was made with.
4297
4942
  */
4298
- type TaxTreatmentKind = (typeof TAX_TREATMENT_KINDS)[number];
4299
- /** The treatment an adapter decided, as a contract and an invoice record it. */
4300
- interface TaxTreatment {
4301
- kind: TaxTreatmentKind;
4302
- /** The rate in percent, such as `19`; `0` for every kind that charges no tax. */
4303
- rate: number;
4304
- /**
4305
- * The sentence the document has to carry for this treatment, such as the
4306
- * reference to the reverse charge; `null` where the law asks for none.
4307
- */
4308
- note: string | null;
4309
- /** Who decided it. */
4310
- adapter: TaxAdapterIdentity;
4943
+ interface CollectionReversedNotice extends CollectionNoticeInvoice {
4944
+ readonly kind: 'collection-reversed';
4945
+ /** How the reversed payment was made. */
4946
+ readonly paymentMethodType: PaymentMethodType;
4947
+ /** What the invoice owes again, of `currency`. */
4948
+ readonly owed: number;
4949
+ readonly next: CollectionReversedNext;
4311
4950
  }
4951
+ /** A notice about collecting an invoice. */
4952
+ type InvoiceCollectionNotice = CollectionFailedNotice | CollectionAnnouncedNotice | CollectionReversedNotice;
4953
+
4312
4954
  /**
4313
- * Where a subscriber stands for tax purposes, as its record stands: what an
4314
- * adapter decides a treatment from.
4955
+ * What made the charge arise. activation: the first period of a subscription. renewal: a later period. planChange: what an immediate plan change adds. bundleBooking: the first, short period of an add-on. bundleChange: what an add-on's switch to a dearer version adds for the rest of its period. credit: a decision that reduces what is owed. correction: a counter-entry reversing an earlier charge, which is how the append-only journal answers a mistake. reductionTakenBack: a reduction granted in advance, taken back for the days it no longer covers — the feature it was granted for came back, or what it reduced ended at once.
4315
4956
  */
4316
- interface SubscriberTaxOrigin {
4317
- /** The country of the billing address, ISO 3166-1 alpha-2; `null` while unknown. */
4318
- country: string | null;
4957
+ type SubscriberChargeOrigin = 'activation' | 'renewal' | 'planChange' | 'bundleBooking' | 'bundleChange' | 'credit' | 'correction' | 'reductionTakenBack';
4958
+ /**
4959
+ * Which kind of contract line the charge realises.
4960
+ */
4961
+ type SubscriberChargeSource = 'plan' | 'bundle' | 'discount';
4962
+ /**
4963
+ * One charge in a subscriber's account: an amount that became due for a period, derived from a line of the contract in force. The journal is append-only — a charge is never updated, and a mistake is answered with a counter-entry rather than an edit, so the account says what happened rather than what somebody thinks today. A charge is net: the tax is decided by the tax adapter when the charge is invoiced, from the subscriber's origin on that day, and computed once per rate on the invoice.
4964
+ */
4965
+ interface SubscriberCharge {
4319
4966
  /**
4320
- * Whether the subscriber is a business, as sign-up or the operator recorded
4321
- * it; `null` while nobody has said. Never derived from a tax identifier: a
4322
- * business outside the European Union may have none.
4967
+ * The charge's own identifier. Never shown to a customer as an invoice number: invoice numbering is sequential, gapless and legally constrained per country, and an identifier somebody has already seen on a screen cannot become one later without confusion.
4323
4968
  */
4324
- business: boolean | null;
4325
- /** The VAT identification number as entered, validated or not. */
4326
- vatId: string | null;
4969
+ id: string;
4327
4970
  /**
4328
- * The same number, only when its latest completed check found it valid;
4329
- * otherwise `null`. An adapter decides as though a subscriber whose number
4330
- * is not validated had none (`SC-PRIC-040`).
4971
+ * The party the contract is concluded with, whose account this is. It outlives the tenant.
4331
4972
  */
4332
- validatedVatId: string | null;
4333
- }
4334
- /** The issuer as an adapter needs it: the operator, as `config/saas.yaml` names it. */
4335
- interface TaxIssuer {
4336
- /** ISO 3166-1 alpha-2; `null` where the configuration names none. */
4337
- country: string | null;
4338
- vatId: string | null;
4339
- }
4340
- /** What an adapter decides a treatment for. */
4341
- interface TaxDecisionRequest {
4342
- issuer: TaxIssuer;
4343
- origin: SubscriberTaxOrigin;
4973
+ subscriberId: string;
4344
4974
  /**
4345
- * The period the charge covers, as a charge records it: from `from` up to
4346
- * `until`, which is the first moment after it. A rate that changed in
4347
- * between is the adapter's to see.
4975
+ * The tenant the subscription belonged to when the charge arose.
4976
+ */
4977
+ tenantId: string;
4978
+ /**
4979
+ * The subscription the charge arose on. Part of the natural key.
4980
+ */
4981
+ subscriptionId: string;
4982
+ /**
4983
+ * The contract whose line the charge realises.
4984
+ */
4985
+ contractId: string;
4986
+ /**
4987
+ * The contract line the charge came from, so that every invoice line can be traced back to what was agreed.
4988
+ */
4989
+ contractLineItemId: string;
4990
+ origin: SubscriberChargeOrigin;
4991
+ source: SubscriberChargeSource;
4992
+ /**
4993
+ * Which thing of its source the charge is for, stable across contracts: the subscription id for the plan, the booking id for an add-on, the discount's key for a discount. Part of the natural key (subscriptionId, source, sourceRef, periodStart, origin), which is unique — a charge derived twice is written once.
4994
+ */
4995
+ sourceRef: string;
4996
+ /**
4997
+ * The start of the period the charge belongs to — the grouping key for an invoice.
4998
+ */
4999
+ periodStart: string;
5000
+ periodEnd: string;
5001
+ /**
5002
+ * ISO 4217, as the contract line records it — recorded per charge so that a charge written in 2026 still means what it meant after the configured currency changes.
5003
+ */
5004
+ currency: string;
5005
+ /**
5006
+ * Net, rounded to the currency's decimal places once, when the charge is written; the written figure is the truth from then on. Negative for a discount.
5007
+ */
5008
+ amountNet: number;
5009
+ /**
5010
+ * When the amount became due. The account is ordered by this, not by when the row was written.
5011
+ */
5012
+ bookedAt: string;
5013
+ createdAt: string;
5014
+ }
5015
+
5016
+ /** A charge as a store reads it back: the wire format, with its dates as dates. */
5017
+ interface SubscriberChargeRecord {
5018
+ id: string;
5019
+ subscriberId: string;
5020
+ tenantId: string;
5021
+ subscriptionId: string;
5022
+ contractId: string;
5023
+ contractLineItemId: string;
5024
+ origin: SubscriberChargeOrigin;
5025
+ source: SubscriberChargeSource;
5026
+ /** The subscription id for the plan, the booking id for an add-on, the discount's key. */
5027
+ sourceRef: string;
5028
+ periodStart: Date;
5029
+ periodEnd: Date;
5030
+ currency: string;
5031
+ /** Net, rounded to the cent when written. Negative for a discount. */
5032
+ amountNet: number;
5033
+ /** When the amount became due. */
5034
+ bookedAt: Date;
5035
+ createdAt: Date;
5036
+ }
5037
+ /** A charge to write: everything but what the store assigns. */
5038
+ type NewSubscriberCharge = Omit<SubscriberChargeRecord, 'id' | 'createdAt'>;
5039
+ /**
5040
+ * The manifest capability that announces the operator's view of an account.
5041
+ * The platform sets it where it serves the view, and the admin UI shows the
5042
+ * view only where it is set.
5043
+ */
5044
+ declare const SUBSCRIBER_ACCOUNT_CAPABILITY = "charges.read";
5045
+ /** Whose account it is, as the operator is shown it. */
5046
+ interface AdminAccountHolder {
5047
+ id: string;
5048
+ /** What the customer quotes, and what an invoice will carry. */
5049
+ customerNumber: string;
5050
+ legalName: string;
5051
+ }
5052
+ /** One charge of an account, with the name its contract line gives it. */
5053
+ interface AdminAccountEntry {
5054
+ /** The charge as the journal holds it. */
5055
+ charge: SubscriberCharge;
5056
+ /**
5057
+ * The contract line's own title, as it was when the contract was
5058
+ * concluded, or `null` where that line cannot be read.
5059
+ */
5060
+ title: string | null;
5061
+ }
5062
+ /**
5063
+ * A tenant's account as the operator reads it: the charges of the subscription
5064
+ * it holds, newest first — by when each became due, then by its period, then
5065
+ * the plan before its add-ons before its discounts.
5066
+ *
5067
+ * No total: without invoices and payments, a sum would be what was charged so
5068
+ * far, and it would be read as what is owed.
5069
+ */
5070
+ interface AdminSubscriberAccount {
5071
+ /** `null` for a tenant that has no subscriber. */
5072
+ holder: AdminAccountHolder | null;
5073
+ entries: AdminAccountEntry[];
5074
+ }
5075
+
5076
+ /** The issuer an invoice names, as of its issue date. */
5077
+ interface SubscriptionInvoiceIssuer extends LegalIdentity, PartyAddress {
5078
+ }
5079
+ /** The subscriber an invoice names, copied from its record on the issue date. */
5080
+ interface SubscriptionInvoiceSubscriber extends LegalIdentity, PartyAddress {
5081
+ customerNumber: string;
5082
+ }
5083
+ /** One line of an invoice: one charge, as the invoice states it. */
5084
+ interface SubscriptionInvoiceLineRecord {
5085
+ id: string;
5086
+ invoiceId: string;
5087
+ /** From 1, in the order the invoice lists its lines. */
5088
+ position: number;
5089
+ /** The charge the line invoices; a charge stands on one invoice (`SC-PRIC-022`). */
5090
+ chargeId: string;
5091
+ /** The contract line the charge came from (`SC-AUD-013`). */
5092
+ contractLineItemId: string;
5093
+ /** What the line is for, as the contract line names it. */
5094
+ title: string;
5095
+ origin: SubscriberChargeOrigin;
5096
+ source: SubscriberChargeSource;
5097
+ /** The first day the charge covers, in the installation's time zone. */
5098
+ periodFrom: CalendarDay;
5099
+ /** The last day the charge covers, in the installation's time zone. */
5100
+ periodUntil: CalendarDay;
5101
+ /** Net, as the charge was written. Negative for a discount. */
5102
+ amountNet: number;
5103
+ /** In per cent: the rate of the invoice's treatment. */
5104
+ taxRate: number;
5105
+ }
5106
+ /** A line to write: everything but what the store assigns. */
5107
+ type NewSubscriptionInvoiceLine = Omit<SubscriptionInvoiceLineRecord, 'id' | 'invoiceId'>;
5108
+ /**
5109
+ * The payment method an invoice is collected with, copied from the
5110
+ * subscriber's on the day it was issued — what the invoice tells the
5111
+ * subscriber, so a later change leaves it as it was (`SC-PRIC-028`).
5112
+ */
5113
+ interface SubscriptionInvoicePayment {
5114
+ /** The subscriber's payment method, which the collection charges. */
5115
+ paymentMethodId: string;
5116
+ /** The account in `config/saas.yaml#payments.accounts` that holds it. */
5117
+ gatewayAccount: string;
5118
+ type: PaymentMethodType;
5119
+ /** The card network, such as `visa`; `null` for a direct debit. */
5120
+ brand: string | null;
5121
+ /** The last four digits of the card number or the IBAN. */
5122
+ last4: string;
5123
+ /** The mandate a direct debit is collected under; `null` for a card. */
5124
+ mandateReference: string | null;
5125
+ }
5126
+ /** An invoice as a store reads it back. */
5127
+ interface SubscriptionInvoiceRecord {
5128
+ id: string;
5129
+ /** `<prefix>-<year>-<sequence>`, e.g. `AHP-2026-000123` (`formatInvoiceNumber`). */
5130
+ number: string;
5131
+ numberPrefix: string;
5132
+ /** The year of the issue date, which the sequence restarts with. */
5133
+ numberYear: number;
5134
+ /** From 1 each year, without gaps. */
5135
+ numberSequence: number;
5136
+ tenantId: string;
5137
+ subscriberId: string;
5138
+ subscriptionId: string;
5139
+ /** The contract the invoiced charges belong to. */
5140
+ contractId: string;
5141
+ issuedAt: Date;
5142
+ /** The day it was issued, in the installation's time zone. */
5143
+ issueDate: CalendarDay;
5144
+ /**
5145
+ * The day it is due (`SC-PRIC-046`): the collection date where it is
5146
+ * collected by direct debit, the issue date plus the payment term otherwise.
5147
+ */
5148
+ dueDate: CalendarDay;
5149
+ /**
5150
+ * The payment method it is collected with, as it stood when the invoice
5151
+ * was issued; `null` where it is not collected — the subscriber had no
5152
+ * payment method that can be, or the invoice asks for nothing.
5153
+ */
5154
+ payment: SubscriptionInvoicePayment | null;
5155
+ /**
5156
+ * The day a direct debit is collected from, which the invoice announces
5157
+ * with its amount and mandate reference (`SC-PRIC-028`): the issue date
5158
+ * plus the lead time. `null` unless `payment` is a direct debit.
5159
+ */
5160
+ collectionDate: CalendarDay | null;
5161
+ /** The first day its charges cover. */
5162
+ servicePeriodFrom: CalendarDay;
5163
+ /** The last day its charges cover. */
5164
+ servicePeriodUntil: CalendarDay;
5165
+ currency: string;
5166
+ issuer: SubscriptionInvoiceIssuer;
5167
+ subscriber: SubscriptionInvoiceSubscriber;
5168
+ /**
5169
+ * The lines `config/saas.yaml` named under `invoicing.footer` on the issue
5170
+ * date — what a business letter of the issuer states beyond the invoice's
5171
+ * own content (`SC-PRIC-077`); none where it named none.
5172
+ */
5173
+ footer: string[];
5174
+ /** The treatment the tax adapter decided when it was issued, with its name and version. */
5175
+ taxTreatment: TaxTreatment;
5176
+ /** The tax, rate by rate, computed once per rate (`SC-PRIC-041`). */
5177
+ taxes: TaxAtRate[];
5178
+ totalNet: number;
5179
+ totalTax: number;
5180
+ totalGross: number;
5181
+ lines: SubscriptionInvoiceLineRecord[];
5182
+ createdAt: Date;
5183
+ }
5184
+ /**
5185
+ * An invoice to issue: everything but what the store assigns — the id, and
5186
+ * the number, which the store draws when it writes the invoice.
5187
+ */
5188
+ interface NewSubscriptionInvoice extends Omit<SubscriptionInvoiceRecord, 'id' | 'number' | 'numberSequence' | 'lines' | 'createdAt'> {
5189
+ lines: NewSubscriptionInvoiceLine[];
5190
+ }
5191
+ /** How many digits an invoice number's sequence is written with, at least. */
5192
+ declare const INVOICE_SEQUENCE_DIGITS = 6;
5193
+ /**
5194
+ * The number an invoice carries: the prefix `config/saas.yaml` names, the year
5195
+ * the sequence counts in, and the sequence written with at least six digits —
5196
+ * `formatInvoiceNumber('AHP', 2026, 123)` is `AHP-2026-000123`.
5197
+ */
5198
+ declare function formatInvoiceNumber(prefix: string, year: number, sequence: number): string;
5199
+
5200
+ /**
5201
+ * The manifest capability that announces the operator's download of an
5202
+ * invoice's archived document. The platform sets it where it serves the route.
5203
+ */
5204
+ declare const INVOICE_DOCUMENT_CAPABILITY = "invoices.read";
5205
+ /** A rendered invoice: its bytes, as a file. */
5206
+ interface InvoiceDocument {
5207
+ content: Uint8Array;
5208
+ /** `application/pdf` for a ZUGFeRD invoice. */
5209
+ mediaType: string;
5210
+ /** What a person saving it would call it, such as `AHP-2026-000123.pdf`. */
5211
+ fileName: string;
5212
+ }
5213
+ /**
5214
+ * Renders an invoice into the file the tax adapter's law requires — the
5215
+ * application's own renderer, or the default one SaaSiCat ships.
5216
+ *
5217
+ * Given the invoice as it was issued, it renders the same bytes every time, so
5218
+ * a repeated attempt archives the file whose checksum was recorded. Whatever
5219
+ * it would take from the clock, such as a PDF's creation date, it takes from
5220
+ * the invoice's `issuedAt`. A renderer updated between two attempts renders
5221
+ * other bytes; while nothing is archived, those take the place of the ones
5222
+ * recorded, and the audit log says so (`SC-AUD-019`).
5223
+ *
5224
+ * An invoice collected by direct debit is the notice SEPA asks for before the
5225
+ * debit: its document states the amount, the `collectionDate` and the
5226
+ * `payment.mandateReference` (`SC-PRIC-028`).
5227
+ */
5228
+ interface InvoiceRenderer {
5229
+ render(invoice: SubscriptionInvoiceRecord): Promise<InvoiceDocument>;
5230
+ }
5231
+ /** A document to archive: the file, under its invoice, with the checksum recorded for it. */
5232
+ interface InvoiceDocumentToArchive extends InvoiceDocument {
5233
+ invoiceId: string;
5234
+ /** SHA-256 of `content`, lower-case hex. */
5235
+ checksum: string;
5236
+ archivedAt: Date;
5237
+ }
5238
+ /** A document as the archive hands it back. */
5239
+ type ArchivedInvoiceDocument = InvoiceDocumentToArchive;
5240
+ /**
5241
+ * Keeps each invoice's document, unalterable, for as long as the law asks —
5242
+ * in Germany 8 years from the end of the calendar year it was issued in, in
5243
+ * the European Union. The shipped adapters keep it in the database
5244
+ * (`SubscriptionInvoiceArchive`, which refuses every update and delete);
5245
+ * object storage with a retention lock is another way to implement it.
5246
+ */
5247
+ interface InvoiceArchivePort {
5248
+ /**
5249
+ * Stores the document under its invoice. Storing it again with the same
5250
+ * checksum is the same write and changes nothing; another checksum for an
5251
+ * invoice already archived is refused with
5252
+ * `SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED`, and the first stays.
5253
+ */
5254
+ store(document: InvoiceDocumentToArchive): Promise<void>;
5255
+ /** The document archived under the invoice, or `null` where none is. */
5256
+ read(invoiceId: string): Promise<ArchivedInvoiceDocument | null>;
5257
+ /**
5258
+ * Why the archive would let a document it keeps be changed or removed, or
5259
+ * `null` where it would not. Asked when invoices start, which are refused
5260
+ * while it names a reason: an archive that is not unalterable keeps no
5261
+ * document as the law asks, and would only be found out at an audit.
5262
+ */
5263
+ protectionProblem(): Promise<string | null>;
5264
+ }
5265
+ /** An invoice on its way to the subscriber. */
5266
+ interface InvoiceMail {
5267
+ invoice: SubscriptionInvoiceRecord;
5268
+ /** The invoice email on the subscriber's record. */
5269
+ to: string;
5270
+ /** The archived file, to attach. */
5271
+ document: InvoiceDocument;
5272
+ }
5273
+ /** A notice about collecting an invoice on its way to the subscriber. */
5274
+ interface InvoiceNoticeMail {
5275
+ notice: InvoiceCollectionNotice;
5276
+ /** The invoice email on the subscriber's record. */
5277
+ to: string;
5278
+ }
5279
+ /**
5280
+ * Sends an invoice to the subscriber with its file attached (`SC-PRIC-047`),
5281
+ * and what the subscriber is told about collecting it (`SC-PRIC-028`,
5282
+ * `SC-PRIC-080`).
5283
+ *
5284
+ * The application words the message — in the subscriber's language, with a
5285
+ * link to the tenant's sign-in rather than to the file itself — and sends it
5286
+ * with its own mail infrastructure. It rejects where the message could not be
5287
+ * handed on; the platform then shows the failure to the operator, with the
5288
+ * rejection's message as the reason and the recipient's address taken out of
5289
+ * it, and tries again on the next run. The invoice stays issued either way: delivery is not
5290
+ * what makes it an invoice.
5291
+ *
5292
+ * A run claims the invoice before it calls this, so of several instances one
5293
+ * sends it. One that does not answer within a minute holds the invoice for
5294
+ * its answer: a late success is recorded, a late failure tried again.
5295
+ */
5296
+ interface InvoiceMailPort {
5297
+ deliver(mail: InvoiceMail): Promise<void>;
5298
+ /**
5299
+ * Tells the subscriber that a collection failed and what follows, or the
5300
+ * day a direct debit announced again is collected under which mandate.
5301
+ * The application words it as it words the invoice; a direct debit's
5302
+ * announcement names the amount, the day and the mandate reference. It
5303
+ * rejects where the message could not be handed on, and the next run tries
5304
+ * again; each notice is sent once however many instances run.
5305
+ */
5306
+ tell(mail: InvoiceNoticeMail): Promise<void>;
5307
+ }
5308
+ /** Where an invoice's document stands, as the invoice records it. */
5309
+ interface SubscriptionInvoiceDocumentRecord {
5310
+ invoiceId: string;
5311
+ /** SHA-256 of the rendered file, lower-case hex, recorded before it is archived. */
5312
+ checksum: string;
5313
+ mediaType: string;
5314
+ fileName: string;
5315
+ /** In bytes. */
5316
+ size: number;
5317
+ renderedAt: Date;
5318
+ /** When the archive confirmed it; `null` while the invoice waits for its document. */
5319
+ archivedAt: Date | null;
5320
+ /**
5321
+ * When the run that is mailing it took it on; `null` while no run holds it.
5322
+ * A claim older than the lease is taken on by the next run.
5323
+ */
5324
+ deliveryClaimedAt: Date | null;
5325
+ /** When it was handed to the mail; `null` until then. */
5326
+ deliveredAt: Date | null;
5327
+ /** The address it was sent to. */
5328
+ deliveredTo: string | null;
5329
+ }
5330
+ /** What is recorded of a rendering before its file is archived. */
5331
+ type NewInvoiceRendering = Pick<SubscriptionInvoiceDocumentRecord, 'checksum' | 'mediaType' | 'fileName' | 'size' | 'renderedAt'>;
5332
+
5333
+ /** The adapter that gave an answer, recorded beside the answer. */
5334
+ interface TaxAdapterIdentity {
5335
+ /** The adapter's package name, such as `@saasicat/tax-de`. */
5336
+ name: string;
5337
+ /** The adapter's version as published, such as `1.0.0`. */
5338
+ version: string;
5339
+ }
5340
+ /** The kinds of tax treatment every adapter shares, in the order they are named. */
5341
+ declare const TAX_TREATMENT_KINDS: readonly ["standard", "reduced", "exempt", "reverse-charge", "not-taxable", "small-business"];
5342
+ /**
5343
+ * What a tax treatment is, in the words every adapter shares.
5344
+ *
5345
+ * - `standard` and `reduced`: the issuer's country taxes the charge at a rate.
5346
+ * - `exempt`: the charge is exempt in the issuer's country.
5347
+ * - `reverse-charge`: the subscriber, a business in another country, owes the
5348
+ * tax instead of the issuer.
5349
+ * - `not-taxable`: the charge is not taxable in the issuer's country at all,
5350
+ * such as a service to a business outside the European Union.
5351
+ * - `small-business`: the issuer charges no tax under a small business scheme.
5352
+ */
5353
+ type TaxTreatmentKind = (typeof TAX_TREATMENT_KINDS)[number];
5354
+ /** The treatment an adapter decided, as a contract and an invoice record it. */
5355
+ interface TaxTreatment {
5356
+ kind: TaxTreatmentKind;
5357
+ /** The rate in percent, such as `19`; `0` for every kind that charges no tax. */
5358
+ rate: number;
5359
+ /**
5360
+ * The sentence the document has to carry for this treatment, such as the
5361
+ * reference to the reverse charge; `null` where the law asks for none.
5362
+ */
5363
+ note: string | null;
5364
+ /** Who decided it. */
5365
+ adapter: TaxAdapterIdentity;
5366
+ }
5367
+ /**
5368
+ * Where a subscriber stands for tax purposes, as its record stands: what an
5369
+ * adapter decides a treatment from.
5370
+ */
5371
+ interface SubscriberTaxOrigin {
5372
+ /** The country of the billing address, ISO 3166-1 alpha-2; `null` while unknown. */
5373
+ country: string | null;
5374
+ /**
5375
+ * Whether the subscriber is a business, as sign-up or the operator recorded
5376
+ * it; `null` while nobody has said. Never derived from a tax identifier: a
5377
+ * business outside the European Union may have none.
5378
+ */
5379
+ business: boolean | null;
5380
+ /** The VAT identification number as entered, validated or not. */
5381
+ vatId: string | null;
5382
+ /**
5383
+ * The same number, only when its latest completed check found it valid;
5384
+ * otherwise `null`. An adapter decides as though a subscriber whose number
5385
+ * is not validated had none (`SC-PRIC-040`).
5386
+ */
5387
+ validatedVatId: string | null;
5388
+ }
5389
+ /** The issuer as an adapter needs it: the operator, as `config/saas.yaml` names it. */
5390
+ interface TaxIssuer {
5391
+ /** ISO 3166-1 alpha-2; `null` where the configuration names none. */
5392
+ country: string | null;
5393
+ vatId: string | null;
5394
+ }
5395
+ /** What an adapter decides a treatment for. */
5396
+ interface TaxDecisionRequest {
5397
+ issuer: TaxIssuer;
5398
+ origin: SubscriberTaxOrigin;
5399
+ /**
5400
+ * The period the charge covers, as a charge records it: from `from` up to
5401
+ * `until`, which is the first moment after it. A rate that changed in
5402
+ * between is the adapter's to see.
4348
5403
  */
4349
5404
  period: {
4350
5405
  from: Date;
@@ -4433,6 +5488,53 @@ interface TaxAdapter extends TaxAdapterIdentity {
4433
5488
  * an answer the adapter cannot read are each a check that did not complete.
4434
5489
  */
4435
5490
  checkVatId(vatId: string, issuer: TaxIssuer): Promise<VatIdCheckOutcome>;
5491
+ /**
5492
+ * An invoice's tax by the rule this adapter's law names (`SC-PRIC-041`):
5493
+ * per rate, with the totals the invoice states. The amount it states is
5494
+ * the amount collected and the amount a payment settles.
5495
+ */
5496
+ invoiceTax(lines: readonly InvoiceTaxLine[]): TaxPerRate;
5497
+ /**
5498
+ * What an invoice lacks of the content the law requires of it
5499
+ * (`SC-PRIC-027`), as the fields it misses — `issuer.taxIdentifier`,
5500
+ * `subscriber.postalCode` — or none where it is complete. Asked before the
5501
+ * number is drawn; an invoice that lacks anything is not issued.
5502
+ */
5503
+ invoiceContentGaps(draft: InvoiceContentDraft): readonly string[];
5504
+ /**
5505
+ * What a rendered document lacks of the format the law requires
5506
+ * (`SC-PRIC-042`), or disagrees with in the invoice it was rendered from —
5507
+ * `format.embeddedXml`, `xml.totalGross` — or none where it is the file to
5508
+ * issue. A document with anything here is not archived, sent or offered;
5509
+ * the invoice keeps its number and waits for a document that passes.
5510
+ */
5511
+ invoiceDocumentGaps(document: InvoiceDocument, invoice: SubscriptionInvoiceRecord): Promise<readonly string[]>;
5512
+ }
5513
+ /** A line as an invoice's tax is computed from it. */
5514
+ interface InvoiceTaxLine {
5515
+ net: number;
5516
+ /** In per cent. */
5517
+ rate: number;
5518
+ }
5519
+ /**
5520
+ * What an invoice says, without its number: what the adapter checks against
5521
+ * the content the law requires before the number is drawn.
5522
+ */
5523
+ interface InvoiceContentDraft {
5524
+ issuer: LegalIdentity & PartyAddress;
5525
+ subscriber: LegalIdentity & PartyAddress;
5526
+ treatment: TaxTreatment;
5527
+ issueDate: string;
5528
+ dueDate: string;
5529
+ servicePeriod: {
5530
+ from: string;
5531
+ until: string;
5532
+ };
5533
+ lines: readonly {
5534
+ title: string;
5535
+ net: number;
5536
+ rate: number;
5537
+ }[];
4436
5538
  }
4437
5539
 
4438
5540
  type ContractLineItemKind = 'plan' | 'bundle' | 'discount';
@@ -5050,125 +6152,673 @@ type AdminSubscriberHistoryEntry = {
5050
6152
  };
5051
6153
 
5052
6154
  /**
5053
- * What made the charge arise. activation: the first period of a subscription. renewal: a later period. planChange: what an immediate plan change adds. bundleBooking: the first, short period of an add-on. bundleChange: what an add-on's switch to a dearer version adds for the rest of its period. credit: a decision that reduces what is owed. correction: a counter-entry reversing an earlier charge, which is how the append-only journal answers a mistake.
6155
+ * Where an attempt stands: `SCHEDULED` while it is planned for a day and has
6156
+ * not left; `SUBMITTED` once it is written as sent, before its request leaves,
6157
+ * and until an answer is recorded; `PENDING` while a direct debit is on its
6158
+ * way; `SUCCEEDED` and `FAILED` once it is settled; `WITHDRAWN` where a planned
6159
+ * one will not be made, because the payment method it was planned with is no
6160
+ * longer in use; `REVERSED` where it succeeded and a reversal of its payment —
6161
+ * a returned direct debit, a chargeback — opened its invoice again, which is
6162
+ * then collected only with another payment method (`SC-PRIC-085`).
6163
+ */
6164
+ type InvoiceCollectionStatus = 'SCHEDULED' | 'SUBMITTED' | 'PENDING' | 'SUCCEEDED' | 'FAILED' | 'WITHDRAWN' | 'REVERSED';
6165
+ /** An attempt as a store reads it back. */
6166
+ interface InvoiceCollectionRecord {
6167
+ id: string;
6168
+ invoiceId: string;
6169
+ /** From 1, per invoice. */
6170
+ attempt: number;
6171
+ /** `collectionAttemptKey(invoiceId, attempt)`: the key every request of this attempt carries. */
6172
+ attemptKey: string;
6173
+ /** The account in `config/saas.yaml#payments.accounts` the request went to. */
6174
+ gatewayAccount: string;
6175
+ /** The subscriber's payment method it charges. */
6176
+ paymentMethodId: string;
6177
+ paymentMethodType: PaymentMethodType;
6178
+ customerRef: string;
6179
+ paymentMethodRef: string;
6180
+ /** The invoice's number, as the request names it. */
6181
+ invoiceNumber: string;
6182
+ /** The invoice's gross amount, of `currency`; the request carries it in cents. */
6183
+ amount: number;
6184
+ currency: string;
6185
+ status: InvoiceCollectionStatus;
6186
+ /** The gateway's reference to what it created; `null` until an answer names one. */
6187
+ paymentRef: string | null;
6188
+ /** Why it failed; `null` unless it did. */
6189
+ failureReason: CollectionFailureReason | null;
6190
+ /** The gateway's own code for the failure. */
6191
+ failureCode: string | null;
6192
+ /**
6193
+ * When it was written as sent and its request first left; `null` while it
6194
+ * is planned, and for a planned one withdrawn before it left.
6195
+ */
6196
+ submittedAt: Date | null;
6197
+ /**
6198
+ * When a run last took it on — to send it, to send it again, or to ask
6199
+ * the gateway about it. Another run leaves it alone until this is old
6200
+ * enough (`INVOICE_COLLECTION_LEASE_MS`, `INVOICE_COLLECTION_ASK_EVERY_MS`).
6201
+ * `null` where `submittedAt` is.
6202
+ */
6203
+ heldAt: Date | null;
6204
+ /** When it was settled, or withdrawn; `null` while it is not. */
6205
+ resolvedAt: Date | null;
6206
+ /**
6207
+ * The day a planned attempt is collected from; `null` for one written as
6208
+ * sent from the start, which the invoice's own date governs. A direct
6209
+ * debit's is the earliest day until it is announced, and the day its
6210
+ * announcement names after.
6211
+ */
6212
+ collectOn: CalendarDay | null;
6213
+ /** When a planned direct debit's announcement reached the subscriber; `null` until it did. */
6214
+ announcedAt: Date | null;
6215
+ /**
6216
+ * When what follows a failure or a reversal was decided — the subscriber's
6217
+ * notice recorded, and the next attempt planned where one is made; `null`
6218
+ * until it was, and for an attempt that neither failed nor was reversed.
6219
+ */
6220
+ followedUpAt: Date | null;
6221
+ }
6222
+ /** An attempt that has been sent: its request carries a moment, and a run holds it. */
6223
+ type SubmittedInvoiceCollection = InvoiceCollectionRecord & {
6224
+ submittedAt: Date;
6225
+ heldAt: Date;
6226
+ };
6227
+ /**
6228
+ * `attempt` as one that has been sent. Throws for one that has not left, which
6229
+ * a run never meets where it reads an attempt it sent or holds.
5054
6230
  */
5055
- type SubscriberChargeOrigin = 'activation' | 'renewal' | 'planChange' | 'bundleBooking' | 'bundleChange' | 'credit' | 'correction';
6231
+ declare function sentCollectionOf(attempt: InvoiceCollectionRecord): SubmittedInvoiceCollection;
6232
+ /** An attempt to start: what its request carries, and the moment it is taken on. */
6233
+ interface NewInvoiceCollection {
6234
+ invoiceId: string;
6235
+ gatewayAccount: string;
6236
+ paymentMethodId: string;
6237
+ paymentMethodType: PaymentMethodType;
6238
+ customerRef: string;
6239
+ paymentMethodRef: string;
6240
+ invoiceNumber: string;
6241
+ amount: number;
6242
+ currency: string;
6243
+ /** Written as both `submittedAt` and `heldAt`. */
6244
+ at: Date;
6245
+ }
6246
+ /** An attempt to plan for `collectOn`: what its request will carry. */
6247
+ interface PlannedInvoiceCollection {
6248
+ invoiceId: string;
6249
+ /**
6250
+ * The number of the invoice's last attempt the plan follows — `0` where it
6251
+ * has none. A run decides what follows from the attempts it read; one that
6252
+ * read them before another run added an attempt plans nothing.
6253
+ */
6254
+ after: number;
6255
+ gatewayAccount: string;
6256
+ paymentMethodId: string;
6257
+ paymentMethodType: PaymentMethodType;
6258
+ customerRef: string;
6259
+ paymentMethodRef: string;
6260
+ invoiceNumber: string;
6261
+ amount: number;
6262
+ currency: string;
6263
+ /** The day it is collected from; for a direct debit, the earliest such day. */
6264
+ collectOn: CalendarDay;
6265
+ }
5056
6266
  /**
5057
- * Which kind of contract line the charge realises.
6267
+ * How long a run's hold on an attempt lasts. Longer than a request may take,
6268
+ * so a run does not ask the gateway about, or send again, a request another
6269
+ * run is still waiting for.
5058
6270
  */
5059
- type SubscriberChargeSource = 'plan' | 'bundle' | 'discount';
6271
+ declare const INVOICE_COLLECTION_LEASE_MS: number;
5060
6272
  /**
5061
- * One charge in a subscriber's account: an amount that became due for a period, derived from a line of the contract in force. The journal is append-only — a charge is never updated, and a mistake is answered with a counter-entry rather than an edit, so the account says what happened rather than what somebody thinks today. A charge is net: the tax is decided by the tax adapter when the charge is invoiced, from the subscriber's origin on that day, and computed once per rate on the invoice.
6273
+ * How often a direct debit on its way is asked about. Most are settled within
6274
+ * six business days, and the gateway's own report of it is an event of its
6275
+ * own; asking is what finds the outcome where no report arrives.
5062
6276
  */
5063
- interface SubscriberCharge {
5064
- /**
5065
- * The charge's own identifier. Never shown to a customer as an invoice number: invoice numbering is sequential, gapless and legally constrained per country, and an identifier somebody has already seen on a screen cannot become one later without confusion.
5066
- */
6277
+ declare const INVOICE_COLLECTION_ASK_EVERY_MS: number;
6278
+ /**
6279
+ * The key every request of an attempt carries, and that the gateway keeps
6280
+ * with what it creates: `saasicat:collect:<invoice>:<attempt>`. The same for
6281
+ * one attempt however often its request is repeated, and another for the next
6282
+ * attempt of the same invoice.
6283
+ */
6284
+ declare function collectionAttemptKey(invoiceId: string, attempt: number): string;
6285
+ /** The status an outcome settles an attempt in. */
6286
+ declare function collectionStatusOf(outcome: CollectionOutcome): InvoiceCollectionStatus;
6287
+ /**
6288
+ * What an attempt whose request never reached the gateway is settled with
6289
+ * where its invoice was paid meanwhile — a late payment for an earlier
6290
+ * attempt — instead of being sent again: failed, for no reason the
6291
+ * subscriber has to act on, under SaaSiCat's own code.
6292
+ */
6293
+ declare const COLLECTION_NOT_SENT_PAID: CollectionOutcome;
6294
+ /**
6295
+ * The same for an attempt whose payment method a payment of its invoice was
6296
+ * reversed on meanwhile: sent now, it would collect with that payment method
6297
+ * again (`SC-PRIC-085`). The reversal's notice tells the subscriber what
6298
+ * follows.
6299
+ */
6300
+ declare const COLLECTION_NOT_SENT_REVERSED: CollectionOutcome;
6301
+ /**
6302
+ * What `abandonPaid` found for an attempt whose request never reached the
6303
+ * gateway: `abandoned` — its invoice owes nothing, and it is settled as
6304
+ * `COLLECTION_NOT_SENT_PAID`; `resend` — it is still `SUBMITTED` and its
6305
+ * invoice still owes, so the same request is sent again; `settled` — it is no
6306
+ * longer `SUBMITTED`, a report having settled it or put it on its way
6307
+ * meanwhile, and nothing is sent.
6308
+ */
6309
+ type AbandonPaidOutcome = 'abandoned' | 'resend' | 'settled';
6310
+
6311
+ /** What a case is about: a refund no credit takes, or a reversal no credit takes. */
6312
+ type ReconciliationCaseKind = 'REFUND_UNMATCHED' | 'REVERSAL_UNMATCHED';
6313
+ /** A case to reconcile, as a store reads it back. */
6314
+ interface SubscriberReconciliationCaseRecord {
5067
6315
  id: string;
5068
- /**
5069
- * The party the contract is concluded with, whose account this is. It outlives the tenant.
5070
- */
5071
6316
  subscriberId: string;
5072
- /**
5073
- * The tenant the subscription belonged to when the charge arose.
5074
- */
6317
+ /** The tenant the payment's invoice was for, as a trace. */
5075
6318
  tenantId: string;
6319
+ kind: ReconciliationCaseKind;
6320
+ /** What matched nothing, positive, of `currency`. */
6321
+ amount: number;
6322
+ currency: string;
6323
+ /** The payment the refund pays back, or the reversal takes back. */
6324
+ paymentId: string;
6325
+ /** The refund, for a `REFUND_UNMATCHED`; `null` otherwise. */
6326
+ refundId: string | null;
6327
+ /** The reversal, for a `REVERSAL_UNMATCHED`; `null` otherwise. */
6328
+ reversalId: string | null;
6329
+ gatewayAccount: string;
6330
+ /** The refund's or the reversal's reference at the gateway, which the operator finds it under. */
6331
+ gatewayRef: string;
6332
+ recordedAt: Date;
6333
+ /** When it was closed; `null` while it is open. */
6334
+ closedAt: Date | null;
6335
+ /** Who closed it; `null` while it is open, and where SaaSiCat closed it. */
6336
+ closedBy: string | null;
6337
+ /** Why it was closed, in the operator's words or SaaSiCat's; `null` while it is open. */
6338
+ note: string | null;
6339
+ }
6340
+ /** An operator closing a case. */
6341
+ interface CloseReconciliationCase {
6342
+ caseId: string;
6343
+ note: string;
6344
+ /** Who closes it. */
6345
+ closedBy: string;
6346
+ at: Date;
6347
+ }
6348
+ /** What closing a case did. */
6349
+ type ClosedReconciliationCase = {
6350
+ outcome: 'closed';
6351
+ case: SubscriberReconciliationCaseRecord;
6352
+ } | {
6353
+ outcome: 'unknown-case';
6354
+ }
6355
+ /** Closed before, by the operator or by SaaSiCat; nothing is written. */
6356
+ | {
6357
+ outcome: 'already-closed';
6358
+ case: SubscriberReconciliationCaseRecord;
6359
+ };
6360
+ /** Whether a list reads the cases still open or the ones closed. */
6361
+ type ReconciliationCaseState = 'open' | 'closed';
6362
+ /**
6363
+ * The manifest capability that announces the operator's list of cases to
6364
+ * reconcile. The platform sets it where it serves the list.
6365
+ */
6366
+ declare const RECONCILIATION_READ_CAPABILITY = "reconciliation.read";
6367
+ /**
6368
+ * The manifest capability that announces closing a case with a note, beside
6369
+ * the list.
6370
+ */
6371
+ declare const RECONCILIATION_CLOSE_CAPABILITY = "reconciliation.close";
6372
+ /**
6373
+ * The manifest capability that announces a tenant's invoices with what each
6374
+ * still owes, and its open cases, on its page.
6375
+ */
6376
+ declare const SUBSCRIBER_PAYMENTS_CAPABILITY = "payments.read";
6377
+ /** A case as the operator reads it. */
6378
+ interface AdminReconciliationCase {
6379
+ id: string;
6380
+ kind: ReconciliationCaseKind;
6381
+ amount: number;
6382
+ currency: string;
6383
+ /** The tenant the payment's invoice was for, which the administration's tenant list names. */
6384
+ tenantId: string;
6385
+ subscriber: {
6386
+ id: string;
6387
+ customerNumber: string;
6388
+ legalName: string;
6389
+ };
6390
+ /** The payment it is about, and the invoice that payment was collected for. */
6391
+ payment: {
6392
+ ref: string;
6393
+ invoiceNumber: string | null;
6394
+ };
6395
+ gatewayAccount: string;
6396
+ /** The refund's or the reversal's reference at the gateway. */
6397
+ reference: string;
6398
+ /** ISO 8601. */
6399
+ recordedAt: string;
6400
+ /** ISO 8601; `null` while it is open. */
6401
+ closedAt: string | null;
6402
+ /** Who closed it; `null` while it is open, and where SaaSiCat closed it. */
6403
+ closedBy: string | null;
6404
+ note: string | null;
6405
+ }
6406
+ /** One page of cases, the oldest first; `next` continues it, `null` at the end. */
6407
+ interface AdminReconciliationCases {
6408
+ cases: AdminReconciliationCase[];
6409
+ next: string | null;
6410
+ }
6411
+ /** The longest note a case is closed with, which the route and the form both hold to. */
6412
+ declare const RECONCILIATION_NOTE_MAX_LENGTH = 500;
6413
+ /** An operator's note closing a case. */
6414
+ interface AdminReconciliationClose {
6415
+ note: string;
6416
+ }
6417
+ /** An invoice on its tenant's page: what it asked for, and what it still owes. */
6418
+ interface AdminTenantInvoice {
6419
+ id: string;
6420
+ number: string;
6421
+ /** ISO 8601. */
6422
+ issuedAt: string;
6423
+ dueDate: CalendarDay;
6424
+ totalGross: number;
6425
+ currency: string;
5076
6426
  /**
5077
- * The subscription the charge arose on. Part of the natural key.
5078
- */
5079
- subscriptionId: string;
5080
- /**
5081
- * The contract whose line the charge realises.
5082
- */
5083
- contractId: string;
5084
- /**
5085
- * The contract line the charge came from, so that every invoice line can be traced back to what was agreed.
5086
- */
5087
- contractLineItemId: string;
5088
- origin: SubscriberChargeOrigin;
5089
- source: SubscriberChargeSource;
5090
- /**
5091
- * Which thing of its source the charge is for, stable across contracts: the subscription id for the plan, the booking id for an add-on, the discount's key for a discount. Part of the natural key (subscriptionId, source, sourceRef, periodStart, origin), which is unique — a charge derived twice is written once.
5092
- */
5093
- sourceRef: string;
5094
- /**
5095
- * The start of the period the charge belongs to — the grouping key for an invoice.
5096
- */
5097
- periodStart: string;
5098
- periodEnd: string;
5099
- /**
5100
- * ISO 4217, as the contract line records it — recorded per charge so that a charge written in 2026 still means what it meant after the configured currency changes.
6427
+ * What it still owes after every payment, reversal and reinstatement
6428
+ * against it; negative where the subscriber is owed, as by an invoice whose
6429
+ * total is negative.
5101
6430
  */
6431
+ owed: number;
6432
+ }
6433
+ /** A tenant's invoices, the newest first, and its cases still open, the oldest first. */
6434
+ interface AdminTenantPayments {
6435
+ invoices: AdminTenantInvoice[];
6436
+ openCases: AdminReconciliationCase[];
6437
+ }
6438
+
6439
+ /** A payment the gateway confirmed for an invoice, as a store reads it back. */
6440
+ interface SubscriberPaymentRecord {
6441
+ id: string;
6442
+ subscriberId: string;
6443
+ /** The tenant the invoice was for, as a trace. */
6444
+ tenantId: string;
6445
+ /** The invoice it was collected for. */
6446
+ invoiceId: string;
6447
+ /** The attempt that collected it. */
6448
+ collectionId: string;
6449
+ /** The account in `config/saas.yaml#payments.accounts` it was collected at. */
6450
+ gatewayAccount: string;
6451
+ provider: string;
6452
+ /** The gateway's own reference to the payment, unique within its account. */
6453
+ gatewayRef: string;
6454
+ /** What the gateway received, of `currency`. */
6455
+ amount: number;
6456
+ currency: string;
6457
+ recordedAt: Date;
6458
+ }
6459
+ /** A payment to record: what the gateway reported for an attempt. */
6460
+ interface NewSubscriberPayment {
6461
+ invoiceId: string;
6462
+ collectionId: string;
6463
+ gatewayAccount: string;
6464
+ provider: string;
6465
+ gatewayRef: string;
6466
+ amount: number;
6467
+ currency: string;
6468
+ at: Date;
6469
+ }
6470
+ /** What recording a payment did: what it settles of its invoice, and the credit it left. */
6471
+ interface RecordedSubscriberPayment {
6472
+ payment: SubscriberPaymentRecord;
6473
+ /** The part of the payment that settles its invoice; `0` where the invoice owed nothing. */
6474
+ settled: number;
6475
+ /** What the payment brought beyond what its invoice owed; `null` where it brought nothing more. */
6476
+ credit: SubscriberCreditRecord | null;
6477
+ }
6478
+ /** Where a credit comes from. */
6479
+ type SubscriberCreditOrigin =
6480
+ /** What a payment brought beyond what its invoice still owed. */
6481
+ {
6482
+ kind: 'payment';
6483
+ paymentId: string;
6484
+ }
6485
+ /** An invoice whose total is negative: the subscriber is owed its amount. */
6486
+ | {
6487
+ kind: 'invoice';
6488
+ invoiceId: string;
6489
+ }
6490
+ /**
6491
+ * What a reversal the gateway gave back brought beyond what the invoices
6492
+ * it had opened again still owed: the subscriber paid them meanwhile.
6493
+ */
6494
+ | {
6495
+ kind: 'reversal';
6496
+ reversalId: string;
6497
+ };
6498
+ /** Money the operator owes a subscriber, as a store reads it back. */
6499
+ interface SubscriberCreditRecord {
6500
+ id: string;
6501
+ subscriberId: string;
6502
+ /** The tenant it arose in, as a trace. */
6503
+ tenantId: string;
6504
+ /** What the subscriber is owed, positive, of `currency`. */
6505
+ amount: number;
6506
+ currency: string;
6507
+ origin: SubscriberCreditOrigin;
6508
+ createdAt: Date;
6509
+ }
6510
+ /**
6511
+ * What changed how much of a credit is paid out: a refund the gateway reported
6512
+ * against it, the same refund given back because it failed, a payout the
6513
+ * operator recorded, a reversal that took the credit's open part back to the
6514
+ * subscriber's bank, and the same reversal given back by the gateway.
6515
+ */
6516
+ type SubscriberCreditEntryKind = 'REFUND' | 'REFUND_FAILED' | 'PAYOUT' | 'REVERSAL' | 'REVERSAL_TAKEN_BACK';
6517
+ /** One change to what a credit has paid out, as a store reads it back. */
6518
+ interface SubscriberCreditEntryRecord {
6519
+ id: string;
6520
+ creditId: string;
6521
+ kind: SubscriberCreditEntryKind;
6522
+ /**
6523
+ * Positive. A `REFUND`, a `PAYOUT` and a `REVERSAL` pay this much of the
6524
+ * credit out; a `REFUND_FAILED` and a `REVERSAL_TAKEN_BACK` give it back.
6525
+ */
6526
+ amount: number;
6527
+ /** The refund, for a `REFUND` and its `REFUND_FAILED`; `null` otherwise. */
6528
+ refundId: string | null;
6529
+ /** The reversal, for a `REVERSAL` and its `REVERSAL_TAKEN_BACK`; `null` otherwise. */
6530
+ reversalId: string | null;
6531
+ /**
6532
+ * Where the operator finds it: the refund's or the reversal's reference
6533
+ * at the gateway, or the payout's, such as the transfer's.
6534
+ */
6535
+ reference: string | null;
6536
+ /** The day the payout left; `null` for a refund's entries. */
6537
+ paidOn: CalendarDay | null;
6538
+ /** Who recorded the payout; `null` for a refund's entries. */
6539
+ recordedBy: string | null;
6540
+ /** What the operator noted with the payout. */
6541
+ note: string | null;
6542
+ recordedAt: Date;
6543
+ }
6544
+ /** A credit with what has been paid out of it, and what is still open. */
6545
+ interface SubscriberCreditStanding {
6546
+ credit: SubscriberCreditRecord;
6547
+ entries: SubscriberCreditEntryRecord[];
6548
+ /** What the subscriber is still owed of it; never below `0`. */
6549
+ open: number;
6550
+ }
6551
+ /**
6552
+ * Where a refund stands, as the gateway reports it: `PENDING` and `SUCCEEDED`
6553
+ * pay out, `FAILED` and `CANCELED` gave the money back to the operator.
6554
+ */
6555
+ type SubscriberRefundStatus = 'PENDING' | 'SUCCEEDED' | 'FAILED' | 'CANCELED';
6556
+ /** A refund the operator made in the gateway, as a store reads it back. */
6557
+ interface SubscriberRefundRecord {
6558
+ id: string;
6559
+ subscriberId: string;
6560
+ /** The payment it pays back. */
6561
+ paymentId: string;
6562
+ gatewayAccount: string;
6563
+ /** The gateway's reference to the refund, unique within its account. */
6564
+ gatewayRef: string;
6565
+ amount: number;
6566
+ currency: string;
6567
+ status: SubscriberRefundStatus;
6568
+ recordedAt: Date;
6569
+ /** When it was recorded as failed or canceled; `null` while it pays out. */
6570
+ endedAt: Date | null;
6571
+ }
6572
+ /** A refund as the gateway reported it, to record against the payment it pays back. */
6573
+ interface ReportedSubscriberRefund {
6574
+ gatewayAccount: string;
6575
+ gatewayRef: string;
6576
+ /** The gateway's reference to the payment it pays back. */
6577
+ paymentRef: string;
6578
+ amount: number;
5102
6579
  currency: string;
5103
- /**
5104
- * Net, rounded to the currency's decimal places once, when the charge is written; the written figure is the truth from then on. Negative for a discount.
5105
- */
5106
- amountNet: number;
5107
- /**
5108
- * When the amount became due. The account is ordered by this, not by when the row was written.
5109
- */
5110
- bookedAt: string;
5111
- createdAt: string;
6580
+ status: SubscriberRefundStatus;
6581
+ at: Date;
5112
6582
  }
5113
-
5114
- /** A charge as a store reads it back: the wire format, with its dates as dates. */
5115
- interface SubscriberChargeRecord {
6583
+ /** What recording a refund did. */
6584
+ type RecordedSubscriberRefund =
6585
+ /** No payment of this installation's is under its reference. */
6586
+ {
6587
+ outcome: 'unknown-payment';
6588
+ }
6589
+ /**
6590
+ * Recorded for the first time: the credits it pays out, and the part that
6591
+ * matches none, which is a case to reconcile.
6592
+ */
6593
+ | {
6594
+ outcome: 'recorded';
6595
+ refund: SubscriberRefundRecord;
6596
+ parts: CreditPart[];
6597
+ unmatched: number;
6598
+ case: SubscriberReconciliationCaseRecord | null;
6599
+ }
6600
+ /**
6601
+ * Recorded before; it failed or was canceled now, gave back what it paid
6602
+ * out, and closed the case its unmatched part had opened.
6603
+ */
6604
+ | {
6605
+ outcome: 'given-back';
6606
+ refund: SubscriberRefundRecord;
6607
+ parts: CreditPart[];
6608
+ closedCases: SubscriberReconciliationCaseRecord[];
6609
+ }
6610
+ /** Recorded before, and nothing it reports changes what is paid out. */
6611
+ | {
6612
+ outcome: 'unchanged';
6613
+ refund: SubscriberRefundRecord;
6614
+ };
6615
+ /** The part of an amount that one credit takes. */
6616
+ interface CreditPart {
6617
+ creditId: string;
6618
+ amount: number;
6619
+ }
6620
+ /** The part of an amount that one invoice takes. */
6621
+ interface InvoicePart {
6622
+ invoiceId: string;
6623
+ amount: number;
6624
+ }
6625
+ /**
6626
+ * Money the gateway took back from the operator for a payment — a returned
6627
+ * direct debit or a chargeback — as a store reads it back. What it withdrew and
6628
+ * what the gateway gave back of it only grow; each change is recorded as the
6629
+ * entries it adds.
6630
+ */
6631
+ interface SubscriberReversalRecord {
5116
6632
  id: string;
5117
6633
  subscriberId: string;
6634
+ /** The tenant the payment's invoice was for, as a trace. */
5118
6635
  tenantId: string;
5119
- subscriptionId: string;
5120
- contractId: string;
5121
- contractLineItemId: string;
5122
- origin: SubscriberChargeOrigin;
5123
- source: SubscriberChargeSource;
5124
- /** The subscription id for the plan, the booking id for an add-on, the discount's key. */
5125
- sourceRef: string;
5126
- periodStart: Date;
5127
- periodEnd: Date;
6636
+ /** The payment it takes back. */
6637
+ paymentId: string;
6638
+ gatewayAccount: string;
6639
+ /** The gateway's reference to it, such as a dispute's, unique within its account. */
6640
+ gatewayRef: string;
6641
+ /** What the gateway withdrew, positive, of `currency`. */
6642
+ amount: number;
5128
6643
  currency: string;
5129
- /** Net, rounded to the cent when written. Negative for a discount. */
5130
- amountNet: number;
5131
- /** When the amount became due. */
5132
- bookedAt: Date;
5133
- createdAt: Date;
6644
+ /**
6645
+ * The part of `amount` taken from the credit the payment left — its open
6646
+ * part and the part already paid out alike —, so a later reversal of the
6647
+ * same payment takes from what of that credit is left.
6648
+ */
6649
+ fromCredit: number;
6650
+ /** What the gateway gave back of `amount`, a dispute won; `0` until it gives anything back. */
6651
+ reinstated: number;
6652
+ recordedAt: Date;
6653
+ /** When the gateway last gave something back; `null` until it does. */
6654
+ reinstatedAt: Date | null;
5134
6655
  }
5135
- /** A charge to write: everything but what the store assigns. */
5136
- type NewSubscriberCharge = Omit<SubscriberChargeRecord, 'id' | 'createdAt'>;
5137
6656
  /**
5138
- * The manifest capability that announces the operator's view of an account.
5139
- * The platform sets it where it serves the view, and the admin UI shows the
5140
- * view only where it is set.
6657
+ * A reversal as the gateway reports it, as it stands when it is reported: what
6658
+ * it withdrew and what it gave back so far, each in total.
5141
6659
  */
5142
- declare const SUBSCRIBER_ACCOUNT_CAPABILITY = "charges.read";
5143
- /** Whose account it is, as the operator is shown it. */
5144
- interface AdminAccountHolder {
6660
+ interface ReportedSubscriberReversal {
6661
+ gatewayAccount: string;
6662
+ gatewayRef: string;
6663
+ /** The gateway's reference to the payment it takes back. */
6664
+ paymentRef: string;
6665
+ currency: string;
6666
+ withdrawn: number;
6667
+ reinstated: number;
6668
+ at: Date;
6669
+ }
6670
+ /** What withdrawing part of a reversal's amount took back. */
6671
+ interface ReversalWithdrawal {
6672
+ /** What it took of the credit the payment left that was still open. */
6673
+ credit: CreditPart | null;
6674
+ /**
6675
+ * What it took instead of opening an invoice again, of the credits other
6676
+ * payments collected for that invoice left, the oldest first.
6677
+ */
6678
+ covering: CreditPart[];
6679
+ /** The invoices it opened again, each by how much, the oldest first. */
6680
+ invoices: InvoicePart[];
6681
+ /**
6682
+ * The covers the payment's own credit gave other reversals of its invoice,
6683
+ * lifted before anything else: each of those reversals now opens the
6684
+ * invoice by what it took (`SC-PRIC-088`).
6685
+ */
6686
+ uncovered: LiftedCover[];
6687
+ /**
6688
+ * What met the part of that credit already paid out, or went beyond what
6689
+ * the payment brought: a case to reconcile.
6690
+ */
6691
+ unmatched: number;
6692
+ case: SubscriberReconciliationCaseRecord | null;
6693
+ }
6694
+ /** A cover lifted: the reversal it was given to, that reversal's payment, and what it opens now. */
6695
+ interface LiftedCover {
6696
+ reversalId: string;
6697
+ paymentId: string;
6698
+ invoiceId: string;
6699
+ amount: number;
6700
+ }
6701
+ /** What giving back part of a reversal's amount took back in turn. */
6702
+ interface ReversalReinstatement {
6703
+ /** The cases of the reversal it covered, closed. */
6704
+ closedCases: SubscriberReconciliationCaseRecord[];
6705
+ /** What it gave back to the credits the reversal had taken from. */
6706
+ credits: CreditPart[];
6707
+ /** The invoices it settled again, each by how much. */
6708
+ invoices: InvoicePart[];
6709
+ /** What the invoices no longer owed, as a credit; `null` where they owed all of it. */
6710
+ credit: SubscriberCreditRecord | null;
6711
+ }
6712
+ /** What recording a reversal did. */
6713
+ type RecordedSubscriberReversal =
6714
+ /** No payment of this installation's is under its reference. */
6715
+ {
6716
+ outcome: 'unknown-payment';
6717
+ }
6718
+ /**
6719
+ * Recorded, or recorded before and changed now: what the newly withdrawn
6720
+ * part took back, and what the newly given back part gave back, each
6721
+ * `null` where nothing of it changed.
6722
+ */
6723
+ | {
6724
+ outcome: 'recorded';
6725
+ reversal: SubscriberReversalRecord;
6726
+ withdrawal: ReversalWithdrawal | null;
6727
+ reinstatement: ReversalReinstatement | null;
6728
+ }
6729
+ /** Recorded before, and nothing it reports changes it. */
6730
+ | {
6731
+ outcome: 'unchanged';
6732
+ reversal: SubscriberReversalRecord;
6733
+ };
6734
+ /** A payout the operator made outside the gateway, to record against a credit. */
6735
+ interface NewSubscriberPayout {
6736
+ creditId: string;
6737
+ amount: number;
6738
+ /** The transfer's reference, which the operator's bank statement names. */
6739
+ reference: string;
6740
+ paidOn: CalendarDay;
6741
+ note: string | null;
6742
+ /** Who records it. */
6743
+ recordedBy: string;
6744
+ at: Date;
6745
+ }
6746
+ /** What recording a payout did. */
6747
+ type RecordedSubscriberPayout = {
6748
+ outcome: 'recorded';
6749
+ entry: SubscriberCreditEntryRecord;
6750
+ open: number;
6751
+ } | {
6752
+ outcome: 'unknown-credit';
6753
+ }
6754
+ /** More than the credit still owes; nothing is written. */
6755
+ | {
6756
+ outcome: 'exceeds-open';
6757
+ open: number;
6758
+ };
6759
+ /**
6760
+ * The manifest capability that announces the operator's view of a
6761
+ * subscriber's credits. The platform sets it where it serves the view.
6762
+ */
6763
+ declare const SUBSCRIBER_CREDIT_CAPABILITY = "credits.read";
6764
+ /**
6765
+ * The manifest capability that announces recording a payout the operator
6766
+ * made outside the gateway, beside the view of the credits.
6767
+ */
6768
+ declare const SUBSCRIBER_PAYOUT_CAPABILITY = "credits.payout";
6769
+ /** What paid a credit out, or gave it back, as the operator reads it. */
6770
+ interface AdminSubscriberCreditEntry {
6771
+ kind: SubscriberCreditEntryKind;
6772
+ amount: number;
6773
+ /** The refund's or the reversal's reference at the gateway, or the payout's. */
6774
+ reference: string | null;
6775
+ /** The day a payout left; `null` for a refund's entries. */
6776
+ paidOn: CalendarDay | null;
6777
+ note: string | null;
6778
+ /** ISO 8601. */
6779
+ recordedAt: string;
6780
+ }
6781
+ /** A credit as the operator reads it: where it comes from, what was paid out, what is open. */
6782
+ interface AdminSubscriberCredit {
5145
6783
  id: string;
5146
- /** What the customer quotes, and what an invoice will carry. */
5147
- customerNumber: string;
5148
- legalName: string;
6784
+ amount: number;
6785
+ currency: string;
6786
+ /**
6787
+ * The payment that brought more than its invoice owed, the invoice whose
6788
+ * total is negative, or the reversal the gateway gave back.
6789
+ */
6790
+ origin: {
6791
+ kind: 'payment';
6792
+ paymentRef: string;
6793
+ invoiceNumber: string | null;
6794
+ } | {
6795
+ kind: 'invoice';
6796
+ invoiceNumber: string | null;
6797
+ } | {
6798
+ kind: 'reversal';
6799
+ reversalRef: string;
6800
+ invoiceNumber: string | null;
6801
+ };
6802
+ /** ISO 8601. */
6803
+ createdAt: string;
6804
+ open: number;
6805
+ entries: AdminSubscriberCreditEntry[];
5149
6806
  }
5150
- /** One charge of an account, with the name its contract line gives it. */
5151
- interface AdminAccountEntry {
5152
- /** The charge as the journal holds it. */
5153
- charge: SubscriberCharge;
6807
+ /** A tenant's credits as the operator reads them, the oldest first. */
6808
+ interface AdminSubscriberCredits {
6809
+ credits: AdminSubscriberCredit[];
5154
6810
  /**
5155
- * The contract line's own title, as it was when the contract was
5156
- * concluded, or `null` where that line cannot be read.
6811
+ * The installation's time zone, in which a payout's day is judged: no
6812
+ * payout lies after today there, wherever the operator sits.
5157
6813
  */
5158
- title: string | null;
6814
+ timeZone: string;
5159
6815
  }
5160
- /**
5161
- * A tenant's account as the operator reads it: the charges of the subscription
5162
- * it holds, newest first — by when each became due, then by its period, then
5163
- * the plan before its add-ons before its discounts.
5164
- *
5165
- * No total: without invoices and payments, a sum would be what was charged so
5166
- * far, and it would be read as what is owed.
5167
- */
5168
- interface AdminSubscriberAccount {
5169
- /** `null` for a tenant that has no subscriber. */
5170
- holder: AdminAccountHolder | null;
5171
- entries: AdminAccountEntry[];
6816
+ /** A payout the operator records against a credit. */
6817
+ interface AdminSubscriberPayout {
6818
+ amount: number;
6819
+ reference: string;
6820
+ paidOn: CalendarDay;
6821
+ note?: string | null;
5172
6822
  }
5173
6823
 
5174
6824
  /**
@@ -5381,6 +7031,26 @@ interface SubscriptionBundleRepository {
5381
7031
  * them still move.
5382
7032
  */
5383
7033
  listScheduledVersionsDue?(asOf: Date): Promise<SubscriptionBundleRecord[]>;
7034
+ /**
7035
+ * Ends at `input.at` the booking `subscriptionBundleId` whose cancellation
7036
+ * was declared for a later date, provided its effective date is still
7037
+ * `input.expectedCanceledEffectiveAt`, and answers it as it now stands;
7038
+ * null where its cancellation moved meanwhile, or it is gone. Both
7039
+ * cancellation fields become `input.at`. What a feature withdrawn for an
7040
+ * external reason lets a subscriber do, cancelled or not; a booking not
7041
+ * cancelled is ended through `cancel`.
7042
+ *
7043
+ * Optional, so a repository written before it keeps working; without it, a
7044
+ * booking already cancelled for a later date cannot be ended at once.
7045
+ */
7046
+ endNow?(subscriptionBundleId: string, input: EndNowInput): Promise<SubscriptionBundleRecord | null>;
7047
+ }
7048
+ /** What ending at once something cancelled for a later date is told to write. */
7049
+ interface EndNowInput {
7050
+ /** The moment it ends, and the moment that is declared. */
7051
+ readonly at: Date;
7052
+ /** The effective date of the cancellation the caller read: the write is conditional on it. */
7053
+ readonly expectedCanceledEffectiveAt: Date;
5384
7054
  }
5385
7055
  /**
5386
7056
  * Append-only repository for V3 SubscriptionContracts. Contracts are the
@@ -5565,6 +7235,405 @@ interface SubscriberLedgerRepository {
5565
7235
  /** Every charge of one subscription, oldest period first. */
5566
7236
  listBySubscription(subscriptionId: string, tx?: TransactionContext): Promise<SubscriberChargeRecord[]>;
5567
7237
  }
7238
+ /**
7239
+ * The invoices issued from the charge journal, and the one number range they
7240
+ * are numbered in (`SC-PRIC-072`).
7241
+ *
7242
+ * An invoice is written once and never changed. Its number is drawn when it is
7243
+ * written, in the same transaction, so an invoice that fails to be written
7244
+ * leaves no gap; the range restarts at 1 each year.
7245
+ */
7246
+ interface SubscriptionInvoiceRepository {
7247
+ /**
7248
+ * The subscriptions with a charge to invoice: a charge on no invoice in a
7249
+ * group — the charges booked at the same moment under the same contract —
7250
+ * that carries an amount (`SC-PRIC-048`). By id, at most `limit`, after
7251
+ * `after` where it is given, so a caller reads them page by page and a
7252
+ * subscription held back on one run never keeps the others from the next.
7253
+ */
7254
+ listSubscriptionsWithUninvoicedCharges(page: {
7255
+ limit: number;
7256
+ after?: string;
7257
+ }, tx?: TransactionContext): Promise<string[]>;
7258
+ /** The charges of one subscription on no invoice, oldest period first. */
7259
+ listUninvoicedCharges(subscriptionId: string, tx?: TransactionContext): Promise<SubscriberChargeRecord[]>;
7260
+ /**
7261
+ * Draws the next number of the invoice's year and writes the invoice with
7262
+ * its lines, in one transaction — the caller's where it passes one. Two
7263
+ * calls at once draw two numbers one after the other, never the same one
7264
+ * and never with a gap between them.
7265
+ *
7266
+ * Refuses with `SUBSCRIPTION_INVOICE_CHARGE_INVOICED` (`moved`) where a
7267
+ * charge already stands on an invoice: nothing is written, and the number
7268
+ * is not drawn.
7269
+ */
7270
+ issue(invoice: NewSubscriptionInvoice, tx?: TransactionContext): Promise<SubscriptionInvoiceRecord>;
7271
+ findById(id: string, tx?: TransactionContext): Promise<SubscriptionInvoiceRecord | null>;
7272
+ /** Every invoice of one subscriber, the latest number first. */
7273
+ listBySubscriber(subscriberId: string, tx?: TransactionContext): Promise<SubscriptionInvoiceRecord[]>;
7274
+ /**
7275
+ * The prefixes the issued invoices carry, at most two: one is the range,
7276
+ * a second one says the prefix was changed under it (`SC-PRIC-024`).
7277
+ */
7278
+ listIssuedNumberPrefixes(tx?: TransactionContext): Promise<string[]>;
7279
+ /**
7280
+ * Records the rendering of an invoice's document before its file is
7281
+ * archived (`SC-AUD-019`), once. A rendering recorded again with the same
7282
+ * checksum is the same write and answers the record as it stands; another
7283
+ * checksum is refused with `SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED`
7284
+ * (`moved`), and the first stays: `replaceRendering` is the one write that
7285
+ * puts another in its place.
7286
+ */
7287
+ recordRendering(invoiceId: string, rendering: NewInvoiceRendering, tx?: TransactionContext): Promise<SubscriptionInvoiceDocumentRecord>;
7288
+ /**
7289
+ * Records a rendering in place of the one recorded with `replaced` as its
7290
+ * checksum, while the invoice is not archived (`SC-AUD-019`): until the
7291
+ * archive holds a file, nothing has been handed out. Answers the record as
7292
+ * it stands now, or `null` where the recorded checksum is another by now or
7293
+ * the invoice is archived — a run that read it before another one changed it.
7294
+ */
7295
+ replaceRendering(invoiceId: string, rendering: NewInvoiceRendering, replaced: string, tx?: TransactionContext): Promise<SubscriptionInvoiceDocumentRecord | null>;
7296
+ /**
7297
+ * Records that the archive confirmed the document whose checksum is
7298
+ * `checksum`; `false` where it was already recorded, or the recorded
7299
+ * checksum is another.
7300
+ */
7301
+ markArchived(invoiceId: string, at: Date, checksum: string, tx?: TransactionContext): Promise<boolean>;
7302
+ /**
7303
+ * Claims an archived invoice's mail for the run calling it at `at`: where
7304
+ * it is not delivered and no run holds it, or the run that holds it took it
7305
+ * on before `staleBefore`. `true` where this run holds it now — of two
7306
+ * concurrent calls exactly one does — so that an invoice is mailed once
7307
+ * however many instances run (`SC-PRIC-047`).
7308
+ */
7309
+ claimDelivery(invoiceId: string, at: Date, staleBefore: Date, tx?: TransactionContext): Promise<boolean>;
7310
+ /**
7311
+ * Records that the invoice was handed to the mail, provided it is still
7312
+ * held by the claim taken at `claimedAt` and not delivered. `false` where it
7313
+ * is not: the claim went stale and another run took the invoice on.
7314
+ */
7315
+ markDelivered(invoiceId: string, delivery: {
7316
+ claimedAt: Date;
7317
+ at: Date;
7318
+ to: string;
7319
+ }, tx?: TransactionContext): Promise<boolean>;
7320
+ /**
7321
+ * Lets go of the claim taken at `claimedAt`, so the next run tries again.
7322
+ * Does nothing where the invoice is delivered or held by another claim.
7323
+ */
7324
+ releaseDelivery(invoiceId: string, claimedAt: Date, tx?: TransactionContext): Promise<void>;
7325
+ /** Where the invoice's document stands, or `null` before it was rendered. */
7326
+ findDocument(invoiceId: string, tx?: TransactionContext): Promise<SubscriptionInvoiceDocumentRecord | null>;
7327
+ /**
7328
+ * The invoices whose document the archive has not confirmed yet —
7329
+ * not rendered, or rendered and not archived (`SC-PRIC-033`). By id, at
7330
+ * most `limit`, after `after` where it is given.
7331
+ */
7332
+ listAwaitingDocument(page: {
7333
+ limit: number;
7334
+ after?: string;
7335
+ }, tx?: TransactionContext): Promise<string[]>;
7336
+ /**
7337
+ * The invoices archived and not yet handed to the mail, page by page as
7338
+ * above — whether or not a run holds them, which `claimDelivery` decides.
7339
+ */
7340
+ listAwaitingDelivery(page: {
7341
+ limit: number;
7342
+ after?: string;
7343
+ }, tx?: TransactionContext): Promise<string[]>;
7344
+ }
7345
+ /**
7346
+ * The attempts to collect an invoice through its payment gateway.
7347
+ *
7348
+ * An invoice has at most one attempt that is open — planned, or sent and not
7349
+ * settled — and none after one succeeded: the database holds that
7350
+ * (`sql/constraints.postgres.sql`), and the turn holds it against two runs
7351
+ * that start at once. Every write that settles
7352
+ * or takes on an attempt names the state it expects, so of two runs one wins
7353
+ * and the other is told.
7354
+ *
7355
+ * Platform-wide: the run reads across tenants inside `RlsBypassPort`.
7356
+ */
7357
+ interface InvoiceCollectionRepository {
7358
+ /**
7359
+ * The invoices to collect on `today`, by id, at most `limit`, after `after`
7360
+ * where it is given: issued with a payment method to collect with, handed
7361
+ * to the mail — so their announcement has reached the subscriber — with no
7362
+ * collection date or one on or before `today`, and no attempt yet, planned
7363
+ * or sent.
7364
+ */
7365
+ listDue(today: CalendarDay, page: {
7366
+ limit: number;
7367
+ after?: string;
7368
+ }, tx?: TransactionContext): Promise<string[]>;
7369
+ /**
7370
+ * Starts the invoice's first attempt in its turn and returns it, written as
7371
+ * `SUBMITTED` before its request leaves; `null`, writing nothing, where the
7372
+ * invoice owes nothing — its total no more than what is settled against
7373
+ * it in `subscription_invoice_settlements` — or has an attempt already —
7374
+ * every later one is planned (`plan`), so
7375
+ * a run that found the invoice due before another run's attempt failed
7376
+ * does not charge it again at once. The turn is the invoice's
7377
+ * own row, locked for the transaction — the chain of one invoice, which a
7378
+ * cancellation's replacement joins — so a cancellation never meets an
7379
+ * attempt about to be sent without knowing it (`SC-PRIC-036`). The attempt
7380
+ * is numbered after the invoice's last, and its key is
7381
+ * `collectionAttemptKey(invoiceId, attempt)`.
7382
+ */
7383
+ startAttempt(attempt: NewInvoiceCollection, tx?: TransactionContext): Promise<InvoiceCollectionRecord | null>;
7384
+ /**
7385
+ * Plans the invoice's next attempt in its turn, as `startAttempt` starts
7386
+ * one, and returns it, written as `SCHEDULED` for `plan.collectOn` with
7387
+ * nothing sent; `null`, writing nothing, where the invoice owes nothing,
7388
+ * where an attempt of it is open or one succeeded, or where its last
7389
+ * attempt is not the one numbered `plan.after` any more.
7390
+ */
7391
+ plan(plan: PlannedInvoiceCollection, tx?: TransactionContext): Promise<InvoiceCollectionRecord | null>;
7392
+ /**
7393
+ * Records that a planned direct debit's announcement reached the subscriber
7394
+ * at `at`, naming `collectOn`, and returns `true`; `false`, writing nothing,
7395
+ * where it is not planned or was announced already.
7396
+ */
7397
+ announce(id: string, collectOn: CalendarDay, at: Date, tx?: TransactionContext): Promise<boolean>;
7398
+ /**
7399
+ * Takes a planned attempt up as sent — `SUBMITTED`, sent and held at `at` —
7400
+ * in its invoice's turn, as `startAttempt` writes one, before its request
7401
+ * leaves, and returns it; `null`, writing nothing, where it is not planned
7402
+ * any more, so of two runs one sends it, or where its invoice owes nothing,
7403
+ * a payment having come for it meanwhile.
7404
+ */
7405
+ submitPlanned(id: string, at: Date, tx?: TransactionContext): Promise<SubmittedInvoiceCollection | null>;
7406
+ /**
7407
+ * Withdraws a planned attempt that will not be made, at `at`, in its
7408
+ * invoice's turn, and returns `true`; `false`, writing nothing, where it is
7409
+ * not planned.
7410
+ */
7411
+ withdraw(id: string, at: Date, tx?: TransactionContext): Promise<boolean>;
7412
+ /** The planned attempts, by id and page as above, whatever their day. */
7413
+ listPlanned(page: {
7414
+ limit: number;
7415
+ after?: string;
7416
+ }, tx?: TransactionContext): Promise<string[]>;
7417
+ /**
7418
+ * The failed and the reversed attempts, by id and page as above, whose
7419
+ * follow-up is not recorded yet.
7420
+ */
7421
+ listToFollowUp(page: {
7422
+ limit: number;
7423
+ after?: string;
7424
+ }, tx?: TransactionContext): Promise<string[]>;
7425
+ /**
7426
+ * The invoices, by id and page as above, that another payment method can
7427
+ * collect: their last attempt was withdrawn, or failed or was reversed and
7428
+ * was followed up, every attempt of theirs that was reversed was followed
7429
+ * up, and their subscriber has a payment method in use other than the one
7430
+ * the last attempt was made with and than every one a reversed attempt was
7431
+ * made with (`subscriber_payment_methods`), and they still owe something.
7432
+ * An invoice whose failed or reversed payment method is still in use, or
7433
+ * whose subscriber has none, is not read until that changes.
7434
+ */
7435
+ listCollectableAgain(page: {
7436
+ limit: number;
7437
+ after?: string;
7438
+ }, tx?: TransactionContext): Promise<string[]>;
7439
+ /**
7440
+ * Records that what follows a failed or a reversed attempt was decided, at
7441
+ * `at`, and returns `true`; `false`, writing nothing, where it neither
7442
+ * failed nor was reversed, or was followed up already.
7443
+ */
7444
+ markFollowedUp(id: string, at: Date, tx?: TransactionContext): Promise<boolean>;
7445
+ /**
7446
+ * Marks the attempt whose payment a reversal took back as `REVERSED`, at
7447
+ * `at`, where the reversal opened its invoice again, and returns `true`;
7448
+ * `false`, writing nothing, where it is neither `SUCCEEDED` nor `FAILED`.
7449
+ * A failed one brought its payment late, beside another attempt of its
7450
+ * invoice (`recordOutcome`). Either is followed up again, as a reversal;
7451
+ * the invoice is then collected only by an attempt with another payment
7452
+ * method than every reversed one, planned once the reversal is followed up.
7453
+ */
7454
+ markReversed(id: string, at: Date, tx?: TransactionContext): Promise<boolean>;
7455
+ /**
7456
+ * Records what became of an attempt that is not settled — `SUBMITTED` or
7457
+ * `PENDING` — and returns `true`; `false`, writing nothing, where it is
7458
+ * settled already. `PENDING` stays open; `SUCCEEDED` and `FAILED` settle it
7459
+ * at `at`.
7460
+ *
7461
+ * A success reported for an attempt recorded as `FAILED` is the money
7462
+ * arriving after all: in the invoice's turn, an attempt planned after it
7463
+ * is withdrawn, and the attempt succeeds and `true` is returned — unless
7464
+ * another attempt of the invoice is on its way or succeeded, which leaves
7465
+ * it failed and returns `false`.
7466
+ */
7467
+ recordOutcome(id: string, outcome: CollectionOutcome, at: Date, tx?: TransactionContext): Promise<boolean>;
7468
+ /**
7469
+ * Decides, in the invoice's turn — the one a payment is recorded in —,
7470
+ * what becomes of a `SUBMITTED` attempt whose request never reached the
7471
+ * gateway: where its invoice owes nothing it is settled as
7472
+ * `COLLECTION_NOT_SENT_PAID` at `at` (`abandoned`); where it is still
7473
+ * `SUBMITTED` and the invoice owes, it is to be sent again (`resend`),
7474
+ * and is held from `at`; where a report settled it or put it on its way
7475
+ * meanwhile, nothing is (`settled`). Both `abandoned` and `resend` rest on
7476
+ * a write conditioned on the attempt still being `SUBMITTED`, so a report
7477
+ * recorded outside the invoice's turn — a failure, an answer that it is on
7478
+ * its way — while the run decides is found rather than overlooked. A run
7479
+ * asks it before it sends such a request again, so a payment that arrived
7480
+ * meanwhile is never charged a second time.
7481
+ */
7482
+ abandonPaid(id: string, at: Date, tx?: TransactionContext): Promise<AbandonPaidOutcome>;
7483
+ /**
7484
+ * Takes on an attempt that is not settled for the run calling it at `at`,
7485
+ * where no run took it on since `heldBefore`, and returns `true`; of two
7486
+ * concurrent calls exactly one does.
7487
+ */
7488
+ hold(id: string, heldBefore: Date, at: Date, tx?: TransactionContext): Promise<boolean>;
7489
+ /**
7490
+ * The attempts a run should take on again, by id and page as above:
7491
+ * `SUBMITTED` ones no run took on since `submittedBefore` — their answer
7492
+ * was lost —, and `PENDING` ones none took on since `pendingBefore`.
7493
+ */
7494
+ listUnsettled(before: {
7495
+ submittedBefore: Date;
7496
+ pendingBefore: Date;
7497
+ }, page: {
7498
+ limit: number;
7499
+ after?: string;
7500
+ }, tx?: TransactionContext): Promise<string[]>;
7501
+ findById(id: string, tx?: TransactionContext): Promise<InvoiceCollectionRecord | null>;
7502
+ /** The attempt `attemptKey` names — the key the gateway keeps with what it created — or `null`. */
7503
+ findByKey(attemptKey: string, tx?: TransactionContext): Promise<InvoiceCollectionRecord | null>;
7504
+ /** Every attempt of one invoice, the first first. */
7505
+ listByInvoice(invoiceId: string, tx?: TransactionContext): Promise<InvoiceCollectionRecord[]>;
7506
+ /**
7507
+ * Every gateway account an attempt that is not settled was sent to, each
7508
+ * once — the accounts that have to stay configured until their attempts
7509
+ * settle, since only the account can say what became of them
7510
+ * (`SC-PRIC-030`). Platform-wide: a start asks it before anything is
7511
+ * served, through `RlsBypassPort`.
7512
+ */
7513
+ accountsInUse(tx?: TransactionContext): Promise<string[]>;
7514
+ }
7515
+ /**
7516
+ * What money moved between a subscriber and the operator: the payments the
7517
+ * gateway confirmed, what each settles of its invoice, the credits the
7518
+ * subscriber is owed, the refunds and payouts that pay them out, the reversals
7519
+ * that take a payment back and give it back again, and the cases nothing
7520
+ * matched (`SC-PRIC-029`, `SC-PRIC-083`, `SC-PRIC-084`, `SC-PRIC-086`,
7521
+ * `SC-ADM-033`). Nothing is edited once written but a refund's status, what a
7522
+ * reversal withdrew and gave back, and a case's closing; every other change is
7523
+ * an entry of its own.
7524
+ *
7525
+ * Platform-wide: the gateway's callbacks and the run read across tenants
7526
+ * inside `RlsBypassPort`.
7527
+ */
7528
+ interface SubscriberPaymentRepository {
7529
+ /**
7530
+ * Records a payment the gateway confirmed for an invoice, in the invoice's
7531
+ * turn (`SC-PRIC-036`): it settles what the invoice still owes, and what it
7532
+ * brought beyond that is a credit on the subscriber's account. Returns what
7533
+ * it did; `null`, writing nothing, where a payment is recorded under the
7534
+ * same gateway account and reference already, however it was reported
7535
+ * then (`SC-PRIC-029`). Throws for an invoice that does not exist, and for
7536
+ * a payment in another currency than its invoice's.
7537
+ */
7538
+ recordPayment(payment: NewSubscriberPayment, tx?: TransactionContext): Promise<RecordedSubscriberPayment | null>;
7539
+ /**
7540
+ * Credits an invoice whose total is negative to its subscriber, at `at`,
7541
+ * and returns the credit; `null`, writing nothing, where it is credited
7542
+ * already or its total is not negative.
7543
+ */
7544
+ creditInvoice(invoiceId: string, at: Date, tx?: TransactionContext): Promise<SubscriberCreditRecord | null>;
7545
+ /**
7546
+ * The invoices whose total is negative and that are not credited yet, by
7547
+ * id, at most `limit`, after `after` where it is given.
7548
+ */
7549
+ listUncredited(page: {
7550
+ limit: number;
7551
+ after?: string;
7552
+ }, tx?: TransactionContext): Promise<string[]>;
7553
+ /**
7554
+ * Records a refund the gateway reported against the payment it pays back.
7555
+ * Seen for the first time, it is divided across the subscriber's open
7556
+ * credits in its currency — the credit that payment left first, then the
7557
+ * oldest — and what none takes matches nothing, a case to reconcile. Seen
7558
+ * again as failed or canceled, it gives back what it paid out of each
7559
+ * credit, once, and closes its case. Every credit it reads is held for the
7560
+ * transaction, so a payout or another refund at the same moment waits for
7561
+ * it.
7562
+ */
7563
+ recordRefund(refund: ReportedSubscriberRefund, tx?: TransactionContext): Promise<RecordedSubscriberRefund>;
7564
+ /**
7565
+ * Records a payout the operator made outside the gateway against one
7566
+ * credit, holding the credit for the transaction; nothing is written where
7567
+ * the credit does not exist or owes less than the payout.
7568
+ */
7569
+ recordPayout(payout: NewSubscriberPayout, tx?: TransactionContext): Promise<RecordedSubscriberPayout>;
7570
+ /** The subscriber's credits, the oldest first, each with its entries and what it still owes. */
7571
+ listCredits(subscriberId: string, tx?: TransactionContext): Promise<SubscriberCreditStanding[]>;
7572
+ /** The payment recorded under `id`, or `null`. */
7573
+ findPaymentById(id: string, tx?: TransactionContext): Promise<SubscriberPaymentRecord | null>;
7574
+ /** The reversal recorded under `id`, or `null`. */
7575
+ findReversalById(id: string, tx?: TransactionContext): Promise<SubscriberReversalRecord | null>;
7576
+ /** The payment recorded under a gateway account and reference, or `null`. */
7577
+ findPaymentByRef(gatewayAccount: string, gatewayRef: string, tx?: TransactionContext): Promise<SubscriberPaymentRecord | null>;
7578
+ /** The payments recorded for an invoice, the first first. */
7579
+ listPaymentsByInvoice(invoiceId: string, tx?: TransactionContext): Promise<SubscriberPaymentRecord[]>;
7580
+ /** What an invoice still owes after what is settled against it; `null` where it does not exist. */
7581
+ owedBy(invoiceId: string, tx?: TransactionContext): Promise<number | null>;
7582
+ /**
7583
+ * What each of `invoiceIds` still owes, for every one that exists, in one
7584
+ * read.
7585
+ */
7586
+ owedByInvoices(invoiceIds: readonly string[], tx?: TransactionContext): Promise<{
7587
+ invoiceId: string;
7588
+ owed: number;
7589
+ }[]>;
7590
+ /**
7591
+ * Records a reversal the gateway reported against the payment it takes
7592
+ * back, in the turn of that payment's invoice (`SC-PRIC-036`), with every
7593
+ * credit of its subscriber held. What it withdrew and what the gateway gave
7594
+ * back of it are reported in total; what grew since it was last recorded is
7595
+ * applied, once however often and in whatever order it is reported. What it
7596
+ * newly withdrew takes from the credit the payment left first — its open
7597
+ * part shrinks it, its part already paid out is a case to reconcile —, then
7598
+ * opens again the invoices the payment settles, the oldest first, and what
7599
+ * exceeds both is a case as well (`SC-PRIC-084`). What it would open again
7600
+ * is taken first of the open credits that other payments collected for
7601
+ * those invoices left, the oldest first (`SC-PRIC-087`). What it takes of
7602
+ * the payment's own credit beyond the open part lifts the covers that
7603
+ * credit gave other reversals before it counts as paid out: each is given
7604
+ * back to the credit, and its reversal opens the invoice by it
7605
+ * (`SC-PRIC-088`, `ReversalWithdrawal.uncovered`). What the gateway gives
7606
+ * back returns to the payment's own credit before the covering ones. What the gateway newly
7607
+ * gave back covers the reversal's cases first, closing each it covers, then
7608
+ * gives back what it took of the credit, then settles again what it opened
7609
+ * as far as the invoice still owes, and what an invoice no longer owes is a
7610
+ * credit (`SC-PRIC-086`). Throws for a reversal in another currency than
7611
+ * its payment.
7612
+ */
7613
+ recordReversal(reversal: ReportedSubscriberReversal, tx?: TransactionContext): Promise<RecordedSubscriberReversal>;
7614
+ /**
7615
+ * The cases to reconcile in `state`, the oldest first — of one subscriber
7616
+ * where `subscriberId` is given —, at most `limit`, after the case `after`
7617
+ * names where it is given.
7618
+ */
7619
+ listCases(filter: {
7620
+ state: ReconciliationCaseState;
7621
+ subscriberId?: string;
7622
+ }, page: {
7623
+ limit: number;
7624
+ after?: string;
7625
+ }, tx?: TransactionContext): Promise<SubscriberReconciliationCaseRecord[]>;
7626
+ /** Closes an open case with the operator's note, once. */
7627
+ closeCase(close: CloseReconciliationCase, tx?: TransactionContext): Promise<ClosedReconciliationCase>;
7628
+ /**
7629
+ * Every gateway account a payment was collected at whose credit is still
7630
+ * owed, in part or whole, each once — the accounts that have to stay
7631
+ * configured, so a refund made there is recorded against the credit
7632
+ * (`SC-PRIC-030`). Platform-wide, asked at the start through
7633
+ * `RlsBypassPort`.
7634
+ */
7635
+ accountsHoldingCredits(tx?: TransactionContext): Promise<string[]>;
7636
+ }
5568
7637
  /**
5569
7638
  * Display form of a subscription for the tenant self-service UI.
5570
7639
  * Richer than `SubscriptionRecord` (which is only the aggregation form); contains
@@ -5659,7 +7728,7 @@ interface SubscriptionUsageRecord {
5659
7728
  * `null` for subscriptions that did not originate from a CheckoutOffer
5660
7729
  * (direct creation, migration).
5661
7730
  */
5662
- packageSnapshot?: unknown | null;
7731
+ packageSnapshot?: unknown;
5663
7732
  /**
5664
7733
  * P11.4: reference to the original `CheckoutOffer.id`. Mostly not needed
5665
7734
  * for the UI (the snapshot is self-contained), but useful for support
@@ -5907,6 +7976,14 @@ interface CancelSubscriptionInput {
5907
7976
  terminateNow: boolean;
5908
7977
  minimumTermUntil?: Date;
5909
7978
  }
7979
+ /** What `endNow` answers with. */
7980
+ interface EndSubscriptionNowResult {
7981
+ /** False where the cancellation moved since it was read, and nothing was written. */
7982
+ ended: boolean;
7983
+ canceledAt: Date | null;
7984
+ canceledEffectiveAt: Date | null;
7985
+ status: string;
7986
+ }
5910
7987
  /** What `cancelSubscription` answers with. */
5911
7988
  interface CancelSubscriptionResult {
5912
7989
  canceledAt: Date | null;
@@ -5976,6 +8053,22 @@ interface TenantSubscriptionWritePort {
5976
8053
  * unchanged, which is the ordinary case.
5977
8054
  */
5978
8055
  cancelSubscription(tenantId: string, input: CancelSubscriptionInput): Promise<CancelSubscriptionResult>;
8056
+ /**
8057
+ * Ends at `input.at` a subscription whose cancellation was declared for a
8058
+ * later date, provided its effective date is still
8059
+ * `input.expectedCanceledEffectiveAt`: both cancellation fields become
8060
+ * `input.at` and the status `CANCELED`. Answers `ended: false`, with the
8061
+ * stored fields, where the cancellation moved meanwhile. A conditional
8062
+ * claim, like `cancelSubscription`, so an end written in between is not
8063
+ * written over.
8064
+ *
8065
+ * What a feature withdrawn for an external reason lets a subscriber do,
8066
+ * cancelled or not; a subscription not cancelled is ended through
8067
+ * `cancelSubscription` with `terminateNow`. Optional, so a port written
8068
+ * before it keeps working; without it, a subscription already cancelled
8069
+ * for a later date cannot be ended at once.
8070
+ */
8071
+ endNow?(tenantId: string, input: EndNowInput): Promise<EndSubscriptionNowResult>;
5979
8072
  /**
5980
8073
  * Atomic onboarding creation: sets plan + cycle + period window
5981
8074
  * AND optionally calls a promo-redeem callback — all in a
@@ -7104,6 +9197,45 @@ interface VersionRetirementRepository {
7104
9197
  findById(id: string): Promise<VersionRetirementRecord | null>;
7105
9198
  }
7106
9199
 
9200
+ /**
9201
+ * Keeps every feature withdrawal: which feature, why, from when, the
9202
+ * reductions the operator named, when it was lifted, and when the
9203
+ * subscriptions it reaches were told. What it means for each of them is kept
9204
+ * beside it as a notice of kind `feature-withdrawn`, written in the
9205
+ * transaction that marks it told.
9206
+ *
9207
+ * An adapter translates. It does not decide whether a feature may be
9208
+ * withdrawn; it holds a feature to one withdrawal not yet lifted, so that two
9209
+ * operators announcing at once cannot both succeed, and makes lifting and
9210
+ * marking it told conditional on neither having happened yet.
9211
+ */
9212
+ interface FeatureWithdrawalRepository {
9213
+ /**
9214
+ * Records a withdrawal, in the caller's transaction where one is given, and
9215
+ * returns it as stored — the id is the adapter's to assign. Returns null
9216
+ * where a withdrawal of the same feature is recorded and not lifted: the
9217
+ * database holds a feature to one, so of two concurrent calls exactly one
9218
+ * lands.
9219
+ */
9220
+ create(data: NewFeatureWithdrawal, tx?: TransactionContext): Promise<FeatureWithdrawalRecord | null>;
9221
+ /** Every withdrawal, the most recently announced first. */
9222
+ list(): Promise<FeatureWithdrawalRecord[]>;
9223
+ findById(id: string): Promise<FeatureWithdrawalRecord | null>;
9224
+ /**
9225
+ * Records that the withdrawal `id` is lifted, provided it is not lifted
9226
+ * yet, and returns it as stored; null where it was lifted meanwhile or no
9227
+ * withdrawal has that id.
9228
+ */
9229
+ lift(id: string, lift: FeatureWithdrawalLift, tx?: TransactionContext): Promise<FeatureWithdrawalRecord | null>;
9230
+ /**
9231
+ * Records that the subscriptions the withdrawal `id` reaches were told at
9232
+ * `at`, provided nobody recorded it yet, in the caller's transaction where
9233
+ * one is given. Returns whether this call recorded it: of an announcement
9234
+ * and a run telling the same withdrawal at once, exactly one does.
9235
+ */
9236
+ markTold(id: string, at: Date, tx?: TransactionContext): Promise<boolean>;
9237
+ }
9238
+
7107
9239
  /** Class reference usable as a DI token (e.g. the consumer's `PrismaService`). */
7108
9240
  type PersistenceClassRef = abstract new (...args: never[]) => unknown;
7109
9241
  /** DI token forms a persistence bundle may reference in `inject`. */
@@ -7191,6 +9323,17 @@ interface SaaSiCatPersistenceEntitlement {
7191
9323
  subscriberRepository?: PersistenceProvider<SubscriberRepository>;
7192
9324
  /** The charges a subscriber's contracts give rise to (`tenantBilling.chargeJournal`). */
7193
9325
  subscriberLedgerRepository?: PersistenceProvider<SubscriberLedgerRepository>;
9326
+ /** The invoices issued from those charges (`tenantBilling.chargeJournal.invoices`). */
9327
+ subscriptionInvoiceRepository?: PersistenceProvider<SubscriptionInvoiceRepository>;
9328
+ /** The invoices' documents, kept in the database (`chargeJournal.invoices.archive`). */
9329
+ subscriptionInvoiceArchive?: PersistenceProvider<InvoiceArchivePort>;
9330
+ /** The attempts to collect those invoices (`chargeJournal.invoices.collections`). */
9331
+ invoiceCollectionRepository?: PersistenceProvider<InvoiceCollectionRepository>;
9332
+ /**
9333
+ * The payments those collections brought, the credits and what pays them
9334
+ * out (`chargeJournal.invoices.payments`).
9335
+ */
9336
+ subscriberPaymentRepository?: PersistenceProvider<SubscriberPaymentRepository>;
7194
9337
  subscriptionBundleRepository?: PersistenceProvider<SubscriptionBundleRepository>;
7195
9338
  bundleRepository?: PersistenceProvider<BundleRepository>;
7196
9339
  }
@@ -7234,6 +9377,11 @@ interface SaaSiCatPersistenceTenantBilling {
7234
9377
  * version is off, and retiring a plan version is not affected.
7235
9378
  */
7236
9379
  bundleVersionRetirements?: PersistenceProvider<BundleVersionRetirementRepository>;
9380
+ /**
9381
+ * The record of every feature withdrawal. Optional so an adapter written
9382
+ * before it keeps working; without it, withdrawing a feature is off.
9383
+ */
9384
+ featureWithdrawals?: PersistenceProvider<FeatureWithdrawalRepository>;
7237
9385
  }
7238
9386
  /**
7239
9387
  * The record of payment gateway callbacks and the payment methods they confirm
@@ -7677,6 +9825,79 @@ declare const BILLING_ERROR_CODES: {
7677
9825
  * show it instead of guessing.
7678
9826
  */
7679
9827
  readonly BUNDLE_VERSION_OFFER_CHANGED: "BUNDLE_VERSION_OFFER_CHANGED";
9828
+ /**
9829
+ * Withdrawing a feature is not offered: the installation's stores cannot
9830
+ * list everybody a withdrawal would reach.
9831
+ */
9832
+ readonly FEATURE_WITHDRAWAL_UNAVAILABLE: "FEATURE_WITHDRAWAL_UNAVAILABLE";
9833
+ /** The catalogue knows no feature of that key, so there is nothing to withdraw. Carries `featureKey`. */
9834
+ readonly FEATURE_WITHDRAWAL_FEATURE_UNKNOWN: "FEATURE_WITHDRAWAL_FEATURE_UNKNOWN";
9835
+ /**
9836
+ * The date names a moment before now. A feature is withdrawn from the
9837
+ * moment it is announced or from a later date: the days before were
9838
+ * delivered.
9839
+ */
9840
+ readonly FEATURE_WITHDRAWAL_DATE_IN_PAST: "FEATURE_WITHDRAWAL_DATE_IN_PAST";
9841
+ /** A withdrawal of the feature is not lifted yet; one at a time. Carries `featureKey`. */
9842
+ readonly FEATURE_WITHDRAWAL_OPEN: "FEATURE_WITHDRAWAL_OPEN";
9843
+ /**
9844
+ * A withdrawal of the feature is lifted only from a date after the one
9845
+ * named, so the two would overlap. Carries `featureKey` and the `date` a
9846
+ * new one may begin on.
9847
+ */
9848
+ readonly FEATURE_WITHDRAWAL_OVERLAPS: "FEATURE_WITHDRAWAL_OVERLAPS";
9849
+ /**
9850
+ * A reduction names a plan or an add-on, in a rhythm, that no line the
9851
+ * withdrawal reaches is. Carries `kind`, `key` and `billingCycle`.
9852
+ */
9853
+ readonly FEATURE_WITHDRAWAL_REDUCTION_NOT_REACHED: "FEATURE_WITHDRAWAL_REDUCTION_NOT_REACHED";
9854
+ /** A reduction is named twice. Carries `kind`, `key` and `billingCycle`. */
9855
+ readonly FEATURE_WITHDRAWAL_REDUCTION_NAMED_TWICE: "FEATURE_WITHDRAWAL_REDUCTION_NAMED_TWICE";
9856
+ /**
9857
+ * A reduction is more than the lowest price among the lines it reduces:
9858
+ * a price is reduced to nothing at most. Carries `key`, `billingCycle` and
9859
+ * that `price`.
9860
+ */
9861
+ readonly FEATURE_WITHDRAWAL_REDUCTION_EXCEEDS_PRICE: "FEATURE_WITHDRAWAL_REDUCTION_EXCEEDS_PRICE";
9862
+ /**
9863
+ * The subscriptions the withdrawal reaches changed since the preview the
9864
+ * operator looked at. Nothing was announced; carries the current `preview`.
9865
+ */
9866
+ readonly FEATURE_WITHDRAWAL_PREVIEW_CHANGED: "FEATURE_WITHDRAWAL_PREVIEW_CHANGED";
9867
+ /** No withdrawal has that id. Carries `withdrawalId`. */
9868
+ readonly FEATURE_WITHDRAWAL_NOT_FOUND: "FEATURE_WITHDRAWAL_NOT_FOUND";
9869
+ /** The withdrawal was lifted already. Carries the `date` it is lifted from. */
9870
+ readonly FEATURE_WITHDRAWAL_ALREADY_LIFTED: "FEATURE_WITHDRAWAL_ALREADY_LIFTED";
9871
+ /**
9872
+ * Nobody the withdrawal reaches has been told of it yet, and telling them
9873
+ * failed just now: a withdrawal is lifted only once they were. Nothing was
9874
+ * lifted; the next try, or the quarter-hourly run, tells them first.
9875
+ */
9876
+ readonly FEATURE_WITHDRAWAL_NOT_TOLD_YET: "FEATURE_WITHDRAWAL_NOT_TOLD_YET";
9877
+ /**
9878
+ * The date a withdrawal would be lifted from lies before now: what was
9879
+ * withdrawn until then was withdrawn.
9880
+ */
9881
+ readonly FEATURE_WITHDRAWAL_LIFT_IN_PAST: "FEATURE_WITHDRAWAL_LIFT_IN_PAST";
9882
+ /**
9883
+ * The withdrawal does not take its feature away now — its date is ahead,
9884
+ * or it was lifted — so nothing ends at once because of it. Carries
9885
+ * `featureKey`.
9886
+ */
9887
+ readonly FEATURE_WITHDRAWAL_NOT_IN_EFFECT: "FEATURE_WITHDRAWAL_NOT_IN_EFFECT";
9888
+ /**
9889
+ * The withdrawal did not reach the subscription, or the line to end: it
9890
+ * was not running at the announcement, or no longer holds the feature.
9891
+ */
9892
+ readonly FEATURE_WITHDRAWAL_DOES_NOT_REACH: "FEATURE_WITHDRAWAL_DOES_NOT_REACH";
9893
+ /** What was to be ended at once has ended already. */
9894
+ readonly FEATURE_WITHDRAWAL_ALREADY_ENDED: "FEATURE_WITHDRAWAL_ALREADY_ENDED";
9895
+ /**
9896
+ * A cancellation is declared for a later date, and the installation's
9897
+ * subscription write or booking store cannot bring it forward (`endNow`).
9898
+ * It ends as declared. Carries that `date`.
9899
+ */
9900
+ readonly FEATURE_WITHDRAWAL_END_NOW_UNSUPPORTED: "FEATURE_WITHDRAWAL_END_NOW_UNSUPPORTED";
7680
9901
  /** The subscription has ended; its plan can no longer be changed. */
7681
9902
  readonly SUBSCRIPTION_ENDED: "SUBSCRIPTION_ENDED";
7682
9903
  /** An active special contract blocks self-service plan changes. */
@@ -7823,6 +10044,94 @@ declare const CONTRACT_ERROR_CODES: {
7823
10044
  readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_DECIDED";
7824
10045
  };
7825
10046
  type ContractErrorCode = (typeof CONTRACT_ERROR_CODES)[keyof typeof CONTRACT_ERROR_CODES];
10047
+ /** Invoices issued from the charge journal (`SubscriptionInvoiceService`). */
10048
+ declare const INVOICE_ERROR_CODES: {
10049
+ /**
10050
+ * A charge already stands on an invoice: a second run issuing the same
10051
+ * charges lost the race. Nothing is written and no number is drawn.
10052
+ */
10053
+ readonly SUBSCRIPTION_INVOICE_CHARGE_INVOICED: "SUBSCRIPTION_INVOICE_CHARGE_INVOICED";
10054
+ /**
10055
+ * The invoice lacks content the tax adapter requires of it — `missing`
10056
+ * names the fields, `adapter` the adapter. It draws no number and waits
10057
+ * until what is missing is supplied (`SC-PRIC-027`).
10058
+ */
10059
+ readonly SUBSCRIPTION_INVOICE_CONTENT_INCOMPLETE: "SUBSCRIPTION_INVOICE_CONTENT_INCOMPLETE";
10060
+ /**
10061
+ * The contract's parties were copied by a migration and the operator has
10062
+ * not confirmed them yet; its charges are not invoiced until then
10063
+ * (`SC-AUD-012`).
10064
+ */
10065
+ readonly SUBSCRIPTION_INVOICE_PARTIES_UNCONFIRMED: "SUBSCRIPTION_INVOICE_PARTIES_UNCONFIRMED";
10066
+ /**
10067
+ * The subscriber's direct debit names no mandate reference
10068
+ * (`paymentMethodId`), which has to be announced before it is debited
10069
+ * (`SC-PRIC-028`). An invoice collected by it draws no number, and one
10070
+ * planned with it is not announced, until the payment method is replaced.
10071
+ */
10072
+ readonly SUBSCRIPTION_INVOICE_MANDATE_MISSING: "SUBSCRIPTION_INVOICE_MANDATE_MISSING";
10073
+ /**
10074
+ * The subscriber (`subscriberId`) has no payment method in use, so the
10075
+ * invoice is not collected until one is (`SC-PRIC-082`).
10076
+ */
10077
+ readonly SUBSCRIPTION_INVOICE_NO_PAYMENT_METHOD: "SUBSCRIPTION_INVOICE_NO_PAYMENT_METHOD";
10078
+ /**
10079
+ * A direct debit announced again after a failed collection (`attemptKey`)
10080
+ * waits until the subscriber has been told of that failure
10081
+ * (`SC-PRIC-080`).
10082
+ */
10083
+ readonly SUBSCRIPTION_INVOICE_FAILURE_NOT_TOLD: "SUBSCRIPTION_INVOICE_FAILURE_NOT_TOLD";
10084
+ /**
10085
+ * A file of the invoice's document has another checksum than the one
10086
+ * recorded or archived for it (`invoiceId`, `recorded`, `rendered`), and
10087
+ * the first stays. The run takes the archived file as the one issued, or —
10088
+ * where nothing is archived — records the new rendering in place of the
10089
+ * old (`SC-AUD-019`); the invoice waits only where another run changed the
10090
+ * record or the archive in between, and the next run settles it.
10091
+ */
10092
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED: "SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED";
10093
+ /**
10094
+ * The tax adapter refuses the rendered document — `missing` names what it
10095
+ * lacks or disagrees with, `adapter` the adapter. The invoice keeps its
10096
+ * number and waits for a document that passes (`SC-PRIC-042`).
10097
+ */
10098
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_REFUSED: "SUBSCRIPTION_INVOICE_DOCUMENT_REFUSED";
10099
+ /**
10100
+ * The archived document does not match the checksum recorded when it was
10101
+ * rendered (`invoiceId`). It is not handed out (`SC-AUD-019`).
10102
+ */
10103
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_MISMATCH: "SUBSCRIPTION_INVOICE_DOCUMENT_MISMATCH";
10104
+ /** The invoice's document is not archived yet (`invoiceId`); nothing is offered until it is (`SC-AUD-014`). */
10105
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_NOT_ARCHIVED: "SUBSCRIPTION_INVOICE_DOCUMENT_NOT_ARCHIVED";
10106
+ /** No invoice with this id (`invoiceId`). */
10107
+ readonly SUBSCRIPTION_INVOICE_NOT_FOUND: "SUBSCRIPTION_INVOICE_NOT_FOUND";
10108
+ /**
10109
+ * The subscriber's record holds no invoice email (`subscriberId`), so the
10110
+ * archived invoice cannot be sent (`SC-PRIC-047`); it is sent once one is
10111
+ * entered.
10112
+ */
10113
+ readonly SUBSCRIPTION_INVOICE_NO_INVOICE_EMAIL: "SUBSCRIPTION_INVOICE_NO_INVOICE_EMAIL";
10114
+ /** No credit under this id for the tenant's subscriber (`creditId`). */
10115
+ readonly SUBSCRIBER_CREDIT_NOT_FOUND: "SUBSCRIBER_CREDIT_NOT_FOUND";
10116
+ /**
10117
+ * A payout of more than the credit still owes (`creditId`, `open`): nothing
10118
+ * is paid out beyond it (`SC-PRIC-083`), and nothing is recorded.
10119
+ */
10120
+ readonly SUBSCRIBER_PAYOUT_EXCEEDS_CREDIT: "SUBSCRIBER_PAYOUT_EXCEEDS_CREDIT";
10121
+ /**
10122
+ * A payout on a day still to come (`paidOn`, `today` in the installation's
10123
+ * zone): a payout is recorded once it left.
10124
+ */
10125
+ readonly SUBSCRIBER_PAYOUT_NOT_MADE_YET: "SUBSCRIBER_PAYOUT_NOT_MADE_YET";
10126
+ /** No case to reconcile under this id (`caseId`). */
10127
+ readonly SUBSCRIBER_RECONCILIATION_CASE_NOT_FOUND: "SUBSCRIBER_RECONCILIATION_CASE_NOT_FOUND";
10128
+ /**
10129
+ * A case closed before (`caseId`, `closedAt`), by the operator or by
10130
+ * SaaSiCat; its note stands, and nothing is written (`SC-ADM-033`).
10131
+ */
10132
+ readonly SUBSCRIBER_RECONCILIATION_CASE_CLOSED: "SUBSCRIBER_RECONCILIATION_CASE_CLOSED";
10133
+ };
10134
+ type InvoiceErrorCode = (typeof INVOICE_ERROR_CODES)[keyof typeof INVOICE_ERROR_CODES];
7826
10135
  /** The parties contracts are concluded with (`SubscriberService`), and their absence. */
7827
10136
  declare const SUBSCRIBER_ERROR_CODES: {
7828
10137
  /**
@@ -8118,28 +10427,112 @@ declare const PLATFORM_ERROR_CODES: {
8118
10427
  /** The operator declared another legal entity: that is a transfer, not an edit. */
8119
10428
  readonly SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER";
8120
10429
  /**
8121
- * A contact change named whether the subscriber is a business. That is part
8122
- * of its tax origin and changes as a recorded change naming who made it.
10430
+ * A contact change named whether the subscriber is a business. That is part
10431
+ * of its tax origin and changes as a recorded change naming who made it.
10432
+ */
10433
+ readonly SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT: "SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT";
10434
+ /** A change of the subscriber's contact details or business status did not say who makes it. */
10435
+ readonly SUBSCRIBER_CHANGE_ACTOR_REQUIRED: "SUBSCRIBER_CHANGE_ACTOR_REQUIRED";
10436
+ /**
10437
+ * Where a tax adapter decides, a contract names its subscriber only once
10438
+ * the address an invoice names is complete (`SC-PRIC-032`): a party copied
10439
+ * onto a contract incomplete cannot be completed afterwards. Carries
10440
+ * `missing`, the empty fields, for a screen to name by their labels; the
10441
+ * shipped sentence names all four rather than the keys.
10442
+ */
10443
+ readonly SUBSCRIBER_IDENTITY_INCOMPLETE: "SUBSCRIBER_IDENTITY_INCOMPLETE";
10444
+ /**
10445
+ * A change of whether the subscriber is a business states no reason. It
10446
+ * decides the tax treatment of the next invoice, so the change log keeps
10447
+ * why it moved (`SC-PRIC-043`).
10448
+ */
10449
+ readonly SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED: "SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED";
10450
+ /** A check of the subscriber's VAT identification number was asked for, and it holds none. */
10451
+ readonly SUBSCRIBER_VAT_ID_MISSING: "SUBSCRIBER_VAT_ID_MISSING";
10452
+ /**
10453
+ * A charge already stands on an invoice: a second run issuing the same
10454
+ * charges lost the race. Nothing is written and no number is drawn.
10455
+ */
10456
+ readonly SUBSCRIPTION_INVOICE_CHARGE_INVOICED: "SUBSCRIPTION_INVOICE_CHARGE_INVOICED";
10457
+ /**
10458
+ * The invoice lacks content the tax adapter requires of it — `missing`
10459
+ * names the fields, `adapter` the adapter. It draws no number and waits
10460
+ * until what is missing is supplied (`SC-PRIC-027`).
10461
+ */
10462
+ readonly SUBSCRIPTION_INVOICE_CONTENT_INCOMPLETE: "SUBSCRIPTION_INVOICE_CONTENT_INCOMPLETE";
10463
+ /**
10464
+ * The contract's parties were copied by a migration and the operator has
10465
+ * not confirmed them yet; its charges are not invoiced until then
10466
+ * (`SC-AUD-012`).
10467
+ */
10468
+ readonly SUBSCRIPTION_INVOICE_PARTIES_UNCONFIRMED: "SUBSCRIPTION_INVOICE_PARTIES_UNCONFIRMED";
10469
+ /**
10470
+ * The subscriber's direct debit names no mandate reference
10471
+ * (`paymentMethodId`), which has to be announced before it is debited
10472
+ * (`SC-PRIC-028`). An invoice collected by it draws no number, and one
10473
+ * planned with it is not announced, until the payment method is replaced.
10474
+ */
10475
+ readonly SUBSCRIPTION_INVOICE_MANDATE_MISSING: "SUBSCRIPTION_INVOICE_MANDATE_MISSING";
10476
+ /**
10477
+ * The subscriber (`subscriberId`) has no payment method in use, so the
10478
+ * invoice is not collected until one is (`SC-PRIC-082`).
10479
+ */
10480
+ readonly SUBSCRIPTION_INVOICE_NO_PAYMENT_METHOD: "SUBSCRIPTION_INVOICE_NO_PAYMENT_METHOD";
10481
+ /**
10482
+ * A direct debit announced again after a failed collection (`attemptKey`)
10483
+ * waits until the subscriber has been told of that failure
10484
+ * (`SC-PRIC-080`).
10485
+ */
10486
+ readonly SUBSCRIPTION_INVOICE_FAILURE_NOT_TOLD: "SUBSCRIPTION_INVOICE_FAILURE_NOT_TOLD";
10487
+ /**
10488
+ * A file of the invoice's document has another checksum than the one
10489
+ * recorded or archived for it (`invoiceId`, `recorded`, `rendered`), and
10490
+ * the first stays. The run takes the archived file as the one issued, or —
10491
+ * where nothing is archived — records the new rendering in place of the
10492
+ * old (`SC-AUD-019`); the invoice waits only where another run changed the
10493
+ * record or the archive in between, and the next run settles it.
10494
+ */
10495
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED: "SUBSCRIPTION_INVOICE_DOCUMENT_CHANGED";
10496
+ /**
10497
+ * The tax adapter refuses the rendered document — `missing` names what it
10498
+ * lacks or disagrees with, `adapter` the adapter. The invoice keeps its
10499
+ * number and waits for a document that passes (`SC-PRIC-042`).
10500
+ */
10501
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_REFUSED: "SUBSCRIPTION_INVOICE_DOCUMENT_REFUSED";
10502
+ /**
10503
+ * The archived document does not match the checksum recorded when it was
10504
+ * rendered (`invoiceId`). It is not handed out (`SC-AUD-019`).
10505
+ */
10506
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_MISMATCH: "SUBSCRIPTION_INVOICE_DOCUMENT_MISMATCH";
10507
+ /** The invoice's document is not archived yet (`invoiceId`); nothing is offered until it is (`SC-AUD-014`). */
10508
+ readonly SUBSCRIPTION_INVOICE_DOCUMENT_NOT_ARCHIVED: "SUBSCRIPTION_INVOICE_DOCUMENT_NOT_ARCHIVED";
10509
+ /** No invoice with this id (`invoiceId`). */
10510
+ readonly SUBSCRIPTION_INVOICE_NOT_FOUND: "SUBSCRIPTION_INVOICE_NOT_FOUND";
10511
+ /**
10512
+ * The subscriber's record holds no invoice email (`subscriberId`), so the
10513
+ * archived invoice cannot be sent (`SC-PRIC-047`); it is sent once one is
10514
+ * entered.
8123
10515
  */
8124
- readonly SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT: "SUBSCRIBER_BUSINESS_STATUS_NOT_A_CONTACT";
8125
- /** A change of the subscriber's contact details or business status did not say who makes it. */
8126
- readonly SUBSCRIBER_CHANGE_ACTOR_REQUIRED: "SUBSCRIBER_CHANGE_ACTOR_REQUIRED";
10516
+ readonly SUBSCRIPTION_INVOICE_NO_INVOICE_EMAIL: "SUBSCRIPTION_INVOICE_NO_INVOICE_EMAIL";
10517
+ /** No credit under this id for the tenant's subscriber (`creditId`). */
10518
+ readonly SUBSCRIBER_CREDIT_NOT_FOUND: "SUBSCRIBER_CREDIT_NOT_FOUND";
8127
10519
  /**
8128
- * Where a tax adapter decides, a contract names its subscriber only once
8129
- * the address an invoice names is complete (`SC-PRIC-032`): a party copied
8130
- * onto a contract incomplete cannot be completed afterwards. Carries
8131
- * `missing`, the empty fields, for a screen to name by their labels; the
8132
- * shipped sentence names all four rather than the keys.
10520
+ * A payout of more than the credit still owes (`creditId`, `open`): nothing
10521
+ * is paid out beyond it (`SC-PRIC-083`), and nothing is recorded.
8133
10522
  */
8134
- readonly SUBSCRIBER_IDENTITY_INCOMPLETE: "SUBSCRIBER_IDENTITY_INCOMPLETE";
10523
+ readonly SUBSCRIBER_PAYOUT_EXCEEDS_CREDIT: "SUBSCRIBER_PAYOUT_EXCEEDS_CREDIT";
8135
10524
  /**
8136
- * A change of whether the subscriber is a business states no reason. It
8137
- * decides the tax treatment of the next invoice, so the change log keeps
8138
- * why it moved (`SC-PRIC-043`).
10525
+ * A payout on a day still to come (`paidOn`, `today` in the installation's
10526
+ * zone): a payout is recorded once it left.
8139
10527
  */
8140
- readonly SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED: "SUBSCRIBER_BUSINESS_STATUS_REASON_REQUIRED";
8141
- /** A check of the subscriber's VAT identification number was asked for, and it holds none. */
8142
- readonly SUBSCRIBER_VAT_ID_MISSING: "SUBSCRIBER_VAT_ID_MISSING";
10528
+ readonly SUBSCRIBER_PAYOUT_NOT_MADE_YET: "SUBSCRIBER_PAYOUT_NOT_MADE_YET";
10529
+ /** No case to reconcile under this id (`caseId`). */
10530
+ readonly SUBSCRIBER_RECONCILIATION_CASE_NOT_FOUND: "SUBSCRIBER_RECONCILIATION_CASE_NOT_FOUND";
10531
+ /**
10532
+ * A case closed before (`caseId`, `closedAt`), by the operator or by
10533
+ * SaaSiCat; its note stands, and nothing is written (`SC-ADM-033`).
10534
+ */
10535
+ readonly SUBSCRIBER_RECONCILIATION_CASE_CLOSED: "SUBSCRIBER_RECONCILIATION_CASE_CLOSED";
8143
10536
  readonly CHECKOUT_OFFER_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_LINE_ITEMS_REQUIRED";
8144
10537
  readonly CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED: "CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED";
8145
10538
  readonly CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED: "CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED";
@@ -8447,6 +10840,79 @@ declare const PLATFORM_ERROR_CODES: {
8447
10840
  * show it instead of guessing.
8448
10841
  */
8449
10842
  readonly BUNDLE_VERSION_OFFER_CHANGED: "BUNDLE_VERSION_OFFER_CHANGED";
10843
+ /**
10844
+ * Withdrawing a feature is not offered: the installation's stores cannot
10845
+ * list everybody a withdrawal would reach.
10846
+ */
10847
+ readonly FEATURE_WITHDRAWAL_UNAVAILABLE: "FEATURE_WITHDRAWAL_UNAVAILABLE";
10848
+ /** The catalogue knows no feature of that key, so there is nothing to withdraw. Carries `featureKey`. */
10849
+ readonly FEATURE_WITHDRAWAL_FEATURE_UNKNOWN: "FEATURE_WITHDRAWAL_FEATURE_UNKNOWN";
10850
+ /**
10851
+ * The date names a moment before now. A feature is withdrawn from the
10852
+ * moment it is announced or from a later date: the days before were
10853
+ * delivered.
10854
+ */
10855
+ readonly FEATURE_WITHDRAWAL_DATE_IN_PAST: "FEATURE_WITHDRAWAL_DATE_IN_PAST";
10856
+ /** A withdrawal of the feature is not lifted yet; one at a time. Carries `featureKey`. */
10857
+ readonly FEATURE_WITHDRAWAL_OPEN: "FEATURE_WITHDRAWAL_OPEN";
10858
+ /**
10859
+ * A withdrawal of the feature is lifted only from a date after the one
10860
+ * named, so the two would overlap. Carries `featureKey` and the `date` a
10861
+ * new one may begin on.
10862
+ */
10863
+ readonly FEATURE_WITHDRAWAL_OVERLAPS: "FEATURE_WITHDRAWAL_OVERLAPS";
10864
+ /**
10865
+ * A reduction names a plan or an add-on, in a rhythm, that no line the
10866
+ * withdrawal reaches is. Carries `kind`, `key` and `billingCycle`.
10867
+ */
10868
+ readonly FEATURE_WITHDRAWAL_REDUCTION_NOT_REACHED: "FEATURE_WITHDRAWAL_REDUCTION_NOT_REACHED";
10869
+ /** A reduction is named twice. Carries `kind`, `key` and `billingCycle`. */
10870
+ readonly FEATURE_WITHDRAWAL_REDUCTION_NAMED_TWICE: "FEATURE_WITHDRAWAL_REDUCTION_NAMED_TWICE";
10871
+ /**
10872
+ * A reduction is more than the lowest price among the lines it reduces:
10873
+ * a price is reduced to nothing at most. Carries `key`, `billingCycle` and
10874
+ * that `price`.
10875
+ */
10876
+ readonly FEATURE_WITHDRAWAL_REDUCTION_EXCEEDS_PRICE: "FEATURE_WITHDRAWAL_REDUCTION_EXCEEDS_PRICE";
10877
+ /**
10878
+ * The subscriptions the withdrawal reaches changed since the preview the
10879
+ * operator looked at. Nothing was announced; carries the current `preview`.
10880
+ */
10881
+ readonly FEATURE_WITHDRAWAL_PREVIEW_CHANGED: "FEATURE_WITHDRAWAL_PREVIEW_CHANGED";
10882
+ /** No withdrawal has that id. Carries `withdrawalId`. */
10883
+ readonly FEATURE_WITHDRAWAL_NOT_FOUND: "FEATURE_WITHDRAWAL_NOT_FOUND";
10884
+ /** The withdrawal was lifted already. Carries the `date` it is lifted from. */
10885
+ readonly FEATURE_WITHDRAWAL_ALREADY_LIFTED: "FEATURE_WITHDRAWAL_ALREADY_LIFTED";
10886
+ /**
10887
+ * Nobody the withdrawal reaches has been told of it yet, and telling them
10888
+ * failed just now: a withdrawal is lifted only once they were. Nothing was
10889
+ * lifted; the next try, or the quarter-hourly run, tells them first.
10890
+ */
10891
+ readonly FEATURE_WITHDRAWAL_NOT_TOLD_YET: "FEATURE_WITHDRAWAL_NOT_TOLD_YET";
10892
+ /**
10893
+ * The date a withdrawal would be lifted from lies before now: what was
10894
+ * withdrawn until then was withdrawn.
10895
+ */
10896
+ readonly FEATURE_WITHDRAWAL_LIFT_IN_PAST: "FEATURE_WITHDRAWAL_LIFT_IN_PAST";
10897
+ /**
10898
+ * The withdrawal does not take its feature away now — its date is ahead,
10899
+ * or it was lifted — so nothing ends at once because of it. Carries
10900
+ * `featureKey`.
10901
+ */
10902
+ readonly FEATURE_WITHDRAWAL_NOT_IN_EFFECT: "FEATURE_WITHDRAWAL_NOT_IN_EFFECT";
10903
+ /**
10904
+ * The withdrawal did not reach the subscription, or the line to end: it
10905
+ * was not running at the announcement, or no longer holds the feature.
10906
+ */
10907
+ readonly FEATURE_WITHDRAWAL_DOES_NOT_REACH: "FEATURE_WITHDRAWAL_DOES_NOT_REACH";
10908
+ /** What was to be ended at once has ended already. */
10909
+ readonly FEATURE_WITHDRAWAL_ALREADY_ENDED: "FEATURE_WITHDRAWAL_ALREADY_ENDED";
10910
+ /**
10911
+ * A cancellation is declared for a later date, and the installation's
10912
+ * subscription write or booking store cannot bring it forward (`endNow`).
10913
+ * It ends as declared. Carries that `date`.
10914
+ */
10915
+ readonly FEATURE_WITHDRAWAL_END_NOW_UNSUPPORTED: "FEATURE_WITHDRAWAL_END_NOW_UNSUPPORTED";
8450
10916
  /** The subscription has ended; its plan can no longer be changed. */
8451
10917
  readonly SUBSCRIPTION_ENDED: "SUBSCRIPTION_ENDED";
8452
10918
  /** An active special contract blocks self-service plan changes. */
@@ -8674,7 +11140,7 @@ declare const PLATFORM_ERROR_CODES: {
8674
11140
  /** Email already taken (mapped from `PlatformUserExistsError`). */
8675
11141
  readonly EMAIL_EXISTS: "EMAIL_EXISTS";
8676
11142
  };
8677
- type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | SubscriberErrorCode | RegistrationErrorCode | PaymentErrorCode | SettingsErrorCode | MaintenanceErrorCode | TaxErrorCode;
11143
+ type PlatformErrorCode = SetupErrorCode | AuthErrorCode | PromoErrorCode | CatalogErrorCode | BillingErrorCode | ContractErrorCode | InvoiceErrorCode | SubscriberErrorCode | RegistrationErrorCode | PaymentErrorCode | SettingsErrorCode | MaintenanceErrorCode | TaxErrorCode;
8678
11144
  /**
8679
11145
  * Shape of a coded error response.
8680
11146
  *
@@ -8759,7 +11225,21 @@ declare const OPTIONAL_CANONICAL_MODELS: {
8759
11225
  readonly SubscriptionNotice: readonly ["tenantBilling.subscriptionNotices"];
8760
11226
  readonly VersionRetirement: readonly ["tenantBilling.versionRetirements"];
8761
11227
  readonly BundleVersionRetirement: readonly ["tenantBilling.bundleVersionRetirements"];
11228
+ readonly FeatureWithdrawal: readonly ["tenantBilling.featureWithdrawals"];
8762
11229
  readonly SubscriberLedgerEntry: readonly ["entitlement.subscriberLedgerRepository"];
11230
+ readonly SubscriptionInvoice: readonly ["entitlement.subscriptionInvoiceRepository"];
11231
+ readonly SubscriptionInvoiceLine: readonly ["entitlement.subscriptionInvoiceRepository"];
11232
+ readonly SubscriptionInvoiceNumber: readonly ["entitlement.subscriptionInvoiceRepository"];
11233
+ readonly SubscriptionInvoiceDocument: readonly ["entitlement.subscriptionInvoiceRepository"];
11234
+ readonly SubscriptionInvoiceArchive: readonly ["entitlement.subscriptionInvoiceArchive"];
11235
+ readonly SubscriptionInvoiceCollection: readonly ["entitlement.invoiceCollectionRepository", "entitlement.subscriberPaymentRepository"];
11236
+ readonly SubscriberPayment: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11237
+ readonly SubscriptionInvoiceSettlement: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11238
+ readonly SubscriberCredit: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11239
+ readonly SubscriberCreditEntry: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11240
+ readonly SubscriberRefund: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11241
+ readonly SubscriberReversal: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
11242
+ readonly SubscriberReconciliationCase: readonly ["entitlement.subscriberPaymentRepository", "entitlement.invoiceCollectionRepository"];
8763
11243
  readonly PromoCodeHold: readonly ["promo.holdRepository"];
8764
11244
  };
8765
11245
  type OptionalCanonicalModel = keyof typeof OPTIONAL_CANONICAL_MODELS;
@@ -9765,6 +12245,10 @@ type IssuerIdentityChange =
9765
12245
  */
9766
12246
  declare function classifyIssuerChange(recorded: LegalIdentity | null, issuer: PlanCatalogIssuer | undefined): IssuerIdentityChange;
9767
12247
 
12248
+ /** Every origin a charge may name, as a record or a line that copies one is checked against. */
12249
+ declare const SUBSCRIBER_CHARGE_ORIGINS: readonly SubscriberChargeOrigin[];
12250
+ /** Every source a charge may name. */
12251
+ declare const SUBSCRIBER_CHARGE_SOURCES: readonly SubscriberChargeSource[];
9768
12252
  /**
9769
12253
  * A `subscriber_ledger_entries` row as either adapter reads it back. The amount
9770
12254
  * is `unknown` because a Prisma row carries a `Decimal` where a Drizzle row
@@ -9806,6 +12290,865 @@ declare function subscriberChargeColumns(charge: NewSubscriberCharge): Omit<Cano
9806
12290
  amountNet: string;
9807
12291
  };
9808
12292
 
12293
+ /**
12294
+ * A `subscription_invoices` row as either adapter reads it back. Amounts are
12295
+ * `unknown` because a Prisma row carries a `Decimal` where a Drizzle row carries
12296
+ * a numeric string, and days because one carries a `Date` at midnight UTC where
12297
+ * the other carries the text.
12298
+ */
12299
+ interface CanonicalSubscriptionInvoiceRow {
12300
+ id: string;
12301
+ number: string;
12302
+ numberPrefix: string;
12303
+ numberYear: number;
12304
+ numberSequence: number;
12305
+ tenantId: string;
12306
+ subscriberId: string;
12307
+ subscriptionId: string;
12308
+ contractId: string;
12309
+ issuedAt: Date;
12310
+ issueDate: unknown;
12311
+ dueDate: unknown;
12312
+ servicePeriodFrom: unknown;
12313
+ servicePeriodUntil: unknown;
12314
+ /** `null` on an invoice that is not collected, and on one issued before invoices recorded it. */
12315
+ payment: unknown;
12316
+ collectionDate: unknown;
12317
+ currency: string;
12318
+ issuerParty: unknown;
12319
+ subscriberParty: unknown;
12320
+ footer: unknown;
12321
+ taxTreatment: unknown;
12322
+ taxes: unknown;
12323
+ totalNet: unknown;
12324
+ totalTax: unknown;
12325
+ totalGross: unknown;
12326
+ createdAt: Date;
12327
+ }
12328
+ /** A `subscription_invoice_lines` row as either adapter reads it back. */
12329
+ interface CanonicalSubscriptionInvoiceLineRow {
12330
+ id: string;
12331
+ invoiceId: string;
12332
+ position: number;
12333
+ chargeId: string;
12334
+ contractLineItemId: string;
12335
+ title: string;
12336
+ origin: string;
12337
+ source: string;
12338
+ periodFrom: unknown;
12339
+ periodUntil: unknown;
12340
+ amountNet: unknown;
12341
+ taxRate: unknown;
12342
+ }
12343
+ /** Reads an invoice row and its lines back as a record, the lines in their order. */
12344
+ declare function toSubscriptionInvoiceRecord(row: CanonicalSubscriptionInvoiceRow, lines: readonly CanonicalSubscriptionInvoiceLineRow[]): SubscriptionInvoiceRecord;
12345
+ /**
12346
+ * The columns an invoice is written with: amounts as decimal strings of two
12347
+ * places, as a charge's are, and days as their text, which each adapter turns
12348
+ * into what its date column takes.
12349
+ */
12350
+ interface SubscriptionInvoiceColumns {
12351
+ number: string;
12352
+ numberPrefix: string;
12353
+ numberYear: number;
12354
+ numberSequence: number;
12355
+ tenantId: string;
12356
+ subscriberId: string;
12357
+ subscriptionId: string;
12358
+ contractId: string;
12359
+ issuedAt: Date;
12360
+ issueDate: CalendarDay;
12361
+ dueDate: CalendarDay;
12362
+ servicePeriodFrom: CalendarDay;
12363
+ servicePeriodUntil: CalendarDay;
12364
+ payment: SubscriptionInvoicePayment | null;
12365
+ collectionDate: CalendarDay | null;
12366
+ currency: string;
12367
+ issuerParty: SubscriptionInvoiceIssuer;
12368
+ subscriberParty: SubscriptionInvoiceSubscriber;
12369
+ footer: string[];
12370
+ taxTreatment: Record<string, unknown>;
12371
+ taxes: TaxAtRate[];
12372
+ totalNet: string;
12373
+ totalTax: string;
12374
+ totalGross: string;
12375
+ }
12376
+ /** The columns a line is written with, in the form `SubscriptionInvoiceColumns` describes. */
12377
+ interface SubscriptionInvoiceLineColumns {
12378
+ invoiceId: string;
12379
+ position: number;
12380
+ chargeId: string;
12381
+ contractLineItemId: string;
12382
+ title: string;
12383
+ origin: string;
12384
+ source: string;
12385
+ periodFrom: CalendarDay;
12386
+ periodUntil: CalendarDay;
12387
+ amountNet: string;
12388
+ taxRate: string;
12389
+ }
12390
+ /** The columns an invoice is written with, given the number the store drew. */
12391
+ declare function subscriptionInvoiceColumns(invoice: NewSubscriptionInvoice, drawn: {
12392
+ number: string;
12393
+ numberSequence: number;
12394
+ }): SubscriptionInvoiceColumns;
12395
+ /** The columns a line is written with. */
12396
+ declare function subscriptionInvoiceLineColumns(line: NewSubscriptionInvoiceLine, invoiceId: string): SubscriptionInvoiceLineColumns;
12397
+ /** A day as the `Date` at midnight UTC a Prisma `@db.Date` column takes. */
12398
+ declare function utcMidnightOf(day: CalendarDay): Date;
12399
+
12400
+ /**
12401
+ * A charge that already stands on an invoice: what the unique `chargeId` of
12402
+ * the invoice lines answers when two runs issue the same charges at once. The
12403
+ * invoice is not written and its number not drawn.
12404
+ */
12405
+ declare function subscriptionInvoiceChargeInvoiced(chargeId: string): PersistenceRefusal;
12406
+ /**
12407
+ * A rendering of an invoice's document whose checksum is not the one recorded
12408
+ * or archived for it, refused: the first stays. Only the run replaces a
12409
+ * recorded rendering, and only while nothing is archived (`SC-AUD-019`).
12410
+ */
12411
+ declare function subscriptionInvoiceDocumentChanged(invoiceId: string, recorded: string, rendered: string): PersistenceRefusal;
12412
+
12413
+ /** The charges one invoice issues: booked at the same moment under the same contract. */
12414
+ interface InvoiceGroup {
12415
+ contractId: string;
12416
+ bookedAt: Date;
12417
+ charges: SubscriberChargeRecord[];
12418
+ }
12419
+ /**
12420
+ * A subscription's charges left to invoice, as the invoices that issue them.
12421
+ *
12422
+ * The charges a billing period opens with are booked together and issued
12423
+ * together; a charge that arises later in the period is booked when it arises
12424
+ * and issued on an invoice of its own (`SC-PRIC-022`). A contract is the
12425
+ * agreement an invoice asks payment under, so charges of two contracts are
12426
+ * never on one invoice. The oldest come first, so numbers follow the charges.
12427
+ * A group whose charges are all zero issues no invoice (`SC-PRIC-048`) and is
12428
+ * left out; a charge of zero beside one that is not stays on its invoice.
12429
+ */
12430
+ declare function invoiceGroupsOf(charges: readonly SubscriberChargeRecord[]): InvoiceGroup[];
12431
+ /** What an invoice is drawn up from. */
12432
+ interface InvoiceDraftInput {
12433
+ group: InvoiceGroup;
12434
+ /** The contract the group's charges belong to: where each line takes its title and place. */
12435
+ contractLines: readonly Pick<ContractLineItemRecord, 'id' | 'titleSnapshot'>[];
12436
+ tenantId: string;
12437
+ subscriberId: string;
12438
+ subscriber: SubscriptionInvoiceSubscriber;
12439
+ issuer: SubscriptionInvoiceIssuer;
12440
+ /** The footer lines `config/saas.yaml` names now (`SC-PRIC-077`). */
12441
+ footer: readonly string[];
12442
+ /** The treatment the tax adapter decides for the subscriber now (`SC-PRIC-043`). */
12443
+ treatment: TaxTreatment;
12444
+ /** The adapter's rule for the tax of an invoice (`SC-PRIC-041`). */
12445
+ tax: (lines: readonly InvoiceTaxLine[]) => TaxPerRate;
12446
+ issuedAt: Date;
12447
+ /** The installation's time zone, which every day the invoice states is read in (`SC-PRIC-045`). */
12448
+ timeZone: string;
12449
+ numberPrefix: string;
12450
+ /** Days from the issue date to the due date, unless collected by direct debit (`SC-PRIC-046`). */
12451
+ paymentTermDays: number;
12452
+ /**
12453
+ * The subscriber's payment method as `invoicePaymentOf` records it, or
12454
+ * `null` where it has none that can be collected.
12455
+ */
12456
+ payment: SubscriptionInvoicePayment | null;
12457
+ /** Days from the issue date to the day a direct debit is collected (`SC-PRIC-028`). */
12458
+ directDebitLeadDays: number;
12459
+ }
12460
+ /**
12461
+ * Calendar days a direct debit is announced before it is collected where
12462
+ * `config/saas.yaml#invoicing` names none: the SEPA rulebook's own notice.
12463
+ */
12464
+ declare const DIRECT_DEBIT_LEAD_DAYS = 14;
12465
+ /** The lead time `invoicing` names, or `DIRECT_DEBIT_LEAD_DAYS`. */
12466
+ declare function directDebitLeadDaysOf(invoicing: Pick<PlanCatalogInvoicing, 'directDebitLeadDays'>): number;
12467
+ /**
12468
+ * What an invoice records of the payment method it is collected with, or
12469
+ * `null` where there is none to collect with: the subscriber has no payment
12470
+ * method, or one that cannot be collected as an invoice announces it — a
12471
+ * direct debit without the mandate reference its announcement has to quote
12472
+ * (`SC-PRIC-028`).
12473
+ */
12474
+ declare function invoicePaymentOf(method: Pick<SubscriberPaymentMethodRecord, 'id' | 'gatewayAccount' | 'type' | 'brand' | 'last4' | 'mandateReference'> | null): SubscriptionInvoicePayment | null;
12475
+ /**
12476
+ * The invoice `input.group` makes. Its lines follow the contract's lines, so
12477
+ * the invoice reads in the order the contract does, each naming its charge and
12478
+ * its contract line (`SC-AUD-013`) and taking the contract line's title. Every
12479
+ * line carries the treatment's rate, and the tax is the adapter's, computed
12480
+ * once per rate over the lines' net amounts.
12481
+ *
12482
+ * An invoice that asks for an amount records the payment method it is
12483
+ * collected with. A direct debit is collected the lead time after the issue
12484
+ * date, which the invoice announces and falls due on; anything else falls due
12485
+ * the payment term after it (`SC-PRIC-028`, `SC-PRIC-046`). An invoice that
12486
+ * asks for nothing is collected with nothing.
12487
+ *
12488
+ * Throws where the charges contradict each other — a currency or a contract
12489
+ * line the group cannot have — which no invoice can be drawn up from, and for
12490
+ * a direct debit without its mandate reference, which `invoicePaymentOf`
12491
+ * never hands over.
12492
+ */
12493
+ declare function draftSubscriptionInvoice(input: InvoiceDraftInput): NewSubscriptionInvoice;
12494
+ /** What the tax adapter checks of an invoice before its number is drawn (`SC-PRIC-027`). */
12495
+ declare function invoiceContentDraftOf(invoice: NewSubscriptionInvoice): InvoiceContentDraft;
12496
+
12497
+ /** A recorded settings change, as far as the issuer's history needs it. */
12498
+ type IssuerHistoryStep = Pick<SettingsChangeRecord, 'previous' | 'current'>;
12499
+ /**
12500
+ * The issuer an invoice of a contract names.
12501
+ *
12502
+ * `copy` is the issuer the contract copied when it was concluded; `configured`
12503
+ * the issuer `config/saas.yaml` names on the issue date, as a contract would
12504
+ * copy it now (`contractPartiesOf`), or `null` where it names none; `history`
12505
+ * the recorded settings changes, the oldest first.
12506
+ */
12507
+ declare function invoiceIssuerOf(copy: ContractIssuerParty, configured: ContractIssuerParty | null, history: readonly IssuerHistoryStep[]): SubscriptionInvoiceIssuer;
12508
+ /**
12509
+ * The footer lines an invoice carries (`SC-PRIC-077`): those `config/saas.yaml`
12510
+ * names, where the invoice names the issuer the file names; none where it names
12511
+ * the contract's copy of another entity, whose register and account the lines
12512
+ * are not.
12513
+ */
12514
+ declare function invoiceFooterOf(issuer: SubscriptionInvoiceIssuer, configured: ContractIssuerParty | null, footer: readonly string[]): string[];
12515
+
12516
+ /** A `subscription_invoice_documents` row as either adapter reads it back. */
12517
+ interface CanonicalSubscriptionInvoiceDocumentRow {
12518
+ invoiceId: string;
12519
+ checksum: string;
12520
+ mediaType: string;
12521
+ fileName: string;
12522
+ size: unknown;
12523
+ renderedAt: Date;
12524
+ archivedAt: Date | null;
12525
+ deliveryClaimedAt: Date | null;
12526
+ deliveredAt: Date | null;
12527
+ deliveredTo: string | null;
12528
+ }
12529
+ /** A `subscription_invoice_archive` row as either adapter reads it back. */
12530
+ interface CanonicalSubscriptionInvoiceArchiveRow {
12531
+ invoiceId: string;
12532
+ checksum: string;
12533
+ mediaType: string;
12534
+ fileName: string;
12535
+ content: Uint8Array;
12536
+ archivedAt: Date;
12537
+ }
12538
+ /** Whether `value` is a checksum as the platform records one. */
12539
+ declare function isInvoiceDocumentChecksum(value: unknown): value is string;
12540
+ declare function toSubscriptionInvoiceDocumentRecord(row: CanonicalSubscriptionInvoiceDocumentRow): SubscriptionInvoiceDocumentRecord;
12541
+ declare function toArchivedInvoiceDocument(row: CanonicalSubscriptionInvoiceArchiveRow): ArchivedInvoiceDocument;
12542
+ /**
12543
+ * The triggers of `subscription_invoice_archive` that keep a document as it
12544
+ * was issued (`1.0-an-invoice-document-is-archived.postgres.sql`): one refuses
12545
+ * every update and delete of a row, the other every truncate of the table.
12546
+ */
12547
+ declare const INVOICE_ARCHIVE_TRIGGERS: readonly ["subscription_invoice_archive_is_kept", "subscription_invoice_archive_is_not_emptied"];
12548
+ /**
12549
+ * Why the database archive would let a document be changed, given the
12550
+ * triggers that fire on its table, or `null` where both of its own do. Shared
12551
+ * by both adapters, which read the enabled triggers from the catalogue.
12552
+ *
12553
+ * A database created from the fragments by `db push` alone, or a migration run
12554
+ * before the table existed, has none: the triggers are SQL the Prisma DSL
12555
+ * cannot express.
12556
+ */
12557
+ declare function invoiceArchiveProtectionProblem(enabledTriggers: readonly string[]): string | null;
12558
+
12559
+ /** Every status an attempt can stand in. */
12560
+ declare const INVOICE_COLLECTION_STATUSES: readonly InvoiceCollectionStatus[];
12561
+ /**
12562
+ * The statuses of an attempt that has been sent and is not settled: the
12563
+ * gateway is asked what became of it.
12564
+ */
12565
+ declare const UNSETTLED_COLLECTION_STATUSES: readonly InvoiceCollectionStatus[];
12566
+ /**
12567
+ * The statuses that keep an invoice from another attempt: one open — planned,
12568
+ * or sent and not settled — or one that succeeded. An invoice has one at most,
12569
+ * which `sql/constraints.postgres.sql` holds as well.
12570
+ */
12571
+ declare const BLOCKING_COLLECTION_STATUSES: readonly InvoiceCollectionStatus[];
12572
+ /** The attempts what follows is decided for: a failure, and a reversal that opened the invoice again. */
12573
+ declare const FOLLOWED_UP_COLLECTION_STATUSES: readonly InvoiceCollectionStatus[];
12574
+ /**
12575
+ * The statuses of an attempt whose payment a reversal can take back: one that
12576
+ * succeeded, and one that failed before its payment arrived after all, beside
12577
+ * another attempt of its invoice that was on its way or succeeded.
12578
+ */
12579
+ declare const REVERSIBLE_COLLECTION_STATUSES: readonly InvoiceCollectionStatus[];
12580
+ /** What the turn reads of an invoice's attempts before it writes the next one. */
12581
+ interface EarlierCollection {
12582
+ attempt: number;
12583
+ status: string;
12584
+ }
12585
+ /** The number of the last of `earlier`, `0` for none. */
12586
+ declare function lastCollectionOf(earlier: readonly EarlierCollection[]): number;
12587
+ /**
12588
+ * Whether the invoice's first attempt is refused: it has one already. Every
12589
+ * later attempt is planned, so a run that found the invoice due before another
12590
+ * run's attempt failed does not charge it again at once.
12591
+ */
12592
+ declare function refusesFirstAttempt(earlier: readonly EarlierCollection[]): boolean;
12593
+ /**
12594
+ * Whether a planned attempt that follows attempt `after` is refused: one of the
12595
+ * invoice's attempts is open or succeeded, or another came after `after`.
12596
+ */
12597
+ declare function refusesPlannedAttempt(earlier: readonly EarlierCollection[], after: number): boolean;
12598
+ /** Every reason a collection can fail for. */
12599
+ declare const COLLECTION_FAILURE_REASONS: readonly CollectionFailureReason[];
12600
+ /**
12601
+ * A `subscription_invoice_collections` row as either adapter reads it back.
12602
+ * `amount` is `unknown` because a Prisma row carries a `Decimal` where a
12603
+ * Drizzle row carries a numeric string.
12604
+ */
12605
+ interface CanonicalInvoiceCollectionRow {
12606
+ id: string;
12607
+ invoiceId: string;
12608
+ attempt: number;
12609
+ attemptKey: string;
12610
+ gatewayAccount: string;
12611
+ paymentMethodId: string;
12612
+ paymentMethodType: string;
12613
+ customerRef: string;
12614
+ paymentMethodRef: string;
12615
+ invoiceNumber: string;
12616
+ amount: unknown;
12617
+ currency: string;
12618
+ status: string;
12619
+ paymentRef: string | null;
12620
+ failureReason: string | null;
12621
+ failureCode: string | null;
12622
+ submittedAt: Date | null;
12623
+ heldAt: Date | null;
12624
+ resolvedAt: Date | null;
12625
+ /** A `date` column: a `Date` from Prisma, the text from Drizzle. */
12626
+ collectOn: unknown;
12627
+ announcedAt: Date | null;
12628
+ followedUpAt: Date | null;
12629
+ }
12630
+ /**
12631
+ * Reads an attempt row back as a record. An attempt that left carries the
12632
+ * moment it left and was held at, and one that did not carries neither; a
12633
+ * planned one carries its day. A row that breaks this is not one a run may act
12634
+ * on: a planned attempt without a day would never be collected, and a sent one
12635
+ * without a moment could not be asked about.
12636
+ */
12637
+ declare function toInvoiceCollectionRecord(row: CanonicalInvoiceCollectionRow): InvoiceCollectionRecord;
12638
+ /** The columns an attempt is started with, numbered `attempt`. */
12639
+ interface InvoiceCollectionColumns {
12640
+ invoiceId: string;
12641
+ attempt: number;
12642
+ attemptKey: string;
12643
+ gatewayAccount: string;
12644
+ paymentMethodId: string;
12645
+ paymentMethodType: string;
12646
+ customerRef: string;
12647
+ paymentMethodRef: string;
12648
+ invoiceNumber: string;
12649
+ /** A decimal string of two places, as an invoice's amounts are written. */
12650
+ amount: string;
12651
+ currency: string;
12652
+ status: InvoiceCollectionStatus;
12653
+ submittedAt: Date | null;
12654
+ heldAt: Date | null;
12655
+ /** The day of a planned attempt; `null` for one written as sent. */
12656
+ collectOn: string | null;
12657
+ }
12658
+ /** The columns of `attempt`, numbered `number`, written as submitted at its `at`. */
12659
+ declare function invoiceCollectionColumns(attempt: NewInvoiceCollection, number: number): InvoiceCollectionColumns;
12660
+ /** The columns of `plan`, numbered `number`, written as planned for its day. */
12661
+ declare function plannedCollectionColumns(plan: PlannedInvoiceCollection, number: number): InvoiceCollectionColumns;
12662
+ /** The columns an outcome sets: `PENDING` leaves the attempt open, the others settle it at `at`. */
12663
+ declare function collectionOutcomeColumns(outcome: CollectionOutcome, at: Date): {
12664
+ status: InvoiceCollectionStatus;
12665
+ paymentRef: string | null;
12666
+ failureReason: CollectionFailureReason | null;
12667
+ failureCode: string | null;
12668
+ resolvedAt: Date | null;
12669
+ };
12670
+
12671
+ /** How many days after a failure the same payment method is charged once more. */
12672
+ declare const COLLECTION_RETRY_AFTER_DAYS = 7;
12673
+ /**
12674
+ * Whether the payment method a failed attempt charged is charged once more:
12675
+ * its reason can pass, and no other attempt of the invoice failed with that
12676
+ * payment method. A replacement gets its own second try.
12677
+ */
12678
+ declare function isChargedAgain(failed: InvoiceCollectionRecord, attempts: readonly InvoiceCollectionRecord[]): boolean;
12679
+ /** The day the same payment method is charged again after a failure on `failedOn`. */
12680
+ declare function chargedAgainOn(failedOn: CalendarDay): CalendarDay;
12681
+ /**
12682
+ * The day a direct debit announced on `announcedOn` is collected: the lead
12683
+ * time after its announcement, and never before `earliest`.
12684
+ */
12685
+ declare function announcedCollectionDay(earliest: CalendarDay, announcedOn: CalendarDay, leadDays: number): CalendarDay;
12686
+
12687
+ /** A recorded `collection-failed` notice, `id` being its record's. */
12688
+ declare function toCollectionFailedNotice(content: unknown, id: string): CollectionFailedNotice;
12689
+ /** A recorded `collection-announced` notice, `id` being its record's. */
12690
+ declare function toCollectionAnnouncedNotice(content: unknown, id: string): CollectionAnnouncedNotice;
12691
+ /** A recorded `collection-reversed` notice, `id` being its record's. */
12692
+ declare function toCollectionReversedNotice(content: unknown, id: string): CollectionReversedNotice;
12693
+
12694
+ /**
12695
+ * What an entry against an invoice is: a payment that settles it, a reversal
12696
+ * that opens it again by part of what a payment settled, and the same part
12697
+ * settled again where the gateway gave the reversal back.
12698
+ */
12699
+ type InvoiceSettlementKind = 'PAYMENT' | 'REVERSAL' | 'REINSTATEMENT';
12700
+ declare const INVOICE_SETTLEMENT_KINDS: readonly InvoiceSettlementKind[];
12701
+ /**
12702
+ * The settlements that add back to what an invoice owes rather than take off
12703
+ * it; an adapter that sums settlements in SQL passes it as a parameter, so the
12704
+ * sign is decided here alone.
12705
+ */
12706
+ declare const REOPENING_SETTLEMENT_KINDS: readonly InvoiceSettlementKind[];
12707
+ declare const SUBSCRIBER_CREDIT_ENTRY_KINDS: readonly SubscriberCreditEntryKind[];
12708
+ declare const SUBSCRIBER_REFUND_STATUSES: readonly SubscriberRefundStatus[];
12709
+ /** The statuses of a refund that gave its money back to the operator. */
12710
+ declare const ENDED_REFUND_STATUSES: readonly SubscriberRefundStatus[];
12711
+ /** Whether a refund in `status` gave its money back. */
12712
+ declare function isEndedRefund(status: SubscriberRefundStatus): boolean;
12713
+ /** A `subscriber_payments` row as either adapter reads it back. */
12714
+ interface CanonicalSubscriberPaymentRow {
12715
+ id: string;
12716
+ subscriberId: string;
12717
+ tenantId: string;
12718
+ invoiceId: string;
12719
+ collectionId: string;
12720
+ gatewayAccount: string;
12721
+ provider: string;
12722
+ gatewayRef: string;
12723
+ amount: unknown;
12724
+ currency: string;
12725
+ recordedAt: Date;
12726
+ }
12727
+ declare function toSubscriberPaymentRecord(row: CanonicalSubscriberPaymentRow): SubscriberPaymentRecord;
12728
+ /** The columns a payment is written with, for the subscriber its invoice names. */
12729
+ declare function subscriberPaymentColumns(payment: NewSubscriberPayment, invoice: {
12730
+ subscriberId: string;
12731
+ tenantId: string;
12732
+ }): Omit<CanonicalSubscriberPaymentRow, 'id' | 'amount'> & {
12733
+ amount: string;
12734
+ };
12735
+ /** A `subscription_invoice_settlements` row, as far as what an invoice owes reads it. */
12736
+ interface CanonicalInvoiceSettlementRow {
12737
+ id: string;
12738
+ kind: string;
12739
+ amount: unknown;
12740
+ }
12741
+ /**
12742
+ * The amount a settlement row takes off what its invoice owes: positive for a
12743
+ * payment and a reinstatement, negative for a reversal, which opens the invoice
12744
+ * again. Its kind is checked, so a kind a later release writes stops the read
12745
+ * rather than being counted as a payment.
12746
+ */
12747
+ declare function settledAmountOf(row: CanonicalInvoiceSettlementRow): number;
12748
+ /** A `subscriber_credits` row as either adapter reads it back. */
12749
+ interface CanonicalSubscriberCreditRow {
12750
+ id: string;
12751
+ subscriberId: string;
12752
+ tenantId: string;
12753
+ amount: unknown;
12754
+ currency: string;
12755
+ originPaymentId: string | null;
12756
+ originInvoiceId: string | null;
12757
+ originReversalId: string | null;
12758
+ createdAt: Date;
12759
+ }
12760
+ /**
12761
+ * Reads a credit back. It comes from exactly one place — a payment, an invoice
12762
+ * or a reversal given back — which the database holds as well; a row that
12763
+ * names several or none cannot be paid out against anything.
12764
+ */
12765
+ declare function toSubscriberCreditRecord(row: CanonicalSubscriberCreditRow): SubscriberCreditRecord;
12766
+ /** A `subscriber_credit_entries` row as either adapter reads it back. */
12767
+ interface CanonicalSubscriberCreditEntryRow {
12768
+ id: string;
12769
+ creditId: string;
12770
+ kind: string;
12771
+ amount: unknown;
12772
+ refundId: string | null;
12773
+ reversalId: string | null;
12774
+ reference: string | null;
12775
+ /** A `date` column: a `Date` from Prisma, the text from Drizzle. */
12776
+ paidOn: unknown;
12777
+ recordedBy: string | null;
12778
+ note: string | null;
12779
+ recordedAt: Date;
12780
+ }
12781
+ declare function toSubscriberCreditEntryRecord(row: CanonicalSubscriberCreditEntryRow): SubscriberCreditEntryRecord;
12782
+ /**
12783
+ * The columns of an entry a refund writes against one credit, carrying the
12784
+ * refund's own reference at the gateway, which the operator finds it under.
12785
+ */
12786
+ declare function refundEntryColumns(creditId: string, refund: {
12787
+ id: string;
12788
+ gatewayRef: string;
12789
+ }, kind: 'REFUND' | 'REFUND_FAILED', amount: number, at: Date): Omit<CanonicalSubscriberCreditEntryRow, 'id' | 'amount' | 'paidOn'> & {
12790
+ amount: string;
12791
+ paidOn: null;
12792
+ };
12793
+ /** The columns of the entry a payout writes against its credit. */
12794
+ declare function payoutEntryColumns(payout: NewSubscriberPayout): Omit<CanonicalSubscriberCreditEntryRow, 'id' | 'amount' | 'paidOn'> & {
12795
+ amount: string;
12796
+ paidOn: string;
12797
+ };
12798
+ /** A `subscriber_refunds` row as either adapter reads it back. */
12799
+ interface CanonicalSubscriberRefundRow {
12800
+ id: string;
12801
+ subscriberId: string;
12802
+ paymentId: string;
12803
+ gatewayAccount: string;
12804
+ gatewayRef: string;
12805
+ amount: unknown;
12806
+ currency: string;
12807
+ status: string;
12808
+ recordedAt: Date;
12809
+ endedAt: Date | null;
12810
+ }
12811
+ declare function toSubscriberRefundRecord(row: CanonicalSubscriberRefundRow): SubscriberRefundRecord;
12812
+ /** The columns a refund is first written with, against the payment it pays back. */
12813
+ declare function subscriberRefundColumns(refund: ReportedSubscriberRefund, payment: {
12814
+ id: string;
12815
+ subscriberId: string;
12816
+ }): Omit<CanonicalSubscriberRefundRow, 'id' | 'amount'> & {
12817
+ amount: string;
12818
+ };
12819
+ /**
12820
+ * The columns of an entry a reversal writes against one credit: what it takes
12821
+ * of it, or gives back, carrying the reversal's own reference at the gateway.
12822
+ */
12823
+ declare function reversalEntryColumns(creditId: string, reversal: {
12824
+ id: string;
12825
+ gatewayRef: string;
12826
+ }, kind: 'REVERSAL' | 'REVERSAL_TAKEN_BACK', amount: number, at: Date): Omit<CanonicalSubscriberCreditEntryRow, 'id' | 'amount' | 'paidOn'> & {
12827
+ amount: string;
12828
+ paidOn: null;
12829
+ };
12830
+ /** A `subscriber_reversals` row as either adapter reads it back. */
12831
+ interface CanonicalSubscriberReversalRow {
12832
+ id: string;
12833
+ subscriberId: string;
12834
+ tenantId: string;
12835
+ paymentId: string;
12836
+ gatewayAccount: string;
12837
+ gatewayRef: string;
12838
+ amount: unknown;
12839
+ currency: string;
12840
+ fromCredit: unknown;
12841
+ reinstated: unknown;
12842
+ recordedAt: Date;
12843
+ reinstatedAt: Date | null;
12844
+ }
12845
+ /**
12846
+ * Reads a reversal back. What it took from the credit and what the gateway
12847
+ * gave back are parts of what it withdrew, and a give-back carries when; a row
12848
+ * that says otherwise stops the read.
12849
+ */
12850
+ declare function toSubscriberReversalRecord(row: CanonicalSubscriberReversalRow): SubscriberReversalRecord;
12851
+ /**
12852
+ * The columns a reversal is first written with, against the payment it takes
12853
+ * back: nothing withdrawn or given back yet, which the entries it writes next
12854
+ * raise.
12855
+ */
12856
+ declare function subscriberReversalColumns(reversal: ReportedSubscriberReversal, payment: {
12857
+ id: string;
12858
+ subscriberId: string;
12859
+ tenantId: string;
12860
+ }): Omit<CanonicalSubscriberReversalRow, 'id' | 'amount' | 'fromCredit' | 'reinstated'> & {
12861
+ amount: string;
12862
+ fromCredit: string;
12863
+ reinstated: string;
12864
+ };
12865
+
12866
+ /**
12867
+ * What an invoice of `gross` still owes after the entries `settled` against
12868
+ * it, each signed as `settledAmountOf` reads it — a reversal that opened the
12869
+ * invoice again counts against what was settled; negative where it owes the
12870
+ * subscriber, as an invoice whose total is negative does.
12871
+ */
12872
+ declare function owedOn(gross: number, settled: readonly number[]): number;
12873
+ /**
12874
+ * How a payment of `amount` divides against an invoice that still owes
12875
+ * `owed`: it settles what is owed, and what it brought beyond that is a credit.
12876
+ * An invoice that owes nothing, or owes the subscriber, is settled by nothing.
12877
+ */
12878
+ declare function paymentSettlement(amount: number, owed: number): {
12879
+ settles: number;
12880
+ credits: number;
12881
+ };
12882
+ /**
12883
+ * The entries that give back what an earlier entry paid out of a credit; an
12884
+ * adapter that sums entries in SQL passes it as a parameter, so the sign is
12885
+ * decided here alone.
12886
+ */
12887
+ declare const GIVING_BACK_CREDIT_ENTRY_KINDS: readonly SubscriberCreditEntryKind[];
12888
+ /**
12889
+ * What a credit of `amount` still owes after `entries`. Never below `0`: an
12890
+ * entry that would take it there is not written.
12891
+ */
12892
+ declare function openOfCredit(amount: number, entries: readonly {
12893
+ kind: SubscriberCreditEntryKind;
12894
+ amount: number;
12895
+ }[]): number;
12896
+ /** A credit as a refund is divided across it. */
12897
+ interface OpenCredit {
12898
+ id: string;
12899
+ origin: SubscriberCreditOrigin;
12900
+ createdAt: Date;
12901
+ /** What it still owes, from `openOfCredit`. */
12902
+ open: number;
12903
+ }
12904
+ /**
12905
+ * How a refund of `amount` that pays back payment `paymentId` divides across
12906
+ * the subscriber's open credits: the credit that payment left first — the
12907
+ * refund pays back what the subscriber overpaid with it —, then the oldest.
12908
+ * What no open credit takes matches nothing, and is the operator's to
12909
+ * reconcile.
12910
+ */
12911
+ declare function refundParts(amount: number, paymentId: string, credits: readonly OpenCredit[]): {
12912
+ parts: CreditPart[];
12913
+ unmatched: number;
12914
+ };
12915
+ /** The credit a payment left, as a reversal of that payment reads it. */
12916
+ interface ReversibleCredit {
12917
+ creditId: string;
12918
+ /** What of the credit no reversal of the payment took yet, open or paid out. */
12919
+ left: number;
12920
+ /** What of the credit is still owed to the subscriber, from `openOfCredit`. */
12921
+ open: number;
12922
+ }
12923
+ /**
12924
+ * A credit that another payment collected for an invoice the reversed payment
12925
+ * settles left, as the reversal reads it.
12926
+ */
12927
+ interface CoveringCredit {
12928
+ creditId: string;
12929
+ /** What of the credit is still owed to the subscriber, from `openOfCredit`. */
12930
+ open: number;
12931
+ }
12932
+ /** An invoice a payment settles, as a reversal of that payment reads it. */
12933
+ interface ReversibleInvoice {
12934
+ invoiceId: string;
12935
+ /** What the payment still settles there: its settlements less what reversals took back. */
12936
+ left: number;
12937
+ }
12938
+ /** How a withdrawn amount divides across what its payment brought. */
12939
+ interface WithdrawalParts {
12940
+ /** What it takes of the credit, open or paid out alike. */
12941
+ fromCredit: number;
12942
+ /** What it takes of the credit that is still open; `null` where nothing. */
12943
+ credit: CreditPart | null;
12944
+ /** What it takes of the covering credits instead of opening their invoices again, in the order given. */
12945
+ covering: CreditPart[];
12946
+ /** The invoices it opens again, in the order given, each by no more than the payment settles there. */
12947
+ invoices: InvoicePart[];
12948
+ /**
12949
+ * What meets the part of the credit already paid out, and what goes beyond
12950
+ * everything the payment brought: the operator's to reconcile.
12951
+ */
12952
+ unmatched: number;
12953
+ }
12954
+ /**
12955
+ * How `amount`, newly withdrawn by a reversal of a payment, divides across what
12956
+ * the payment brought: the credit it left first, so the operator is not left
12957
+ * refunding what is owed again — its open part shrinks it, its part already
12958
+ * paid out matches nothing —, then the invoices it settles, in the order given,
12959
+ * the oldest first. What the reversal would open again of them is covered
12960
+ * first by `covering`, the open credits other payments collected for those
12961
+ * invoices left, in the order given: that money was collected for the same
12962
+ * invoices, so it settles them rather than waiting to be paid out while they
12963
+ * are collected again. Whatever exceeds the credit and the invoices matches
12964
+ * nothing; no covering credit takes it.
12965
+ */
12966
+ declare function withdrawalParts(amount: number, credit: ReversibleCredit | null, invoices: readonly ReversibleInvoice[], covering?: readonly CoveringCredit[]): WithdrawalParts;
12967
+ /** What a reversal took back that an amount the gateway gives back can return. */
12968
+ interface ReinstatableParts {
12969
+ /** What of the reversal's unmatched amount is not covered by an earlier give-back yet. */
12970
+ unmatched: number;
12971
+ /** What it took of each credit and has not given back yet. */
12972
+ credits: readonly {
12973
+ creditId: string;
12974
+ left: number;
12975
+ }[];
12976
+ /**
12977
+ * What it opened again of each invoice and has not settled again yet, the
12978
+ * oldest first, with what the invoice owes now.
12979
+ */
12980
+ invoices: readonly {
12981
+ invoiceId: string;
12982
+ left: number;
12983
+ owed: number;
12984
+ }[];
12985
+ }
12986
+ /** How an amount the gateway gives back divides across what its reversal took. */
12987
+ interface ReinstatementParts {
12988
+ /** What covers the reversal's unmatched amount. */
12989
+ covered: number;
12990
+ /** What each credit is owed again. */
12991
+ credits: CreditPart[];
12992
+ /** What settles each invoice again, as far as it still owes. */
12993
+ invoices: InvoicePart[];
12994
+ /** What the invoices no longer owe — the subscriber paid them meanwhile —, as a credit. */
12995
+ credited: number;
12996
+ /** What goes beyond everything the reversal took, which nothing takes. */
12997
+ beyond: number;
12998
+ }
12999
+ /**
13000
+ * How `amount`, newly given back by the gateway for a reversal, takes it back
13001
+ * part for part, in the reverse of how it was withdrawn: the unmatched part
13002
+ * first — such as the refund the subscriber received before the dispute, which
13003
+ * the gateway returns where the dispute is lost —, then what it took of the
13004
+ * credits, then what it opened of the invoices, settling each again as far as
13005
+ * it still owes. What an invoice no longer owes becomes a credit.
13006
+ */
13007
+ declare function reinstatementParts(amount: number, took: ReinstatableParts): ReinstatementParts;
13008
+ /**
13009
+ * What each invoice nets from `entries` — settlements signed as
13010
+ * `settledAmountOf` reads them —, in whole cents, in the order the invoices
13011
+ * first appear. Read over a payment's settlements, it is what the payment still
13012
+ * settles on each; over a reversal's, the negative of what it opened and has
13013
+ * not settled again.
13014
+ */
13015
+ declare function netByInvoice(entries: readonly InvoicePart[]): InvoicePart[];
13016
+ /**
13017
+ * What `entries` paid out of each credit, net of what they gave back, in whole
13018
+ * cents, in the order the credits first appear. Read over a reversal's
13019
+ * entries, it is what the reversal took of each credit and has not given back.
13020
+ */
13021
+ declare function paidOutByCredit(entries: readonly {
13022
+ creditId: string;
13023
+ kind: SubscriberCreditEntryKind;
13024
+ amount: number;
13025
+ }[]): CreditPart[];
13026
+ /**
13027
+ * What other reversals took of one credit to cover what they would have opened
13028
+ * of its invoice (`SC-PRIC-087`) and still hold: the credit's `entries` of
13029
+ * reversals not in `own`, net of what was given back, in whole cents, in the
13030
+ * order the reversals first appear. Where the credit's own payment is reversed
13031
+ * as well, these covers are lifted first (`SC-PRIC-088`).
13032
+ */
13033
+ declare function coversOf(entries: readonly {
13034
+ reversalId: string | null;
13035
+ kind: SubscriberCreditEntryKind;
13036
+ amount: number;
13037
+ }[], own: ReadonlySet<string>): {
13038
+ reversalId: string;
13039
+ amount: number;
13040
+ }[];
13041
+ /**
13042
+ * The covers a withdrawal lifts: what it takes of its payment's credit beyond
13043
+ * the open part — `parts.fromCredit` less `parts.credit` — reaches the covers
13044
+ * that credit gave other reversals (`coversOf`) before it counts as paid out,
13045
+ * in the order given. Each lifted cover opens its reversal's invoice again;
13046
+ * what it reaches beyond them stays unmatched (`SC-PRIC-088`).
13047
+ */
13048
+ declare function coversLifted(parts: Pick<WithdrawalParts, 'fromCredit' | 'credit' | 'unmatched'>, covers: readonly {
13049
+ reversalId: string;
13050
+ amount: number;
13051
+ }[]): {
13052
+ lifted: {
13053
+ reversalId: string;
13054
+ amount: number;
13055
+ }[];
13056
+ unmatched: number;
13057
+ };
13058
+ /**
13059
+ * `parts` in the order a reversal of payment `paymentId` takes credits: the
13060
+ * credit that payment left first, then the covering ones, the oldest first —
13061
+ * so what the gateway gives back returns to them in that order, whatever order
13062
+ * a database reads their entries in.
13063
+ */
13064
+ declare function inWithdrawalOrder(parts: readonly CreditPart[], credits: readonly SubscriberCreditRecord[], paymentId: string): CreditPart[];
13065
+ /**
13066
+ * The ids of `cases`, in the order given — the order they were opened —, that
13067
+ * the first `covered` of what the gateway gave back covers in full.
13068
+ */
13069
+ declare function casesCovered(cases: readonly {
13070
+ id: string;
13071
+ amount: number;
13072
+ }[], covered: number): string[];
13073
+
13074
+ declare const RECONCILIATION_CASE_KINDS: readonly ReconciliationCaseKind[];
13075
+ /** A `subscriber_reconciliation_cases` row as either adapter reads it back. */
13076
+ interface CanonicalReconciliationCaseRow {
13077
+ id: string;
13078
+ subscriberId: string;
13079
+ tenantId: string;
13080
+ kind: string;
13081
+ amount: unknown;
13082
+ currency: string;
13083
+ paymentId: string;
13084
+ refundId: string | null;
13085
+ reversalId: string | null;
13086
+ gatewayAccount: string;
13087
+ gatewayRef: string;
13088
+ recordedAt: Date;
13089
+ closedAt: Date | null;
13090
+ closedBy: string | null;
13091
+ note: string | null;
13092
+ }
13093
+ /**
13094
+ * Reads a case back. It is about exactly what its kind says — a refund or a
13095
+ * reversal —, and a closed case carries why it was closed; a row that says
13096
+ * otherwise stops the read rather than reaching the operator's list as
13097
+ * something it is not.
13098
+ */
13099
+ declare function toSubscriberReconciliationCaseRecord(row: CanonicalReconciliationCaseRow): SubscriberReconciliationCaseRecord;
13100
+ /** What a case is opened about: a refund or a reversal, with the payment and its subscriber. */
13101
+ interface NewReconciliationCase {
13102
+ kind: ReconciliationCaseKind;
13103
+ amount: number;
13104
+ currency: string;
13105
+ payment: {
13106
+ id: string;
13107
+ subscriberId: string;
13108
+ tenantId: string;
13109
+ };
13110
+ /** The refund's id, for a `REFUND_UNMATCHED`, or the reversal's. */
13111
+ about: {
13112
+ id: string;
13113
+ gatewayAccount: string;
13114
+ gatewayRef: string;
13115
+ };
13116
+ at: Date;
13117
+ }
13118
+ /** The columns a case is opened with. */
13119
+ declare function reconciliationCaseColumns(opened: NewReconciliationCase): Omit<CanonicalReconciliationCaseRow, 'id' | 'amount'> & {
13120
+ amount: string;
13121
+ };
13122
+ /** Why SaaSiCat closes a case of a refund that failed or was canceled. */
13123
+ declare const CASE_CLOSED_REFUND_ENDED = "The refund failed or was canceled, and its money came back.";
13124
+ /** Why SaaSiCat closes a case of a reversal the gateway gave back. */
13125
+ declare const CASE_CLOSED_REVERSAL_GIVEN_BACK = "The gateway gave the reversal back, and with it what matched nothing.";
13126
+
13127
+ /** Which column of which row a value came from, for the error that names it. */
13128
+ interface ColumnWhere {
13129
+ table: string;
13130
+ column: string;
13131
+ id: string;
13132
+ }
13133
+
13134
+ /** The amount a `numeric` column holds; throws, naming the column, for anything else. */
13135
+ declare function columnAmountOf(value: unknown, where: ColumnWhere): number;
13136
+
13137
+ /** The VAT category of EN 16931 (UNTDID 5305) a line and a breakdown name. */
13138
+ type VatCategory = 'S' | 'E' | 'AE' | 'O';
13139
+ /** The category EN 16931 names for a treatment an adapter decides. */
13140
+ declare function vatCategoryOf(kind: TaxTreatmentKind): VatCategory;
13141
+ /** Whether `text` can stand in an XML document as it is. */
13142
+ declare function holdsOnlyXmlCharacters(text: string): boolean;
13143
+ /**
13144
+ * `text` as an e-invoice's XML states it, which is what every XML parser reads
13145
+ * back from it: a character XML cannot hold becomes `?`, as the page shows a
13146
+ * character its font has no glyph for (`SC-PRIC-078`), and a carriage return
13147
+ * is the line feed XML 1.0 hands over in its place (§ 2.11). The renderer
13148
+ * writes this, and the adapter's check compares the record through it.
13149
+ */
13150
+ declare function asXmlReadsIt(text: string): string;
13151
+
9809
13152
  /** A `subscribers` row as either adapter reads it back. */
9810
13153
  interface CanonicalSubscriberRow {
9811
13154
  id: string;
@@ -10182,7 +13525,7 @@ type ErrorMessageParams = Record<string, unknown>;
10182
13525
  /**
10183
13526
  * Replaces `{name}` with `params.name`. An unknown placeholder is left
10184
13527
  * verbatim, so a missing value is visible in the UI rather than silently
10185
- * vanishing.
13528
+ * vanishing — and so is a value without a text of its own.
10186
13529
  */
10187
13530
  declare function formatErrorMessage(template: string, params?: ErrorMessageParams): string;
10188
13531
  /**
@@ -10219,4 +13562,4 @@ declare function resolveErrorMessage(body: ResolvableErrorBody, overrides?: Part
10219
13562
 
10220
13563
  declare const ERROR_MESSAGES_DE: Record<PlatformErrorCode, string>;
10221
13564
 
10222
- export { ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES, AUTH_ERROR_CODES, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminAccountEntry, type AdminAccountHolder, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminResourcesPort, type AdminSubscriberAccount, type AdminSubscriberAttention, type AdminSubscriberCorrected, type AdminSubscriberHistoryEntry, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminTenantSubscriber, type AdminUserListFilter, type AdminUserListRow, type AdminVatIdCheckOutcome, type AppliedSettingsPort, type AppliedSettingsRecord, type AppliedSettingsValues, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditActor, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BUNDLE_PRICE_LOOKUP_LIMIT, BUNDLE_VERSION_RETIREMENT_CAPABILITY, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRetirementAnnounced, type BundleRetirementPreview, type BundleRetirementReachedRow, type BundleRetirementSkipReason, type BundleRetirementSkippedRow, type BundleRetirementSwitchResult, type BundleRetirementSwitchTerms, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionOfferView, type BundleVersionOfferedNotice, type BundleVersionRetiredNotice, type BundleVersionRetirementRecord, type BundleVersionRetirementReminder, type BundleVersionRetirementRepository, type BundleVersionRetirementView, type BundleVersionRow, type BundleVersionSide, type BundleVersionSwitchResult, CATALOGUE_KEYS, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, CUSTOM_LIMITS_KEYS, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalBundleVersionRetirementRow, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalMaintenanceWindowRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalRunningContractRow, type CanonicalSubscriberChargeRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberRow, type CanonicalSubscriberTaxOriginChangeRow, type CanonicalSubscriberVatIdCheckRow, type CanonicalSubscriptionBundleRow, type CanonicalSubscriptionNoticeRow, type CanonicalVersionRetirementRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type CatalogVersionKind, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferSelection, type CheckoutOfferSelectionUpdate, type CheckoutOfferStatus, type CleanupResult, type CliUserRow, type ComponentKey, type ConcurrencyGate, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ConfirmedPaymentMethod, type ContractErrorCode, type ContractIssuerParty, type ContractLineItemKind, type ContractLineItemRecord, type ContractSubscriberParty, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriberData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type CustomLimits, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EffectiveLimitsSnapshot, type EmailPort, type ErrorMessageParams, FEATURE_NOT_LICENSED, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FinalActivationResult, type FirstTimeCustomerCheck, ForeignPaymentMethodReferenceError, type HeldVatId, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type IssuerCorrectionFault, type IssuerIdentityChange, type KpiCardDef, type KpiDisplayHint, LEGAL_IDENTITY_FIELDS, type LegalIdentity, type LegalIdentityField, MAINTENANCE_CAPABILITY, MAINTENANCE_ERROR_CODES, MAINTENANCE_MESSAGE_MAX_LENGTH, MAINTENANCE_STATE_MAX_AGE_SECONDS, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type MaintenanceErrorCode, type MaintenanceLockView, type MaintenanceNotificationPort, type MaintenanceOverview, type MaintenanceStatusView, type MaintenanceUnlockView, type MaintenanceWindowChanges, type MaintenanceWindowEvent, type MaintenanceWindowPort, type MaintenanceWindowRecord, type MaintenanceWindowStage, type MaintenanceWindowStatus, type MaintenanceWindowView, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, NO_SCHEDULED_CHANGE, type NewBundleVersionRetirement, type NewContractLineItemData, type NewMaintenanceWindow, type NewSettingsChange, type NewSubscriberCharge, type NewSubscriberDetails, type NewSubscriptionContractData, type NewVersionRetirement, type NotToldReasons, type NoticeToRecord, OPTIONAL_CANONICAL_MODELS, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, type OptionalBundleMember, type OptionalCanonicalModel, type OrderlyRetirementSettings, PASSWORD_RESET_TTL_MINUTES, PAYMENT_ERROR_CODES, PAYMENT_METHOD_TYPES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PartyAddress, type PasswordHasher, type PasswordResetCliResult, PaymentCallbackRejectedError, type PaymentErrorCode, type PaymentEventClaim, type PaymentEventLog, type PaymentGateway, type PaymentGatewayCallback, type PaymentGatewayEvent, type PaymentMethodHolder, type PaymentMethodSetupSession, type PaymentMethodSetupSubject, type PaymentMethodType, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, PersistenceRefusal, type PersistenceRefusalReason, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogIssuer, type PlanCatalogIssuerCorrection, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogNotifications, type PlanCatalogPaymentAccount, type PlanCatalogPayments, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, type PlanCatalogSettings, type PlanCatalogSubscribers, type PlanCatalogTax, type PlanCatalogTenantBilling, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformJobActor, type PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeHoldRecord, type PromoCodeHoldRepository, type PromoCodeHoldTaken, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionI18n, type PromotionI18nFields, type PromotionOnPrice, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicNewPaymentMethods, type PublicSignupPlan, type PublishBundleVersionData, type PublishBundleVersionMeta, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, RETIREMENT_REMINDER_LEAD_DAYS, type ReadCustomLimits, type ReassignTenantAdminCliResult, type RecommendablePlan, type RecordSubscriberPaymentMethodData, type RecordSubscriberPaymentMethodOutcome, type RecordSubscriberPaymentMethodResult, type RecordedVatIdCheck, type RedeemPromoInTransactionCallback, type RegistrationActivation, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationBillingDetails, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type RequiredCapabilities, type ResolvableErrorBody, type ResumeRegistrationInput, type ResumeRegistrationResult, type RetiredBundleVersionRef, type RetiredVersionRef, type RetirementAnnounced, type RetirementBlocker, type RetirementMoveRun, type RetirementPreview, type RetirementPricedSide, type RetirementProgress, type RetirementReachedRow, type RetirementSide, type RetirementSkipReason, type RetirementSkippedRow, type RetirementSwitchResult, type RetirementSwitchTerms, type ReviewCatalogEntryData, type RlsBypassPort, type RunningContractIssuer, type RunningContractIssuers, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ACCOUNT_CAPABILITY, SUBSCRIBER_ATTENTION_CAPABILITY, SUBSCRIBER_ATTENTION_PAGE_SIZE, SUBSCRIBER_CORRECTION_CAPABILITY, SUBSCRIBER_ERROR_CODES, SUBSCRIBER_INVOICE_ADDRESS_FIELDS, SUBSCRIBER_STANDING_CAPABILITY, SUBSCRIBER_TAX_ORIGIN_FIELDS, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePayments, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledChangeColumns, type ScheduledPlanChangeInput, type SecretSealer, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SelfServiceBlockedPlans, type SetCatalogEntryReviewData, type SettingsChangeFilter, type SettingsChangeRecord, type SettingsDifference, type SettingsErrorCode, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartPaymentMethodSetupInput, type StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type SubscriberBusinessStatusData, type SubscriberBusinessStatusResult, type SubscriberCharge, type SubscriberChargeOrigin, type SubscriberChargeRecord, type SubscriberChargeSource, type SubscriberContact, type SubscriberContactChange, type SubscriberCorrectionData, type SubscriberCorrectionRecord, type SubscriberCorrectionResult, type SubscriberDetails, type SubscriberErrorCode, type SubscriberIdentityCorrection, type SubscriberIdentityDelta, type SubscriberIdentityValues, type SubscriberInvoiceAddressField, type SubscriberLedgerRepository, type SubscriberPaymentMethodRecord, type SubscriberPaymentMethodReference, type SubscriberPaymentMethodRepository, type SubscriberPaymentMethodSetupData, type SubscriberPaymentMethodSetupMatch, type SubscriberPaymentMethodStatus, type SubscriberReadiness, type SubscriberRecord, type SubscriberRepository, type SubscriberTaxOrigin, type SubscriberTaxOriginChangeRecord, type SubscriberTaxOriginField, type SubscriberTaxOriginValues, type SubscriberTaxStatus, type SubscriberVatIdCheckRecord, type SubscriberVatIdCheckResult, type SubscriberWithCurrentCheck, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractParties, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionNotice, type SubscriptionNoticeDelivery, type SubscriptionNoticeKey, type SubscriptionNoticeKind, type SubscriptionNoticePort, type SubscriptionNoticeRecord, type SubscriptionNoticeRepository, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SupersedeSubscriptionContractData, type SyncDiscoveryResult, TAX_ERROR_CODES, TAX_TREATMENT_KINDS, type TaxAdapter, type TaxAdapterFactory, type TaxAdapterIdentity, type TaxDecision, type TaxDecisionRequest, type TaxErrorCode, type TaxIssuer, type TaxOriginWrite, type TaxTreatment, type TaxTreatmentKind, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionUsage, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, VERSION_RETIREMENT_CAPABILITY, type VatIdCheck, type VatIdCheckOutcome, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionOffer, type VersionOfferClass, type VersionOfferFields, type VersionOfferSide, type VersionOfferView, type VersionOfferedNotice, type VersionRetiredNotice, type VersionRetirementRecord, type VersionRetirementReminder, type VersionRetirementRepository, type VersionRetirementView, type VersionSale, type VersionSaleDates, type VersionSaleKind, type VersionSwitchResult, type VersionWindow, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleKeyTaken, bundleStemDefaults, canonicalJson, canonicalVatId, catalogDraftExists, catalogVersionAlreadyPublished, catalogVersionGone, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, classifyVersionOffer, collectUnsatisfiedRequires, computeIncludedVat, concurrencyGate, concurrencyGateOf, contractPartiesOf, coverageExcludingSelf, customLimitsReader, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, grossFromNet, identityCorrectionDelta, isBundleRedundant, isForeignPaymentMethodReferenceError, isMaintenanceAnnouncementLapsed, isMaintenanceOverrun, isPaymentCallbackRejectedError, isPersistenceRefusal, isPlatformUserExistsError, isVersionActiveAt, isVersionEditable, issuerIdentityOf, keepOneRecommended, keepsVatIdCheck, maintenanceRetryAfterSeconds, maintenanceStatusOf, maintenanceWindowStatusOf, maintenanceWindowViewOf, marketingProjectionTaken, membersLeftOut, missingRequiresFor, movedIdentityFields, netFromGross, noActivePlanVersion, parseZonedInstant, percentOf, pickActivePromo, planCatalogSettingsOf, planKeyTaken, planNotInCatalog, previousUtcDay, promoCodeTaken, promoStatus, promotionOnPrice, prorate, readCustomLimits, readQuotaRecord, readQuotaValue, recordedIssuerIdentity, refuseForeignPaymentMethodReference, resolveBundleAvailability, resolveErrorMessage, retirementCostsTheSubscription, retirementReminderDueAt, retirementReminderIsDue, retirementSwitchTerms, roundToCents, sameLegalIdentity, scheduledChangeAfterWrite, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberChargeColumns, subscriberFromRegistration, subscriberPaymentMethodColumns, subscriptionBundleAlreadyCancelled, subscriptionBundleGone, subscriptionContractGone, subscriptionGone, sumToCents, taxOriginOf, taxOriginWrite, taxTreatmentToJson, toBundleStemRow, toBundleVersionRetirementRecord, toCents, toContractLineItemRecord, toDecimalString, toMaintenanceWindowRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberChargeRecord, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriberTaxOriginChangeRecord, toSubscriberVatIdCheckRecord, toSubscriptionBundleRecord, toSubscriptionContractRecord, toSubscriptionNoticeRecord, toTaxOriginValues, toTaxTreatment, toVersionRetirementRecord, vatIdCheckFromStore, versionOnSale, versionOnSaleOrNext, versionSale };
13565
+ export { ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES, AUTH_ERROR_CODES, type AbandonPaidOutcome, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminAccountEntry, type AdminAccountHolder, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminReconciliationCase, type AdminReconciliationCases, type AdminReconciliationClose, type AdminResourcesPort, type AdminSubscriberAccount, type AdminSubscriberAttention, type AdminSubscriberCorrected, type AdminSubscriberCredit, type AdminSubscriberCreditEntry, type AdminSubscriberCredits, type AdminSubscriberHistoryEntry, type AdminSubscriberPayout, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantInvoice, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantPayments, type AdminTenantStateResult, type AdminTenantSubscriber, type AdminUserListFilter, type AdminUserListRow, type AdminVatIdCheckOutcome, type AppliedSettingsPort, type AppliedSettingsRecord, type AppliedSettingsValues, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type ArchivedInvoiceDocument, type AuditActionDef, type AuditActor, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BLOCKING_COLLECTION_STATUSES, BUNDLE_PRICE_LOOKUP_LIMIT, BUNDLE_VERSION_RETIREMENT_CAPABILITY, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRetirementAnnounced, type BundleRetirementPreview, type BundleRetirementReachedRow, type BundleRetirementSkipReason, type BundleRetirementSkippedRow, type BundleRetirementSwitchResult, type BundleRetirementSwitchTerms, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionOfferView, type BundleVersionOfferedNotice, type BundleVersionRetiredNotice, type BundleVersionRetirementRecord, type BundleVersionRetirementReminder, type BundleVersionRetirementRepository, type BundleVersionRetirementView, type BundleVersionRow, type BundleVersionSide, type BundleVersionSwitchResult, CASE_CLOSED_REFUND_ENDED, CASE_CLOSED_REVERSAL_GIVEN_BACK, CATALOGUE_KEYS, CATALOG_ERROR_CODES, COLLECTION_FAILURE_REASONS, COLLECTION_NOT_SENT_PAID, COLLECTION_NOT_SENT_REVERSED, COLLECTION_RETRY_AFTER_DAYS, CONTRACT_ERROR_CODES, CUSTOM_LIMITS_KEYS, type CalendarDay, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalBundleVersionRetirementRow, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalFeatureWithdrawalRow, type CanonicalInvoiceCollectionRow, type CanonicalInvoiceSettlementRow, type CanonicalMaintenanceWindowRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalReconciliationCaseRow, type CanonicalRunningContractRow, type CanonicalSubscriberChargeRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberCreditEntryRow, type CanonicalSubscriberCreditRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberPaymentRow, type CanonicalSubscriberRefundRow, type CanonicalSubscriberReversalRow, type CanonicalSubscriberRow, type CanonicalSubscriberTaxOriginChangeRow, type CanonicalSubscriberVatIdCheckRow, type CanonicalSubscriptionBundleRow, type CanonicalSubscriptionInvoiceArchiveRow, type CanonicalSubscriptionInvoiceDocumentRow, type CanonicalSubscriptionInvoiceLineRow, type CanonicalSubscriptionInvoiceRow, type CanonicalSubscriptionNoticeRow, type CanonicalVersionRetirementRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type CatalogVersionKind, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferSelection, type CheckoutOfferSelectionUpdate, type CheckoutOfferStatus, type CleanupResult, type CliUserRow, type CloseReconciliationCase, type ClosedReconciliationCase, type CollectInvoiceInput, type CollectionAnnouncedNotice, type CollectionFailedNotice, type CollectionFailureNext, type CollectionFailureReason, type CollectionOutcome, type CollectionReversedNext, type CollectionReversedNotice, type ComponentKey, type ConcurrencyGate, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ConfirmedPaymentMethod, type ContractErrorCode, type ContractIssuerParty, type ContractLineItemKind, type ContractLineItemRecord, type ContractSubscriberParty, type CoveringCredit, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriberData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type CreditPart, type CustomLimits, DIRECT_DEBIT_LEAD_DAYS, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ENDED_REFUND_STATUSES, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EarlierCollection, type EffectiveLimitsSnapshot, type EmailPort, type EndAtOncePreview, type EndNowInput, type EndSubscriptionNowResult, type EndedAtOnce, type EndedAtOnceNotice, type ErrorMessageParams, FEATURE_NOT_LICENSED, FEATURE_WITHDRAWAL_CAPABILITY, FEATURE_WITHDRAWAL_REASON_MAX_LENGTH, FOLLOWED_UP_COLLECTION_STATUSES, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FeatureWithdrawalAnnounced, type FeatureWithdrawalBlocker, type FeatureWithdrawalLift, type FeatureWithdrawalLifted, type FeatureWithdrawalLiftedNotice, type FeatureWithdrawalLine, type FeatureWithdrawalLineKind, type FeatureWithdrawalMark, type FeatureWithdrawalNoticeLine, type FeatureWithdrawalPreview, type FeatureWithdrawalReachedRow, type FeatureWithdrawalRecord, type FeatureWithdrawalReduction, type FeatureWithdrawalRepository, type FeatureWithdrawalRow, type FeatureWithdrawalSkippedRow, type FeatureWithdrawalTarget, type FeatureWithdrawalView, type FeatureWithdrawnNotice, type FinalActivationResult, type FindCollectionInput, type FirstTimeCustomerCheck, ForeignPaymentMethodReferenceError, GIVING_BACK_CREDIT_ENTRY_KINDS, type GatewayRefund, type GatewayReversal, type HeldVatId, INVOICE_ARCHIVE_TRIGGERS, INVOICE_COLLECTION_ASK_EVERY_MS, INVOICE_COLLECTION_LEASE_MS, INVOICE_COLLECTION_STATUSES, INVOICE_DOCUMENT_CAPABILITY, INVOICE_ERROR_CODES, INVOICE_SEQUENCE_DIGITS, INVOICE_SETTLEMENT_KINDS, type ImmediatePlanChangeInput, type InvoiceArchivePort, type InvoiceCollectionColumns, type InvoiceCollectionNotice, type InvoiceCollectionRecord, type InvoiceCollectionRepository, type InvoiceCollectionStatus, type InvoiceContentDraft, type InvoiceDocument, type InvoiceDocumentToArchive, type InvoiceDraftInput, type InvoiceErrorCode, type InvoiceGroup, type InvoiceLineItemSnapshot, type InvoiceMail, type InvoiceMailPort, type InvoiceNoticeMail, type InvoicePart, type InvoiceRenderer, type InvoiceSettlementKind, type InvoiceTaxLine, type IssuerCorrectionFault, type IssuerHistoryStep, type IssuerIdentityChange, type KpiCardDef, type KpiDisplayHint, LEGAL_IDENTITY_FIELDS, type LegalIdentity, type LegalIdentityField, type LiftedCover, MAINTENANCE_CAPABILITY, MAINTENANCE_ERROR_CODES, MAINTENANCE_MESSAGE_MAX_LENGTH, MAINTENANCE_STATE_MAX_AGE_SECONDS, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type MaintenanceErrorCode, type MaintenanceLockView, type MaintenanceNotificationPort, type MaintenanceOverview, type MaintenanceStatusView, type MaintenanceUnlockView, type MaintenanceWindowChanges, type MaintenanceWindowEvent, type MaintenanceWindowPort, type MaintenanceWindowRecord, type MaintenanceWindowStage, type MaintenanceWindowStatus, type MaintenanceWindowView, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, NO_SCHEDULED_CHANGE, type NewBundleVersionRetirement, type NewContractLineItemData, type NewFeatureWithdrawal, type NewInvoiceCollection, type NewInvoiceRendering, type NewMaintenanceWindow, type NewReconciliationCase, type NewSettingsChange, type NewSubscriberCharge, type NewSubscriberDetails, type NewSubscriberPayment, type NewSubscriberPayout, type NewSubscriptionContractData, type NewSubscriptionInvoice, type NewSubscriptionInvoiceLine, type NewVersionRetirement, type NotToldReasons, type NoticeToRecord, OPTIONAL_CANONICAL_MODELS, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, type OpenCredit, type OptionalBundleMember, type OptionalCanonicalModel, type OrderlyRetirementSettings, PASSWORD_RESET_TTL_MINUTES, PAYMENT_ERROR_CODES, PAYMENT_METHOD_TYPES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PartyAddress, type PasswordHasher, type PasswordResetCliResult, PaymentCallbackRejectedError, type PaymentErrorCode, type PaymentEventClaim, type PaymentEventLog, type PaymentGateway, type PaymentGatewayCallback, type PaymentGatewayEvent, type PaymentMethodHolder, type PaymentMethodSetupSession, type PaymentMethodSetupSubject, type PaymentMethodType, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, PersistenceRefusal, type PersistenceRefusalReason, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogInvoicing, type PlanCatalogIssuer, type PlanCatalogIssuerCorrection, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogNotifications, type PlanCatalogPaymentAccount, type PlanCatalogPayments, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, type PlanCatalogSettings, type PlanCatalogSubscribers, type PlanCatalogTax, type PlanCatalogTenantBilling, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlannedInvoiceCollection, type PlatformErrorBody, type PlatformErrorCode, type PlatformJobActor, type PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeHoldRecord, type PromoCodeHoldRepository, type PromoCodeHoldTaken, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionI18n, type PromotionI18nFields, type PromotionOnPrice, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicNewPaymentMethods, type PublicSignupPlan, type PublishBundleVersionData, type PublishBundleVersionMeta, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, RECONCILIATION_CASE_KINDS, RECONCILIATION_CLOSE_CAPABILITY, RECONCILIATION_NOTE_MAX_LENGTH, RECONCILIATION_READ_CAPABILITY, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, REOPENING_SETTLEMENT_KINDS, RETIREMENT_REMINDER_LEAD_DAYS, REVERSIBLE_COLLECTION_STATUSES, type ReadCustomLimits, type ReassignTenantAdminCliResult, type RecommendablePlan, type ReconciliationCaseKind, type ReconciliationCaseState, type RecordSubscriberPaymentMethodData, type RecordSubscriberPaymentMethodOutcome, type RecordSubscriberPaymentMethodResult, type RecordedSubscriberPayment, type RecordedSubscriberPayout, type RecordedSubscriberRefund, type RecordedSubscriberReversal, type RecordedVatIdCheck, type RedeemPromoInTransactionCallback, type RegistrationActivation, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationBillingDetails, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type ReinstatableParts, type ReinstatementParts, type ReportedSubscriberRefund, type ReportedSubscriberReversal, type RequiredCapabilities, type ResolvableErrorBody, type ResumeRegistrationInput, type ResumeRegistrationResult, type RetiredBundleVersionRef, type RetiredVersionRef, type RetirementAnnounced, type RetirementBlocker, type RetirementMoveRun, type RetirementPreview, type RetirementPricedSide, type RetirementProgress, type RetirementReachedRow, type RetirementSide, type RetirementSkipReason, type RetirementSkippedRow, type RetirementSwitchResult, type RetirementSwitchTerms, type ReversalReinstatement, type ReversalWithdrawal, type ReversibleCredit, type ReversibleInvoice, type ReviewCatalogEntryData, type RlsBypassPort, type RunningContractIssuer, type RunningContractIssuers, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ACCOUNT_CAPABILITY, SUBSCRIBER_ATTENTION_CAPABILITY, SUBSCRIBER_ATTENTION_PAGE_SIZE, SUBSCRIBER_CHARGE_ORIGINS, SUBSCRIBER_CHARGE_SOURCES, SUBSCRIBER_CORRECTION_CAPABILITY, SUBSCRIBER_CREDIT_CAPABILITY, SUBSCRIBER_CREDIT_ENTRY_KINDS, SUBSCRIBER_ERROR_CODES, SUBSCRIBER_INVOICE_ADDRESS_FIELDS, SUBSCRIBER_PAYMENTS_CAPABILITY, SUBSCRIBER_PAYOUT_CAPABILITY, SUBSCRIBER_REFUND_STATUSES, SUBSCRIBER_STANDING_CAPABILITY, SUBSCRIBER_TAX_ORIGIN_FIELDS, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePayments, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledChangeColumns, type ScheduledPlanChangeInput, type SecretSealer, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SelfServiceBlockedPlans, type SetCatalogEntryReviewData, type SettingsChangeFilter, type SettingsChangeRecord, type SettingsDifference, type SettingsErrorCode, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartPaymentMethodSetupInput, type StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type SubmittedInvoiceCollection, type SubscriberBusinessStatusData, type SubscriberBusinessStatusResult, type SubscriberCharge, type SubscriberChargeOrigin, type SubscriberChargeRecord, type SubscriberChargeSource, type SubscriberContact, type SubscriberContactChange, type SubscriberCorrectionData, type SubscriberCorrectionRecord, type SubscriberCorrectionResult, type SubscriberCreditEntryKind, type SubscriberCreditEntryRecord, type SubscriberCreditOrigin, type SubscriberCreditRecord, type SubscriberCreditStanding, type SubscriberDetails, type SubscriberErrorCode, type SubscriberIdentityCorrection, type SubscriberIdentityDelta, type SubscriberIdentityValues, type SubscriberInvoiceAddressField, type SubscriberLedgerRepository, type SubscriberPaymentMethodRecord, type SubscriberPaymentMethodReference, type SubscriberPaymentMethodRepository, type SubscriberPaymentMethodSetupData, type SubscriberPaymentMethodSetupMatch, type SubscriberPaymentMethodStatus, type SubscriberPaymentRecord, type SubscriberPaymentRepository, type SubscriberReadiness, type SubscriberReconciliationCaseRecord, type SubscriberRecord, type SubscriberRefundRecord, type SubscriberRefundStatus, type SubscriberRepository, type SubscriberReversalRecord, type SubscriberTaxOrigin, type SubscriberTaxOriginChangeRecord, type SubscriberTaxOriginField, type SubscriberTaxOriginValues, type SubscriberTaxStatus, type SubscriberVatIdCheckRecord, type SubscriberVatIdCheckResult, type SubscriberWithCurrentCheck, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractParties, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionInvoiceColumns, type SubscriptionInvoiceDocumentRecord, type SubscriptionInvoiceIssuer, type SubscriptionInvoiceLineColumns, type SubscriptionInvoiceLineRecord, type SubscriptionInvoicePayment, type SubscriptionInvoiceRecord, type SubscriptionInvoiceRepository, type SubscriptionInvoiceSubscriber, type SubscriptionNotice, type SubscriptionNoticeDelivery, type SubscriptionNoticeKey, type SubscriptionNoticeKind, type SubscriptionNoticePort, type SubscriptionNoticeRecord, type SubscriptionNoticeRepository, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SupersedeSubscriptionContractData, type SyncDiscoveryResult, TAX_ERROR_CODES, TAX_TREATMENT_KINDS, type TaxAdapter, type TaxAdapterFactory, type TaxAdapterIdentity, type TaxAtRate, type TaxDecision, type TaxDecisionRequest, type TaxErrorCode, type TaxIssuer, type TaxOriginWrite, type TaxPerRate, type TaxTreatment, type TaxTreatmentKind, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantFeatureWithdrawal, type TenantFeatureWithdrawalLine, type TenantListFilter, type TenantPort, type TenantSubscriptionUsage, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, UNSETTLED_COLLECTION_STATUSES, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, VERSION_RETIREMENT_CAPABILITY, type VatCategory, type VatIdCheck, type VatIdCheckOutcome, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionOffer, type VersionOfferClass, type VersionOfferFields, type VersionOfferSide, type VersionOfferView, type VersionOfferedNotice, type VersionRetiredNotice, type VersionRetirementRecord, type VersionRetirementReminder, type VersionRetirementRepository, type VersionRetirementView, type VersionSale, type VersionSaleDates, type VersionSaleKind, type VersionSwitchResult, type VersionWindow, type VersionedEntityBase, type WithdrawalParts, type WithdrawnFeature, addDaysToDay, announcedCollectionDay, applyPromo, asXmlReadsIt, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleKeyTaken, bundleStemDefaults, canonicalJson, canonicalVatId, casesCovered, catalogDraftExists, catalogVersionAlreadyPublished, catalogVersionGone, chargedAgainOn, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, classifyVersionOffer, collectUnsatisfiedRequires, collectionAttemptKey, collectionOutcomeColumns, collectionStatusOf, columnAmountOf, computeIncludedVat, concurrencyGate, concurrencyGateOf, contractPartiesOf, coverageExcludingSelf, coversLifted, coversOf, customLimitsReader, dayInZone, definedFields, diffSettings, directDebitLeadDaysOf, draftSubscriptionInvoice, endedAtOnceSubjectOf, featureWithdrawalRowOf, featuresWithdrawnAt, formatCustomerNumber, formatErrorMessage, formatInvoiceNumber, grossFromNet, holdsOnlyXmlCharacters, identityCorrectionDelta, inWithdrawalOrder, invoiceArchiveProtectionProblem, invoiceCollectionColumns, invoiceContentDraftOf, invoiceFooterOf, invoiceGroupsOf, invoiceIssuerOf, invoicePaymentOf, isBundleRedundant, isChargedAgain, isEndedRefund, isFeatureWithdrawnAt, isForeignPaymentMethodReferenceError, isInvoiceDocumentChecksum, isMaintenanceAnnouncementLapsed, isMaintenanceOverrun, isPaymentCallbackRejectedError, isPersistenceRefusal, isPlatformUserExistsError, isRetryableCollectionFailure, isVersionActiveAt, isVersionEditable, issuerIdentityOf, keepOneRecommended, keepsVatIdCheck, lastCollectionOf, lastDayInZone, maintenanceRetryAfterSeconds, maintenanceStatusOf, maintenanceWindowStatusOf, maintenanceWindowViewOf, marketingProjectionTaken, membersLeftOut, missingRequiresFor, movedIdentityFields, netByInvoice, netFromGross, nextWithdrawalChange, noActivePlanVersion, openOfCredit, owedOn, paidOutByCredit, parseZonedInstant, paymentSettlement, payoutEntryColumns, percentOf, pickActivePromo, planCatalogSettingsOf, planKeyTaken, planNotInCatalog, plannedCollectionColumns, previousUtcDay, promoCodeTaken, promoStatus, promotionOnPrice, prorate, readCustomLimits, readQuotaRecord, readQuotaValue, reconciliationCaseColumns, recordedIssuerIdentity, refundEntryColumns, refundParts, refuseForeignPaymentMethodReference, refusesFirstAttempt, refusesPlannedAttempt, reinstatementParts, resolveBundleAvailability, resolveErrorMessage, retirementCostsTheSubscription, retirementReminderDueAt, retirementReminderIsDue, retirementSwitchTerms, reversalEntryColumns, roundToCents, sameLegalIdentity, scheduledChangeAfterWrite, selectChargeableBundles, sentCollectionOf, settingsSubtreeOf, settledAmountOf, startOfUtcDay, subscriberChargeColumns, subscriberFromRegistration, subscriberPaymentColumns, subscriberPaymentMethodColumns, subscriberRefundColumns, subscriberReversalColumns, subscriptionBundleAlreadyCancelled, subscriptionBundleGone, subscriptionContractGone, subscriptionGone, subscriptionInvoiceChargeInvoiced, subscriptionInvoiceColumns, subscriptionInvoiceDocumentChanged, subscriptionInvoiceLineColumns, sumToCents, taxOriginOf, taxOriginWrite, taxPerRate, taxTreatmentToJson, toArchivedInvoiceDocument, toBundleStemRow, toBundleVersionRetirementRecord, toCents, toCollectionAnnouncedNotice, toCollectionFailedNotice, toCollectionReversedNotice, toContractLineItemRecord, toDecimalString, toFeatureWithdrawalRecord, toInvoiceCollectionRecord, toMaintenanceWindowRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberChargeRecord, toSubscriberCorrectionRecord, toSubscriberCreditEntryRecord, toSubscriberCreditRecord, toSubscriberPaymentMethodRecord, toSubscriberPaymentRecord, toSubscriberReconciliationCaseRecord, toSubscriberRecord, toSubscriberRefundRecord, toSubscriberReversalRecord, toSubscriberTaxOriginChangeRecord, toSubscriberVatIdCheckRecord, toSubscriptionBundleRecord, toSubscriptionContractRecord, toSubscriptionInvoiceDocumentRecord, toSubscriptionInvoiceRecord, toSubscriptionNoticeRecord, toTaxOriginValues, toTaxTreatment, toVersionRetirementRecord, utcMidnightOf, vatCategoryOf, vatIdCheckFromStore, versionOnSale, versionOnSaleOrNext, versionSale, withdrawalParts, withdrawnFeaturesOf, yearOfDay };