@saasicat/spec 1.0.0-rc.2 → 1.0.0-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/acceptance/README.md +3 -3
- package/acceptance/mfa/totp-verify-good-and-bad-code.yaml +6 -6
- package/admin-api.openapi.yaml +331 -77
- package/cli-conventions.md +19 -19
- package/index.cjs +3 -0
- package/index.d.cts +3 -1
- package/index.d.ts +2 -0
- package/index.js +9 -1
- package/package.json +4 -2
- package/prisma-fragments/01-subscription.prisma +34 -47
- package/prisma-fragments/02-promo-code.prisma +38 -0
- package/prisma-fragments/03-plan-versions.prisma +3 -4
- package/prisma-fragments/05-bundle.prisma +4 -5
- package/prisma-fragments/06-catalog-entries.prisma +24 -24
- package/prisma-fragments/07-promotion.prisma +2 -3
- package/prisma-fragments/08-subscription-contract.prisma +42 -5
- package/prisma-fragments/09-pending-registration.prisma +32 -27
- package/prisma-fragments/11-subscription-bundle.prisma +17 -0
- package/prisma-fragments/12-applied-settings.prisma +55 -0
- package/prisma-fragments/13-subscriber.prisma +94 -0
- package/prisma-fragments/14-payments.prisma +108 -0
- package/prisma-fragments/README.md +40 -22
- package/schemas/admin-manifest.schema.json +10 -3
- package/schemas/plan-catalog.schema.json +239 -18
- package/schemas/promo-code.schema.json +7 -1
- package/schemas/tenant-ledger.schema.json +236 -0
- package/sql/1.0-a-contract-names-its-subscriber.postgres.sql +383 -0
- package/sql/1.0-a-payment-method-is-a-gateway-reference.postgres.sql +177 -0
- package/sql/1.0-a-promo-slot-is-held-through-checkout.postgres.sql +69 -0
- package/sql/1.0-a-settings-change-carries-its-order.postgres.sql +73 -0
- package/sql/1.0-line-items-record-their-money.postgres.sql +134 -0
- package/sql/1.0-remove-project-key.postgres.sql +203 -0
- package/sql/1.0-the-applied-settings-are-recorded.postgres.sql +67 -0
- package/sql/constraints.postgres.sql +76 -0
- package/sql/reference-schema.postgres.sql +324 -77
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
-- prisma-fragments/09-pending-registration.prisma
|
|
15
15
|
-- prisma-fragments/10-super-admin.prisma
|
|
16
16
|
-- prisma-fragments/11-subscription-bundle.prisma
|
|
17
|
+
-- prisma-fragments/12-applied-settings.prisma
|
|
18
|
+
-- prisma-fragments/13-subscriber.prisma
|
|
19
|
+
-- prisma-fragments/14-payments.prisma
|
|
17
20
|
-- plus the normative constraints from sql/constraints.postgres.sql.
|
|
18
21
|
-- Do not edit by hand — change the fragments/constraints and regenerate.
|
|
19
22
|
|
|
@@ -26,9 +29,6 @@ CREATE TYPE "BillingCycle" AS ENUM ('MONTHLY', 'YEARLY');
|
|
|
26
29
|
-- CreateEnum
|
|
27
30
|
CREATE TYPE "SubscriptionStatus" AS ENUM ('TRIAL', 'ACTIVE', 'PAST_DUE', 'CANCELED', 'PENDING_SALES');
|
|
28
31
|
|
|
29
|
-
-- CreateEnum
|
|
30
|
-
CREATE TYPE "SubscriptionPaymentType" AS ENUM ('CARD', 'SEPA', 'PAYPAL', 'KLARNA', 'INVOICE');
|
|
31
|
-
|
|
32
32
|
-- CreateEnum
|
|
33
33
|
CREATE TYPE "PromoCodeValueType" AS ENUM ('PERCENT', 'ABSOLUTE');
|
|
34
34
|
|
|
@@ -60,8 +60,11 @@ CREATE TABLE "subscriptions" (
|
|
|
60
60
|
"trialEndsAt" TIMESTAMP(3),
|
|
61
61
|
"startedAt" TIMESTAMP(3),
|
|
62
62
|
"canceledAt" TIMESTAMP(3),
|
|
63
|
+
"canceledEffectiveAt" TIMESTAMP(3),
|
|
63
64
|
"currentPeriodStart" TIMESTAMP(3),
|
|
64
65
|
"currentPeriodEnd" TIMESTAMP(3),
|
|
66
|
+
"minimumTermUntil" TIMESTAMP(3),
|
|
67
|
+
"billingAnchorDay" INTEGER,
|
|
65
68
|
"planVersionId" TEXT NOT NULL,
|
|
66
69
|
"pendingPlanVersionId" TEXT,
|
|
67
70
|
"pendingPlanVersionEffectiveAt" TIMESTAMP(3),
|
|
@@ -89,29 +92,9 @@ CREATE TABLE "subscriptions" (
|
|
|
89
92
|
CONSTRAINT "subscriptions_pkey" PRIMARY KEY ("id")
|
|
90
93
|
);
|
|
91
94
|
|
|
92
|
-
-- CreateTable
|
|
93
|
-
CREATE TABLE "subscription_payment_methods" (
|
|
94
|
-
"id" TEXT NOT NULL,
|
|
95
|
-
"subscriptionId" TEXT NOT NULL,
|
|
96
|
-
"type" "SubscriptionPaymentType" NOT NULL,
|
|
97
|
-
"cardName" TEXT,
|
|
98
|
-
"cardBrand" TEXT,
|
|
99
|
-
"cardLast4" TEXT,
|
|
100
|
-
"cardExp" TEXT,
|
|
101
|
-
"ibanLast4" TEXT,
|
|
102
|
-
"ibanName" TEXT,
|
|
103
|
-
"paypalEmail" TEXT,
|
|
104
|
-
"klarnaPlan" TEXT,
|
|
105
|
-
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
106
|
-
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
107
|
-
|
|
108
|
-
CONSTRAINT "subscription_payment_methods_pkey" PRIMARY KEY ("id")
|
|
109
|
-
);
|
|
110
|
-
|
|
111
95
|
-- CreateTable
|
|
112
96
|
CREATE TABLE "checkout_offers" (
|
|
113
97
|
"id" TEXT NOT NULL,
|
|
114
|
-
"projectKey" TEXT NOT NULL,
|
|
115
98
|
"planKey" TEXT NOT NULL,
|
|
116
99
|
"planVersionId" TEXT,
|
|
117
100
|
"billingCycle" TEXT NOT NULL,
|
|
@@ -145,6 +128,7 @@ CREATE TABLE "promo_codes" (
|
|
|
145
128
|
"validUntil" TIMESTAMP(3),
|
|
146
129
|
"maxRedemptions" INTEGER,
|
|
147
130
|
"redemptionsCount" INTEGER NOT NULL DEFAULT 0,
|
|
131
|
+
"heldCount" INTEGER NOT NULL DEFAULT 0,
|
|
148
132
|
"appliesToPlans" TEXT[],
|
|
149
133
|
"appliesToBilling" "BillingCycle",
|
|
150
134
|
"firstTimeCustomersOnly" BOOLEAN NOT NULL DEFAULT true,
|
|
@@ -181,6 +165,18 @@ CREATE TABLE "promo_code_redemptions" (
|
|
|
181
165
|
CONSTRAINT "promo_code_redemptions_pkey" PRIMARY KEY ("id")
|
|
182
166
|
);
|
|
183
167
|
|
|
168
|
+
-- CreateTable
|
|
169
|
+
CREATE TABLE "promo_code_holds" (
|
|
170
|
+
"id" TEXT NOT NULL,
|
|
171
|
+
"promoCodeId" TEXT NOT NULL,
|
|
172
|
+
"checkoutOfferId" TEXT NOT NULL,
|
|
173
|
+
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
174
|
+
"handedOverTx" BIGINT,
|
|
175
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
176
|
+
|
|
177
|
+
CONSTRAINT "promo_code_holds_pkey" PRIMARY KEY ("id")
|
|
178
|
+
);
|
|
179
|
+
|
|
184
180
|
-- CreateTable
|
|
185
181
|
CREATE TABLE "promo_code_validation_logs" (
|
|
186
182
|
"id" TEXT NOT NULL,
|
|
@@ -197,7 +193,6 @@ CREATE TABLE "promo_code_validation_logs" (
|
|
|
197
193
|
-- CreateTable
|
|
198
194
|
CREATE TABLE "plans" (
|
|
199
195
|
"id" TEXT NOT NULL,
|
|
200
|
-
"projectKey" TEXT NOT NULL,
|
|
201
196
|
"planKey" TEXT NOT NULL,
|
|
202
197
|
"label" TEXT NOT NULL,
|
|
203
198
|
"description" TEXT,
|
|
@@ -257,7 +252,6 @@ CREATE TABLE "audit_logs" (
|
|
|
257
252
|
-- CreateTable
|
|
258
253
|
CREATE TABLE "bundles" (
|
|
259
254
|
"id" TEXT NOT NULL,
|
|
260
|
-
"projectKey" TEXT NOT NULL,
|
|
261
255
|
"bundleKey" TEXT NOT NULL,
|
|
262
256
|
"label" TEXT NOT NULL,
|
|
263
257
|
"description" TEXT,
|
|
@@ -302,7 +296,6 @@ CREATE TABLE "bundle_versions" (
|
|
|
302
296
|
-- CreateTable
|
|
303
297
|
CREATE TABLE "capability_catalog_entries" (
|
|
304
298
|
"id" TEXT NOT NULL,
|
|
305
|
-
"projectKey" TEXT NOT NULL,
|
|
306
299
|
"capabilityKey" TEXT NOT NULL,
|
|
307
300
|
"label" TEXT NOT NULL,
|
|
308
301
|
"description" TEXT,
|
|
@@ -327,7 +320,6 @@ CREATE TABLE "capability_catalog_entries" (
|
|
|
327
320
|
-- CreateTable
|
|
328
321
|
CREATE TABLE "feature_catalog_entries" (
|
|
329
322
|
"id" TEXT NOT NULL,
|
|
330
|
-
"projectKey" TEXT NOT NULL,
|
|
331
323
|
"featureKey" TEXT NOT NULL,
|
|
332
324
|
"label" TEXT NOT NULL,
|
|
333
325
|
"description" TEXT,
|
|
@@ -356,7 +348,6 @@ CREATE TABLE "feature_catalog_entries" (
|
|
|
356
348
|
-- CreateTable
|
|
357
349
|
CREATE TABLE "quota_catalog_entries" (
|
|
358
350
|
"id" TEXT NOT NULL,
|
|
359
|
-
"projectKey" TEXT NOT NULL,
|
|
360
351
|
"quotaKey" TEXT NOT NULL,
|
|
361
352
|
"label" TEXT NOT NULL,
|
|
362
353
|
"description" TEXT,
|
|
@@ -382,7 +373,6 @@ CREATE TABLE "quota_catalog_entries" (
|
|
|
382
373
|
-- CreateTable
|
|
383
374
|
CREATE TABLE "marketing_projections" (
|
|
384
375
|
"id" TEXT NOT NULL,
|
|
385
|
-
"projectKey" TEXT NOT NULL,
|
|
386
376
|
"targetType" TEXT NOT NULL,
|
|
387
377
|
"targetVersionId" TEXT NOT NULL,
|
|
388
378
|
"locale" TEXT NOT NULL DEFAULT 'de',
|
|
@@ -405,8 +395,7 @@ CREATE TABLE "marketing_projections" (
|
|
|
405
395
|
|
|
406
396
|
-- CreateTable
|
|
407
397
|
CREATE TABLE "marketing_settings" (
|
|
408
|
-
"id" TEXT NOT NULL,
|
|
409
|
-
"projectKey" TEXT NOT NULL,
|
|
398
|
+
"id" TEXT NOT NULL DEFAULT 'marketing-settings',
|
|
410
399
|
"activeLocales" JSONB NOT NULL DEFAULT '[]',
|
|
411
400
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
412
401
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
@@ -417,7 +406,6 @@ CREATE TABLE "marketing_settings" (
|
|
|
417
406
|
-- CreateTable
|
|
418
407
|
CREATE TABLE "promotions" (
|
|
419
408
|
"id" TEXT NOT NULL,
|
|
420
|
-
"projectKey" TEXT NOT NULL,
|
|
421
409
|
"internalLabel" TEXT NOT NULL,
|
|
422
410
|
"type" TEXT NOT NULL,
|
|
423
411
|
"value" JSONB NOT NULL,
|
|
@@ -441,8 +429,11 @@ CREATE TABLE "promotions" (
|
|
|
441
429
|
-- CreateTable
|
|
442
430
|
CREATE TABLE "subscription_contracts" (
|
|
443
431
|
"id" TEXT NOT NULL,
|
|
444
|
-
"projectKey" TEXT NOT NULL,
|
|
445
432
|
"tenantId" TEXT NOT NULL,
|
|
433
|
+
"subscriberId" TEXT NOT NULL,
|
|
434
|
+
"subscriberSnapshot" JSONB NOT NULL,
|
|
435
|
+
"issuerSnapshot" JSONB,
|
|
436
|
+
"partiesMigrated" BOOLEAN NOT NULL DEFAULT false,
|
|
446
437
|
"status" "SubscriptionContractStatus" NOT NULL DEFAULT 'active',
|
|
447
438
|
"effectiveFrom" TIMESTAMP(3) NOT NULL,
|
|
448
439
|
"effectiveUntil" TIMESTAMP(3),
|
|
@@ -474,6 +465,9 @@ CREATE TABLE "contract_line_items" (
|
|
|
474
465
|
"priceNet" DECIMAL(10,2) NOT NULL,
|
|
475
466
|
"priceGross" DECIMAL(10,2) NOT NULL,
|
|
476
467
|
"billingCycle" TEXT NOT NULL,
|
|
468
|
+
"currency" TEXT NOT NULL,
|
|
469
|
+
"taxRate" DECIMAL(5,2) NOT NULL,
|
|
470
|
+
"taxAmount" DECIMAL(10,2) NOT NULL,
|
|
477
471
|
"minimumTermUntil" TIMESTAMP(3),
|
|
478
472
|
"featuresSnapshot" JSONB NOT NULL DEFAULT '[]',
|
|
479
473
|
"quotaEffectsSnapshot" JSONB NOT NULL DEFAULT '{}',
|
|
@@ -506,7 +500,16 @@ CREATE TABLE "PendingRegistration" (
|
|
|
506
500
|
"configJson" JSONB,
|
|
507
501
|
"billingCycle" TEXT,
|
|
508
502
|
"appliedPromoCode" TEXT,
|
|
503
|
+
"addressLine1" TEXT,
|
|
504
|
+
"addressLine2" TEXT,
|
|
505
|
+
"postalCode" TEXT,
|
|
506
|
+
"city" TEXT,
|
|
507
|
+
"country" TEXT,
|
|
508
|
+
"vatId" TEXT,
|
|
509
|
+
"taxNumber" TEXT,
|
|
509
510
|
"checkoutSessionId" TEXT,
|
|
511
|
+
"checkoutGatewayAccount" TEXT,
|
|
512
|
+
"gatewayCustomerRef" TEXT,
|
|
510
513
|
"checkoutStartedAt" TIMESTAMP(3),
|
|
511
514
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
512
515
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
@@ -515,19 +518,6 @@ CREATE TABLE "PendingRegistration" (
|
|
|
515
518
|
CONSTRAINT "PendingRegistration_pkey" PRIMARY KEY ("id")
|
|
516
519
|
);
|
|
517
520
|
|
|
518
|
-
-- CreateTable
|
|
519
|
-
CREATE TABLE "PaymentEventLog" (
|
|
520
|
-
"id" TEXT NOT NULL,
|
|
521
|
-
"eventId" TEXT NOT NULL,
|
|
522
|
-
"provider" TEXT NOT NULL,
|
|
523
|
-
"sessionId" TEXT,
|
|
524
|
-
"status" TEXT NOT NULL,
|
|
525
|
-
"payload" JSONB,
|
|
526
|
-
"processedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
527
|
-
|
|
528
|
-
CONSTRAINT "PaymentEventLog_pkey" PRIMARY KEY ("id")
|
|
529
|
-
);
|
|
530
|
-
|
|
531
521
|
-- CreateTable
|
|
532
522
|
CREATE TABLE "super_admin_users" (
|
|
533
523
|
"id" TEXT NOT NULL,
|
|
@@ -562,6 +552,9 @@ CREATE TABLE "subscription_bundles" (
|
|
|
562
552
|
"bundleVersionId" TEXT NOT NULL,
|
|
563
553
|
"startedAt" TIMESTAMP(3) NOT NULL,
|
|
564
554
|
"minimumTermEndsAt" TIMESTAMP(3),
|
|
555
|
+
"billingCycle" TEXT,
|
|
556
|
+
"currentPeriodStart" TIMESTAMP(3),
|
|
557
|
+
"currentPeriodEnd" TIMESTAMP(3),
|
|
565
558
|
"canceledAt" TIMESTAMP(3),
|
|
566
559
|
"canceledEffectiveAt" TIMESTAMP(3),
|
|
567
560
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
@@ -570,6 +563,127 @@ CREATE TABLE "subscription_bundles" (
|
|
|
570
563
|
CONSTRAINT "subscription_bundles_pkey" PRIMARY KEY ("id")
|
|
571
564
|
);
|
|
572
565
|
|
|
566
|
+
-- CreateTable
|
|
567
|
+
CREATE TABLE "applied_settings" (
|
|
568
|
+
"id" TEXT NOT NULL DEFAULT 'installation',
|
|
569
|
+
"fingerprint" TEXT NOT NULL,
|
|
570
|
+
"settings" JSONB NOT NULL,
|
|
571
|
+
"source" TEXT NOT NULL,
|
|
572
|
+
"appliedAt" TIMESTAMP(3) NOT NULL,
|
|
573
|
+
|
|
574
|
+
CONSTRAINT "applied_settings_pkey" PRIMARY KEY ("id")
|
|
575
|
+
);
|
|
576
|
+
|
|
577
|
+
-- CreateTable
|
|
578
|
+
CREATE TABLE "settings_changes" (
|
|
579
|
+
"id" TEXT NOT NULL,
|
|
580
|
+
"seq" SERIAL NOT NULL,
|
|
581
|
+
"noticedAt" TIMESTAMP(3) NOT NULL,
|
|
582
|
+
"source" TEXT NOT NULL,
|
|
583
|
+
"previous" JSONB NOT NULL,
|
|
584
|
+
"current" JSONB NOT NULL,
|
|
585
|
+
"acknowledgedAt" TIMESTAMP(3),
|
|
586
|
+
"acknowledgedBy" TEXT,
|
|
587
|
+
|
|
588
|
+
CONSTRAINT "settings_changes_pkey" PRIMARY KEY ("id")
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
-- CreateTable
|
|
592
|
+
CREATE TABLE "subscribers" (
|
|
593
|
+
"id" TEXT NOT NULL,
|
|
594
|
+
"customerSequence" SERIAL NOT NULL,
|
|
595
|
+
"customerNumberPrefix" TEXT NOT NULL DEFAULT '',
|
|
596
|
+
"legalName" TEXT NOT NULL,
|
|
597
|
+
"vatId" TEXT,
|
|
598
|
+
"taxNumber" TEXT,
|
|
599
|
+
"addressLine1" TEXT,
|
|
600
|
+
"addressLine2" TEXT,
|
|
601
|
+
"postalCode" TEXT,
|
|
602
|
+
"city" TEXT,
|
|
603
|
+
"country" TEXT,
|
|
604
|
+
"invoiceEmail" TEXT,
|
|
605
|
+
"migrated" BOOLEAN NOT NULL DEFAULT false,
|
|
606
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
607
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
608
|
+
|
|
609
|
+
CONSTRAINT "subscribers_pkey" PRIMARY KEY ("id")
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
-- CreateTable
|
|
613
|
+
CREATE TABLE "subscriber_tenants" (
|
|
614
|
+
"id" TEXT NOT NULL,
|
|
615
|
+
"subscriberId" TEXT NOT NULL,
|
|
616
|
+
"tenantId" TEXT NOT NULL,
|
|
617
|
+
"linkedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
618
|
+
"unlinkedAt" TIMESTAMP(3),
|
|
619
|
+
|
|
620
|
+
CONSTRAINT "subscriber_tenants_pkey" PRIMARY KEY ("id")
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
-- CreateTable
|
|
624
|
+
CREATE TABLE "subscriber_corrections" (
|
|
625
|
+
"id" TEXT NOT NULL,
|
|
626
|
+
"subscriberId" TEXT NOT NULL,
|
|
627
|
+
"previous" JSONB NOT NULL,
|
|
628
|
+
"corrected" JSONB NOT NULL,
|
|
629
|
+
"reason" TEXT NOT NULL,
|
|
630
|
+
"correctedBy" TEXT NOT NULL,
|
|
631
|
+
"correctedAt" TIMESTAMP(3) NOT NULL,
|
|
632
|
+
|
|
633
|
+
CONSTRAINT "subscriber_corrections_pkey" PRIMARY KEY ("id")
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
-- CreateTable
|
|
637
|
+
CREATE TABLE "subscriber_payment_methods" (
|
|
638
|
+
"id" TEXT NOT NULL,
|
|
639
|
+
"subscriberId" TEXT NOT NULL,
|
|
640
|
+
"gatewayAccount" TEXT NOT NULL,
|
|
641
|
+
"provider" TEXT NOT NULL,
|
|
642
|
+
"customerRef" TEXT NOT NULL,
|
|
643
|
+
"paymentMethodRef" TEXT NOT NULL,
|
|
644
|
+
"type" TEXT NOT NULL,
|
|
645
|
+
"brand" TEXT,
|
|
646
|
+
"last4" TEXT NOT NULL,
|
|
647
|
+
"expiryMonth" INTEGER,
|
|
648
|
+
"expiryYear" INTEGER,
|
|
649
|
+
"country" TEXT,
|
|
650
|
+
"bankCode" TEXT,
|
|
651
|
+
"mandateReference" TEXT,
|
|
652
|
+
"status" TEXT NOT NULL DEFAULT 'ACTIVE',
|
|
653
|
+
"confirmedAt" TIMESTAMP(3) NOT NULL,
|
|
654
|
+
"replacedAt" TIMESTAMP(3),
|
|
655
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
656
|
+
|
|
657
|
+
CONSTRAINT "subscriber_payment_methods_pkey" PRIMARY KEY ("id")
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
-- CreateTable
|
|
661
|
+
CREATE TABLE "subscriber_payment_method_setups" (
|
|
662
|
+
"id" TEXT NOT NULL,
|
|
663
|
+
"subscriberId" TEXT NOT NULL,
|
|
664
|
+
"gatewayAccount" TEXT NOT NULL,
|
|
665
|
+
"sessionRef" TEXT NOT NULL,
|
|
666
|
+
"customerRef" TEXT NOT NULL,
|
|
667
|
+
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
668
|
+
"completedAt" TIMESTAMP(3),
|
|
669
|
+
|
|
670
|
+
CONSTRAINT "subscriber_payment_method_setups_pkey" PRIMARY KEY ("id")
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
-- CreateTable
|
|
674
|
+
CREATE TABLE "PaymentEventLog" (
|
|
675
|
+
"id" TEXT NOT NULL,
|
|
676
|
+
"gatewayAccount" TEXT NOT NULL,
|
|
677
|
+
"eventId" TEXT NOT NULL,
|
|
678
|
+
"provider" TEXT NOT NULL,
|
|
679
|
+
"sessionId" TEXT,
|
|
680
|
+
"status" TEXT NOT NULL,
|
|
681
|
+
"payload" JSONB,
|
|
682
|
+
"processedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
683
|
+
|
|
684
|
+
CONSTRAINT "PaymentEventLog_pkey" PRIMARY KEY ("id")
|
|
685
|
+
);
|
|
686
|
+
|
|
573
687
|
-- CreateIndex
|
|
574
688
|
CREATE UNIQUE INDEX "subscriptions_tenantId_key" ON "subscriptions"("tenantId");
|
|
575
689
|
|
|
@@ -586,10 +700,7 @@ CREATE INDEX "subscriptions_pendingPlanVersionId_idx" ON "subscriptions"("pendin
|
|
|
586
700
|
CREATE INDEX "subscriptions_currentPeriodEnd_idx" ON "subscriptions"("currentPeriodEnd");
|
|
587
701
|
|
|
588
702
|
-- CreateIndex
|
|
589
|
-
CREATE
|
|
590
|
-
|
|
591
|
-
-- CreateIndex
|
|
592
|
-
CREATE INDEX "checkout_offers_projectKey_status_idx" ON "checkout_offers"("projectKey", "status");
|
|
703
|
+
CREATE INDEX "checkout_offers_status_idx" ON "checkout_offers"("status");
|
|
593
704
|
|
|
594
705
|
-- CreateIndex
|
|
595
706
|
CREATE UNIQUE INDEX "promo_codes_code_key" ON "promo_codes"("code");
|
|
@@ -612,6 +723,15 @@ CREATE INDEX "promo_code_redemptions_promoCodeId_status_idx" ON "promo_code_rede
|
|
|
612
723
|
-- CreateIndex
|
|
613
724
|
CREATE INDEX "promo_code_redemptions_startsAt_endsAt_idx" ON "promo_code_redemptions"("startsAt", "endsAt");
|
|
614
725
|
|
|
726
|
+
-- CreateIndex
|
|
727
|
+
CREATE UNIQUE INDEX "promo_code_holds_checkoutOfferId_key" ON "promo_code_holds"("checkoutOfferId");
|
|
728
|
+
|
|
729
|
+
-- CreateIndex
|
|
730
|
+
CREATE INDEX "promo_code_holds_promoCodeId_expiresAt_idx" ON "promo_code_holds"("promoCodeId", "expiresAt");
|
|
731
|
+
|
|
732
|
+
-- CreateIndex
|
|
733
|
+
CREATE INDEX "promo_code_holds_expiresAt_idx" ON "promo_code_holds"("expiresAt");
|
|
734
|
+
|
|
615
735
|
-- CreateIndex
|
|
616
736
|
CREATE INDEX "promo_code_validation_logs_codeAttempt_createdAt_idx" ON "promo_code_validation_logs"("codeAttempt", "createdAt");
|
|
617
737
|
|
|
@@ -622,10 +742,10 @@ CREATE INDEX "promo_code_validation_logs_ipHash_createdAt_idx" ON "promo_code_va
|
|
|
622
742
|
CREATE INDEX "promo_code_validation_logs_sessionId_createdAt_idx" ON "promo_code_validation_logs"("sessionId", "createdAt");
|
|
623
743
|
|
|
624
744
|
-- CreateIndex
|
|
625
|
-
CREATE INDEX "
|
|
745
|
+
CREATE INDEX "plans_deletedAt_idx" ON "plans"("deletedAt");
|
|
626
746
|
|
|
627
747
|
-- CreateIndex
|
|
628
|
-
CREATE UNIQUE INDEX "
|
|
748
|
+
CREATE UNIQUE INDEX "plans_planKey_key" ON "plans"("planKey");
|
|
629
749
|
|
|
630
750
|
-- CreateIndex
|
|
631
751
|
CREATE INDEX "plan_versions_planId_supersededAt_idx" ON "plan_versions"("planId", "supersededAt");
|
|
@@ -652,10 +772,10 @@ CREATE INDEX "audit_logs_entity_action_createdAt_idx" ON "audit_logs"("entity",
|
|
|
652
772
|
CREATE INDEX "audit_logs_actorTag_createdAt_idx" ON "audit_logs"("actorTag", "createdAt");
|
|
653
773
|
|
|
654
774
|
-- CreateIndex
|
|
655
|
-
CREATE INDEX "
|
|
775
|
+
CREATE INDEX "bundles_deletedAt_idx" ON "bundles"("deletedAt");
|
|
656
776
|
|
|
657
777
|
-- CreateIndex
|
|
658
|
-
CREATE UNIQUE INDEX "
|
|
778
|
+
CREATE UNIQUE INDEX "bundles_bundleKey_key" ON "bundles"("bundleKey");
|
|
659
779
|
|
|
660
780
|
-- CreateIndex
|
|
661
781
|
CREATE INDEX "bundle_versions_bundleId_supersededAt_idx" ON "bundle_versions"("bundleId", "supersededAt");
|
|
@@ -670,46 +790,46 @@ CREATE INDEX "bundle_versions_bundleId_validFrom_idx" ON "bundle_versions"("bund
|
|
|
670
790
|
CREATE UNIQUE INDEX "bundle_versions_bundleId_version_key" ON "bundle_versions"("bundleId", "version");
|
|
671
791
|
|
|
672
792
|
-- CreateIndex
|
|
673
|
-
CREATE INDEX "
|
|
793
|
+
CREATE INDEX "capability_catalog_entries_codeStatus_idx" ON "capability_catalog_entries"("codeStatus");
|
|
674
794
|
|
|
675
795
|
-- CreateIndex
|
|
676
|
-
CREATE INDEX "
|
|
796
|
+
CREATE INDEX "capability_catalog_entries_featureKey_idx" ON "capability_catalog_entries"("featureKey");
|
|
677
797
|
|
|
678
798
|
-- CreateIndex
|
|
679
|
-
CREATE UNIQUE INDEX "
|
|
799
|
+
CREATE UNIQUE INDEX "capability_catalog_entries_capabilityKey_key" ON "capability_catalog_entries"("capabilityKey");
|
|
680
800
|
|
|
681
801
|
-- CreateIndex
|
|
682
|
-
CREATE INDEX "
|
|
802
|
+
CREATE INDEX "feature_catalog_entries_discoveryStatus_idx" ON "feature_catalog_entries"("discoveryStatus");
|
|
683
803
|
|
|
684
804
|
-- CreateIndex
|
|
685
|
-
CREATE INDEX "
|
|
805
|
+
CREATE INDEX "feature_catalog_entries_plannedOnly_idx" ON "feature_catalog_entries"("plannedOnly");
|
|
686
806
|
|
|
687
807
|
-- CreateIndex
|
|
688
|
-
CREATE UNIQUE INDEX "
|
|
808
|
+
CREATE UNIQUE INDEX "feature_catalog_entries_featureKey_key" ON "feature_catalog_entries"("featureKey");
|
|
689
809
|
|
|
690
810
|
-- CreateIndex
|
|
691
|
-
CREATE INDEX "
|
|
811
|
+
CREATE INDEX "quota_catalog_entries_discoveryStatus_idx" ON "quota_catalog_entries"("discoveryStatus");
|
|
692
812
|
|
|
693
813
|
-- CreateIndex
|
|
694
|
-
CREATE UNIQUE INDEX "
|
|
814
|
+
CREATE UNIQUE INDEX "quota_catalog_entries_quotaKey_key" ON "quota_catalog_entries"("quotaKey");
|
|
695
815
|
|
|
696
816
|
-- CreateIndex
|
|
697
|
-
CREATE INDEX "
|
|
817
|
+
CREATE INDEX "marketing_projections_targetType_locale_priority_idx" ON "marketing_projections"("targetType", "locale", "priority");
|
|
698
818
|
|
|
699
819
|
-- CreateIndex
|
|
700
820
|
CREATE UNIQUE INDEX "marketing_projections_targetType_targetVersionId_locale_key" ON "marketing_projections"("targetType", "targetVersionId", "locale");
|
|
701
821
|
|
|
702
822
|
-- CreateIndex
|
|
703
|
-
CREATE
|
|
823
|
+
CREATE INDEX "promotions_targetType_validFrom_validTo_idx" ON "promotions"("targetType", "validFrom", "validTo");
|
|
704
824
|
|
|
705
825
|
-- CreateIndex
|
|
706
|
-
CREATE INDEX "
|
|
826
|
+
CREATE INDEX "subscription_contracts_tenantId_status_effectiveFrom_idx" ON "subscription_contracts"("tenantId", "status", "effectiveFrom");
|
|
707
827
|
|
|
708
828
|
-- CreateIndex
|
|
709
|
-
CREATE INDEX "
|
|
829
|
+
CREATE INDEX "subscription_contracts_subscriberId_idx" ON "subscription_contracts"("subscriberId");
|
|
710
830
|
|
|
711
831
|
-- CreateIndex
|
|
712
|
-
CREATE INDEX "
|
|
832
|
+
CREATE INDEX "subscription_contracts_status_idx" ON "subscription_contracts"("status");
|
|
713
833
|
|
|
714
834
|
-- CreateIndex
|
|
715
835
|
CREATE INDEX "subscription_contracts_originalOfferId_idx" ON "subscription_contracts"("originalOfferId");
|
|
@@ -730,13 +850,7 @@ CREATE INDEX "PendingRegistration_status_expiresAt_idx" ON "PendingRegistration"
|
|
|
730
850
|
CREATE INDEX "PendingRegistration_tenantSlug_idx" ON "PendingRegistration"("tenantSlug");
|
|
731
851
|
|
|
732
852
|
-- CreateIndex
|
|
733
|
-
CREATE
|
|
734
|
-
|
|
735
|
-
-- CreateIndex
|
|
736
|
-
CREATE INDEX "PaymentEventLog_sessionId_idx" ON "PaymentEventLog"("sessionId");
|
|
737
|
-
|
|
738
|
-
-- CreateIndex
|
|
739
|
-
CREATE INDEX "PaymentEventLog_status_processedAt_idx" ON "PaymentEventLog"("status", "processedAt");
|
|
853
|
+
CREATE INDEX "PendingRegistration_checkoutGatewayAccount_checkoutSessionI_idx" ON "PendingRegistration"("checkoutGatewayAccount", "checkoutSessionId");
|
|
740
854
|
|
|
741
855
|
-- CreateIndex
|
|
742
856
|
CREATE UNIQUE INDEX "super_admin_users_email_key" ON "super_admin_users"("email");
|
|
@@ -753,21 +867,63 @@ CREATE INDEX "subscription_bundles_bundleVersionId_idx" ON "subscription_bundles
|
|
|
753
867
|
-- CreateIndex
|
|
754
868
|
CREATE INDEX "subscription_bundles_canceledEffectiveAt_idx" ON "subscription_bundles"("canceledEffectiveAt");
|
|
755
869
|
|
|
870
|
+
-- CreateIndex
|
|
871
|
+
CREATE UNIQUE INDEX "settings_changes_seq_key" ON "settings_changes"("seq");
|
|
872
|
+
|
|
873
|
+
-- CreateIndex
|
|
874
|
+
CREATE INDEX "settings_changes_acknowledgedAt_noticedAt_idx" ON "settings_changes"("acknowledgedAt", "noticedAt");
|
|
875
|
+
|
|
876
|
+
-- CreateIndex
|
|
877
|
+
CREATE UNIQUE INDEX "subscribers_customerSequence_key" ON "subscribers"("customerSequence");
|
|
878
|
+
|
|
879
|
+
-- CreateIndex
|
|
880
|
+
CREATE INDEX "subscriber_tenants_tenantId_idx" ON "subscriber_tenants"("tenantId");
|
|
881
|
+
|
|
882
|
+
-- CreateIndex
|
|
883
|
+
CREATE INDEX "subscriber_tenants_subscriberId_idx" ON "subscriber_tenants"("subscriberId");
|
|
884
|
+
|
|
885
|
+
-- CreateIndex
|
|
886
|
+
CREATE INDEX "subscriber_corrections_subscriberId_correctedAt_idx" ON "subscriber_corrections"("subscriberId", "correctedAt");
|
|
887
|
+
|
|
888
|
+
-- CreateIndex
|
|
889
|
+
CREATE INDEX "subscriber_payment_methods_subscriberId_status_idx" ON "subscriber_payment_methods"("subscriberId", "status");
|
|
890
|
+
|
|
891
|
+
-- CreateIndex
|
|
892
|
+
CREATE INDEX "subscriber_payment_methods_gatewayAccount_status_idx" ON "subscriber_payment_methods"("gatewayAccount", "status");
|
|
893
|
+
|
|
894
|
+
-- CreateIndex
|
|
895
|
+
CREATE UNIQUE INDEX "subscriber_payment_methods_gatewayAccount_paymentMethodRef_key" ON "subscriber_payment_methods"("gatewayAccount", "paymentMethodRef");
|
|
896
|
+
|
|
897
|
+
-- CreateIndex
|
|
898
|
+
CREATE INDEX "subscriber_payment_method_setups_subscriberId_idx" ON "subscriber_payment_method_setups"("subscriberId");
|
|
899
|
+
|
|
900
|
+
-- CreateIndex
|
|
901
|
+
CREATE UNIQUE INDEX "subscriber_payment_method_setups_gatewayAccount_sessionRef_key" ON "subscriber_payment_method_setups"("gatewayAccount", "sessionRef");
|
|
902
|
+
|
|
903
|
+
-- CreateIndex
|
|
904
|
+
CREATE INDEX "PaymentEventLog_sessionId_idx" ON "PaymentEventLog"("sessionId");
|
|
905
|
+
|
|
906
|
+
-- CreateIndex
|
|
907
|
+
CREATE INDEX "PaymentEventLog_status_processedAt_idx" ON "PaymentEventLog"("status", "processedAt");
|
|
908
|
+
|
|
909
|
+
-- CreateIndex
|
|
910
|
+
CREATE UNIQUE INDEX "PaymentEventLog_gatewayAccount_eventId_key" ON "PaymentEventLog"("gatewayAccount", "eventId");
|
|
911
|
+
|
|
756
912
|
-- AddForeignKey
|
|
757
913
|
ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_planVersionId_fkey" FOREIGN KEY ("planVersionId") REFERENCES "plan_versions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
758
914
|
|
|
759
915
|
-- AddForeignKey
|
|
760
916
|
ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_pendingPlanVersionId_fkey" FOREIGN KEY ("pendingPlanVersionId") REFERENCES "plan_versions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
761
917
|
|
|
762
|
-
-- AddForeignKey
|
|
763
|
-
ALTER TABLE "subscription_payment_methods" ADD CONSTRAINT "subscription_payment_methods_subscriptionId_fkey" FOREIGN KEY ("subscriptionId") REFERENCES "subscriptions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
764
|
-
|
|
765
918
|
-- AddForeignKey
|
|
766
919
|
ALTER TABLE "promo_code_redemptions" ADD CONSTRAINT "promo_code_redemptions_promoCodeId_fkey" FOREIGN KEY ("promoCodeId") REFERENCES "promo_codes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
767
920
|
|
|
768
921
|
-- AddForeignKey
|
|
769
922
|
ALTER TABLE "promo_code_redemptions" ADD CONSTRAINT "promo_code_redemptions_subscriptionId_fkey" FOREIGN KEY ("subscriptionId") REFERENCES "subscriptions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
770
923
|
|
|
924
|
+
-- AddForeignKey
|
|
925
|
+
ALTER TABLE "promo_code_holds" ADD CONSTRAINT "promo_code_holds_promoCodeId_fkey" FOREIGN KEY ("promoCodeId") REFERENCES "promo_codes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
926
|
+
|
|
771
927
|
-- AddForeignKey
|
|
772
928
|
ALTER TABLE "promo_code_validation_logs" ADD CONSTRAINT "promo_code_validation_logs_promoCodeId_fkey" FOREIGN KEY ("promoCodeId") REFERENCES "promo_codes"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
773
929
|
|
|
@@ -780,6 +936,9 @@ ALTER TABLE "bundle_versions" ADD CONSTRAINT "bundle_versions_bundleId_fkey" FOR
|
|
|
780
936
|
-- AddForeignKey
|
|
781
937
|
ALTER TABLE "bundle_versions" ADD CONSTRAINT "bundle_versions_baseVersionId_fkey" FOREIGN KEY ("baseVersionId") REFERENCES "bundle_versions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
782
938
|
|
|
939
|
+
-- AddForeignKey
|
|
940
|
+
ALTER TABLE "subscription_contracts" ADD CONSTRAINT "subscription_contracts_subscriberId_fkey" FOREIGN KEY ("subscriberId") REFERENCES "subscribers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
941
|
+
|
|
783
942
|
-- AddForeignKey
|
|
784
943
|
ALTER TABLE "contract_line_items" ADD CONSTRAINT "contract_line_items_contractId_fkey" FOREIGN KEY ("contractId") REFERENCES "subscription_contracts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
785
944
|
|
|
@@ -789,6 +948,18 @@ ALTER TABLE "subscription_bundles" ADD CONSTRAINT "subscription_bundles_subscrip
|
|
|
789
948
|
-- AddForeignKey
|
|
790
949
|
ALTER TABLE "subscription_bundles" ADD CONSTRAINT "subscription_bundles_bundleVersionId_fkey" FOREIGN KEY ("bundleVersionId") REFERENCES "bundle_versions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
791
950
|
|
|
951
|
+
-- AddForeignKey
|
|
952
|
+
ALTER TABLE "subscriber_tenants" ADD CONSTRAINT "subscriber_tenants_subscriberId_fkey" FOREIGN KEY ("subscriberId") REFERENCES "subscribers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
953
|
+
|
|
954
|
+
-- AddForeignKey
|
|
955
|
+
ALTER TABLE "subscriber_corrections" ADD CONSTRAINT "subscriber_corrections_subscriberId_fkey" FOREIGN KEY ("subscriberId") REFERENCES "subscribers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
956
|
+
|
|
957
|
+
-- AddForeignKey
|
|
958
|
+
ALTER TABLE "subscriber_payment_methods" ADD CONSTRAINT "subscriber_payment_methods_subscriberId_fkey" FOREIGN KEY ("subscriberId") REFERENCES "subscribers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
959
|
+
|
|
960
|
+
-- AddForeignKey
|
|
961
|
+
ALTER TABLE "subscriber_payment_method_setups" ADD CONSTRAINT "subscriber_payment_method_setups_subscriberId_fkey" FOREIGN KEY ("subscriberId") REFERENCES "subscribers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
962
|
+
|
|
792
963
|
-- =============================================================================
|
|
793
964
|
-- SaaSiCat — normative PostgreSQL constraints the Prisma DSL cannot express.
|
|
794
965
|
-- =============================================================================
|
|
@@ -808,3 +979,79 @@ CREATE UNIQUE INDEX IF NOT EXISTS plan_versions_draft_per_plan
|
|
|
808
979
|
|
|
809
980
|
CREATE UNIQUE INDEX IF NOT EXISTS bundle_versions_draft_per_bundle
|
|
810
981
|
ON bundle_versions ("bundleId") WHERE "publishedAt" IS NULL;
|
|
982
|
+
|
|
983
|
+
-- `marketing_settings` holds at most ONE row.
|
|
984
|
+
--
|
|
985
|
+
-- The Prisma DSL cannot say this, and the constant default on `id` does not: a
|
|
986
|
+
-- default applies only where the caller omits the value, and a primary key
|
|
987
|
+
-- accepts every distinct one. A consumer writing the row directly could make as
|
|
988
|
+
-- many as it liked, and the repository would then read one and ignore the rest.
|
|
989
|
+
--
|
|
990
|
+
-- `ADD CONSTRAINT` has no `IF NOT EXISTS`, and this file is applied again on
|
|
991
|
+
-- every deployment — so it is dropped first. Two plain statements rather than a
|
|
992
|
+
-- dollar-quoted `DO` block on purpose: every consumer of this file splits it at
|
|
993
|
+
-- the statement separator, and a dollar-quoted body would need each of those
|
|
994
|
+
-- splitters to become a SQL lexer. For the same reason no comment in this file
|
|
995
|
+
-- may contain that separator — one here did, and three splitters cut the
|
|
996
|
+
-- sentence in half.
|
|
997
|
+
ALTER TABLE marketing_settings
|
|
998
|
+
DROP CONSTRAINT IF EXISTS marketing_settings_is_a_singleton;
|
|
999
|
+
ALTER TABLE marketing_settings
|
|
1000
|
+
ADD CONSTRAINT marketing_settings_is_a_singleton CHECK ("id" = 'marketing-settings');
|
|
1001
|
+
|
|
1002
|
+
-- `applied_settings` holds at most ONE row: the installation's.
|
|
1003
|
+
--
|
|
1004
|
+
-- Same reasoning as above, and the same two plain statements. The row mirrors
|
|
1005
|
+
-- the settings the installation applied at its last start, and an installation
|
|
1006
|
+
-- serves one application, so there is exactly one configuration to record.
|
|
1007
|
+
ALTER TABLE applied_settings
|
|
1008
|
+
DROP CONSTRAINT IF EXISTS applied_settings_is_a_singleton;
|
|
1009
|
+
ALTER TABLE applied_settings
|
|
1010
|
+
ADD CONSTRAINT applied_settings_is_a_singleton CHECK ("id" = 'installation');
|
|
1011
|
+
|
|
1012
|
+
-- A subscriber is live for at most ONE tenant, and a tenant has at most ONE
|
|
1013
|
+
-- live subscriber. A link that ended keeps its row with `unlinkedAt` set, so the
|
|
1014
|
+
-- tenants a subscriber had before stay in its history. Two partial unique
|
|
1015
|
+
-- indexes, because a link that is over must not count against the next one.
|
|
1016
|
+
CREATE UNIQUE INDEX IF NOT EXISTS subscriber_tenants_live_per_tenant
|
|
1017
|
+
ON subscriber_tenants ("tenantId") WHERE "unlinkedAt" IS NULL;
|
|
1018
|
+
|
|
1019
|
+
CREATE UNIQUE INDEX IF NOT EXISTS subscriber_tenants_live_per_subscriber
|
|
1020
|
+
ON subscriber_tenants ("subscriberId") WHERE "unlinkedAt" IS NULL;
|
|
1021
|
+
|
|
1022
|
+
-- A subscriber has at most ONE payment method in use. The one a newer payment
|
|
1023
|
+
-- method replaced keeps its row as `REPLACED`, so it does not count here.
|
|
1024
|
+
CREATE UNIQUE INDEX IF NOT EXISTS subscriber_payment_methods_active_per_subscriber
|
|
1025
|
+
ON subscriber_payment_methods ("subscriberId") WHERE "status" = 'ACTIVE';
|
|
1026
|
+
|
|
1027
|
+
-- A gateway session is confirmed ONCE.
|
|
1028
|
+
--
|
|
1029
|
+
-- A gateway delivers every event at least once, and it may report one session
|
|
1030
|
+
-- through more than one event — a completed form and the payment method behind
|
|
1031
|
+
-- it can arrive as two. `eventId` tells those apart, so both would be claimed,
|
|
1032
|
+
-- and both would record the session's payment method: for a sign-up that means
|
|
1033
|
+
-- a second tenant for one registration.
|
|
1034
|
+
--
|
|
1035
|
+
-- Both adapters claim with `ON CONFLICT DO NOTHING` and no conflict target, so
|
|
1036
|
+
-- this index turns the second confirmation into no row rather than an error,
|
|
1037
|
+
-- and the caller reads it as the duplicate it is. Partial on the kind, because
|
|
1038
|
+
-- a failed setup and an event SaaSiCat does not act on say nothing about the
|
|
1039
|
+
-- session being confirmed. A claim carrying no session does not collide:
|
|
1040
|
+
-- PostgreSQL counts nulls as distinct in a unique index.
|
|
1041
|
+
CREATE UNIQUE INDEX IF NOT EXISTS payment_event_log_confirmation_per_session
|
|
1042
|
+
ON "PaymentEventLog" ("gatewayAccount", "sessionId")
|
|
1043
|
+
WHERE "status" = 'payment-method-confirmed';
|
|
1044
|
+
|
|
1045
|
+
-- Customer numbers count from 10001, so a number has five digits up to 99999
|
|
1046
|
+
-- and none reads as a count of subscribers. Two statements: the first makes
|
|
1047
|
+
-- 10001 where the sequence starts over, which a restart of its identity reads,
|
|
1048
|
+
-- and the second moves a sequence that has never handed out a number there. A
|
|
1049
|
+
-- second run finds the start already set and the sequence used, and an
|
|
1050
|
+
-- installation without the subscriber tables has no such sequence.
|
|
1051
|
+
ALTER SEQUENCE IF EXISTS "subscribers_customerSequence_seq" START WITH 10001;
|
|
1052
|
+
|
|
1053
|
+
SELECT setval(format('%I.%I', schemaname, sequencename)::regclass, 10001, false)
|
|
1054
|
+
FROM pg_sequences
|
|
1055
|
+
WHERE schemaname = current_schema()
|
|
1056
|
+
AND sequencename = 'subscribers_customerSequence_seq'
|
|
1057
|
+
AND last_value IS NULL;
|