Docker-Images bauen und veroeffentlichen / build-and-push (push) Failing after 1m32s
529 lines
18 KiB
PL/PgSQL
529 lines
18 KiB
PL/PgSQL
-- CreateEnum
|
|
CREATE TYPE "PricePhase" AS ENUM ('PREVIEW', 'EARLY_BIRD', 'REGULAR');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "BookingStatus" AS ENUM ('PENDING', 'CONFIRMED', 'CANCELED', 'EXPIRED', 'NEEDS_REVIEW');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "PaymentStatus" AS ENUM ('UNPAID', 'PROCESSING', 'PARTIALLY_PAID', 'PAID', 'FAILED', 'PARTIALLY_REFUNDED', 'REFUNDED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "PlanType" AS ENUM ('FULL', 'TWO_INSTALLMENTS', 'THREE_INSTALLMENTS');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "InstallmentStatus" AS ENUM ('PENDING', 'PROCESSING', 'PAID', 'FAILED', 'REQUIRES_ACTION', 'CANCELED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ReservationStatus" AS ENUM ('ACTIVE', 'HELD', 'CONVERTED', 'RELEASED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "RedemptionStatus" AS ENUM ('RESERVED', 'COMPLETED', 'RELEASED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "StripeEventStatus" AS ENUM ('PROCESSING', 'PROCESSED', 'IGNORED', 'FAILED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "EmailStatus" AS ENUM ('PENDING', 'SENT', 'FAILED');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ActorType" AS ENUM ('ADMIN', 'CUSTOMER', 'STRIPE', 'WORKER', 'SYSTEM');
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Camp" (
|
|
"id" TEXT NOT NULL,
|
|
"salesEnabled" BOOLEAN NOT NULL DEFAULT false,
|
|
"capacity" INTEGER NOT NULL DEFAULT 10,
|
|
"capacityConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"stammmodelQuota" INTEGER NOT NULL DEFAULT 4,
|
|
"stammmodelQuotaConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"campStartDate" DATE,
|
|
"campEndDate" DATE,
|
|
"dateConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"locationName" TEXT,
|
|
"locationRegion" TEXT,
|
|
"locationConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"accommodationText" TEXT,
|
|
"accommodationConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"servicesConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"organizerName" TEXT,
|
|
"organizerAddress" TEXT,
|
|
"organizerEmail" TEXT,
|
|
"organizerPhone" TEXT,
|
|
"organizerConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"taxNote" TEXT,
|
|
"taxConfirmed" BOOLEAN NOT NULL DEFAULT false,
|
|
"termsVersion" TEXT,
|
|
"termsUrl" TEXT,
|
|
"termsApproved" BOOLEAN NOT NULL DEFAULT false,
|
|
"travelLawChecked" BOOLEAN NOT NULL DEFAULT false,
|
|
"installmentsApproved" BOOLEAN NOT NULL DEFAULT false,
|
|
"installmentRuleApproved" BOOLEAN NOT NULL DEFAULT false,
|
|
"reservationMinutes" INTEGER NOT NULL DEFAULT 30,
|
|
"finalInstallmentLeadDays" INTEGER NOT NULL DEFAULT 30,
|
|
"minInstallmentGapDays" INTEGER NOT NULL DEFAULT 14,
|
|
"testPhaseOverride" "PricePhase",
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
"updatedBy" TEXT,
|
|
|
|
CONSTRAINT "Camp_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Booking" (
|
|
"id" TEXT NOT NULL,
|
|
"reference" TEXT NOT NULL,
|
|
"campId" TEXT NOT NULL,
|
|
"status" "BookingStatus" NOT NULL DEFAULT 'PENDING',
|
|
"paymentStatus" "PaymentStatus" NOT NULL DEFAULT 'UNPAID',
|
|
"livemode" BOOLEAN NOT NULL,
|
|
"idempotencyKey" TEXT NOT NULL,
|
|
"statusTokenHash" TEXT NOT NULL,
|
|
"firstName" TEXT NOT NULL,
|
|
"lastName" TEXT NOT NULL,
|
|
"email" TEXT NOT NULL,
|
|
"phone" TEXT NOT NULL,
|
|
"country" TEXT NOT NULL,
|
|
"notes" TEXT,
|
|
"adultConfirmedAt" TIMESTAMP(3) NOT NULL,
|
|
"termsAcceptedAt" TIMESTAMP(3) NOT NULL,
|
|
"termsVersion" TEXT NOT NULL,
|
|
"accommodationAcknowledgedAt" TIMESTAMP(3) NOT NULL,
|
|
"privacyAcknowledgedAt" TIMESTAMP(3) NOT NULL,
|
|
"installmentMandateAt" TIMESTAMP(3),
|
|
"pricePhase" "PricePhase" NOT NULL,
|
|
"basePriceCents" INTEGER NOT NULL,
|
|
"phaseDiscountCents" INTEGER NOT NULL,
|
|
"voucherDiscountCents" INTEGER NOT NULL,
|
|
"totalCents" INTEGER NOT NULL,
|
|
"planType" "PlanType" NOT NULL,
|
|
"priceSnapshot" JSONB NOT NULL,
|
|
"priceLockedUntil" TIMESTAMP(3) NOT NULL,
|
|
"voucherId" TEXT,
|
|
"stripeCustomerId" TEXT,
|
|
"stripeCheckoutSessionId" TEXT,
|
|
"stripeCheckoutUrl" TEXT,
|
|
"stripePaymentMethodId" TEXT,
|
|
"paymentMethodDetachedAt" TIMESTAMP(3),
|
|
"paidCents" INTEGER NOT NULL DEFAULT 0,
|
|
"refundedCents" INTEGER NOT NULL DEFAULT 0,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
"confirmedAt" TIMESTAMP(3),
|
|
"canceledAt" TIMESTAMP(3),
|
|
"cancelReason" TEXT,
|
|
"reviewReason" TEXT,
|
|
|
|
CONSTRAINT "Booking_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Installment" (
|
|
"id" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"seq" INTEGER NOT NULL,
|
|
"amountCents" INTEGER NOT NULL,
|
|
"dueAt" TIMESTAMP(3),
|
|
"status" "InstallmentStatus" NOT NULL DEFAULT 'PENDING',
|
|
"attemptCount" INTEGER NOT NULL DEFAULT 0,
|
|
"lastAttemptAt" TIMESTAMP(3),
|
|
"nextAttemptAt" TIMESTAMP(3),
|
|
"failureCode" TEXT,
|
|
"paidAt" TIMESTAMP(3),
|
|
"refundedCents" INTEGER NOT NULL DEFAULT 0,
|
|
"stripePaymentIntentId" TEXT,
|
|
"stripeChargeId" TEXT,
|
|
"checkoutSessionId" TEXT,
|
|
"checkoutExpiresAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Installment_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Refund" (
|
|
"id" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"installmentId" TEXT,
|
|
"stripeRefundId" TEXT NOT NULL,
|
|
"amountCents" INTEGER NOT NULL,
|
|
"status" TEXT NOT NULL,
|
|
"reason" TEXT,
|
|
"createdBy" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Refund_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "SeatReservation" (
|
|
"id" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"campId" TEXT NOT NULL,
|
|
"livemode" BOOLEAN NOT NULL,
|
|
"status" "ReservationStatus" NOT NULL DEFAULT 'ACTIVE',
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"releasedAt" TIMESTAMP(3),
|
|
"releaseReason" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "SeatReservation_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Voucher" (
|
|
"id" TEXT NOT NULL,
|
|
"code" TEXT NOT NULL,
|
|
"active" BOOLEAN NOT NULL DEFAULT true,
|
|
"validFrom" TIMESTAMP(3),
|
|
"validUntil" TIMESTAMP(3),
|
|
"maxRedemptions" INTEGER NOT NULL DEFAULT 1,
|
|
"boundEmail" TEXT,
|
|
"internalNote" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Voucher_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "VoucherRedemption" (
|
|
"id" TEXT NOT NULL,
|
|
"voucherId" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"livemode" BOOLEAN NOT NULL,
|
|
"status" "RedemptionStatus" NOT NULL DEFAULT 'RESERVED',
|
|
"releasedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "VoucherRedemption_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "StripeEvent" (
|
|
"id" TEXT NOT NULL,
|
|
"type" TEXT NOT NULL,
|
|
"livemode" BOOLEAN NOT NULL,
|
|
"status" "StripeEventStatus" NOT NULL DEFAULT 'PROCESSING',
|
|
"error" TEXT,
|
|
"attempts" INTEGER NOT NULL DEFAULT 1,
|
|
"receivedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"processedAt" TIMESTAMP(3),
|
|
|
|
CONSTRAINT "StripeEvent_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "EmailMessage" (
|
|
"id" TEXT NOT NULL,
|
|
"dedupeKey" TEXT NOT NULL,
|
|
"bookingId" TEXT,
|
|
"toAddress" TEXT NOT NULL,
|
|
"subject" TEXT NOT NULL,
|
|
"textBody" TEXT NOT NULL,
|
|
"htmlBody" TEXT NOT NULL,
|
|
"status" "EmailStatus" NOT NULL DEFAULT 'PENDING',
|
|
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
"lastError" TEXT,
|
|
"sentAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "EmailMessage_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "AuditLog" (
|
|
"id" TEXT NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"actorType" "ActorType" NOT NULL,
|
|
"actorId" TEXT,
|
|
"action" TEXT NOT NULL,
|
|
"entityType" TEXT NOT NULL,
|
|
"entityId" TEXT NOT NULL,
|
|
"details" JSONB,
|
|
|
|
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "RateLimitBucket" (
|
|
"key" TEXT NOT NULL,
|
|
"windowStart" TIMESTAMP(3) NOT NULL,
|
|
"count" INTEGER NOT NULL,
|
|
|
|
CONSTRAINT "RateLimitBucket_pkey" PRIMARY KEY ("key")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "user" (
|
|
"id" TEXT NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"email" TEXT NOT NULL,
|
|
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
|
|
"image" TEXT,
|
|
"twoFactorEnabled" BOOLEAN DEFAULT false,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "user_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "session" (
|
|
"id" TEXT NOT NULL,
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"token" TEXT NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
"ipAddress" TEXT,
|
|
"userAgent" TEXT,
|
|
"userId" TEXT NOT NULL,
|
|
|
|
CONSTRAINT "session_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "account" (
|
|
"id" TEXT NOT NULL,
|
|
"accountId" TEXT NOT NULL,
|
|
"providerId" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
"accessToken" TEXT,
|
|
"refreshToken" TEXT,
|
|
"idToken" TEXT,
|
|
"accessTokenExpiresAt" TIMESTAMP(3),
|
|
"refreshTokenExpiresAt" TIMESTAMP(3),
|
|
"scope" TEXT,
|
|
"password" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "account_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "verification" (
|
|
"id" TEXT NOT NULL,
|
|
"identifier" TEXT NOT NULL,
|
|
"value" TEXT NOT NULL,
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "verification_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "twoFactor" (
|
|
"id" TEXT NOT NULL,
|
|
"secret" TEXT NOT NULL,
|
|
"backupCodes" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
|
|
CONSTRAINT "twoFactor_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "rateLimit" (
|
|
"id" TEXT NOT NULL,
|
|
"key" TEXT NOT NULL,
|
|
"count" INTEGER NOT NULL,
|
|
"lastRequest" BIGINT NOT NULL,
|
|
|
|
CONSTRAINT "rateLimit_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Booking_reference_key" ON "Booking"("reference");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Booking_idempotencyKey_key" ON "Booking"("idempotencyKey");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Booking_statusTokenHash_key" ON "Booking"("statusTokenHash");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Booking_stripeCheckoutSessionId_key" ON "Booking"("stripeCheckoutSessionId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Booking_livemode_status_idx" ON "Booking"("livemode", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Booking_email_idx" ON "Booking"("email");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Booking_createdAt_idx" ON "Booking"("createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Installment_stripePaymentIntentId_key" ON "Installment"("stripePaymentIntentId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Installment_stripeChargeId_key" ON "Installment"("stripeChargeId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Installment_checkoutSessionId_key" ON "Installment"("checkoutSessionId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Installment_status_dueAt_idx" ON "Installment"("status", "dueAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Installment_bookingId_seq_key" ON "Installment"("bookingId", "seq");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Refund_stripeRefundId_key" ON "Refund"("stripeRefundId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "SeatReservation_bookingId_key" ON "SeatReservation"("bookingId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "SeatReservation_campId_livemode_status_expiresAt_idx" ON "SeatReservation"("campId", "livemode", "status", "expiresAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Voucher_code_key" ON "Voucher"("code");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "VoucherRedemption_bookingId_key" ON "VoucherRedemption"("bookingId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "VoucherRedemption_voucherId_livemode_status_idx" ON "VoucherRedemption"("voucherId", "livemode", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "EmailMessage_dedupeKey_key" ON "EmailMessage"("dedupeKey");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "EmailMessage_status_createdAt_idx" ON "EmailMessage"("status", "createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_entityType_entityId_idx" ON "AuditLog"("entityType", "entityId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_createdAt_idx" ON "AuditLog"("createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "user_email_key" ON "user"("email");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "session_userId_idx" ON "session"("userId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "account_userId_idx" ON "account"("userId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "verification_identifier_idx" ON "verification"("identifier");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "twoFactor_secret_idx" ON "twoFactor"("secret");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "twoFactor_userId_idx" ON "twoFactor"("userId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "rateLimit_key_key" ON "rateLimit"("key");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_campId_fkey" FOREIGN KEY ("campId") REFERENCES "Camp"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_voucherId_fkey" FOREIGN KEY ("voucherId") REFERENCES "Voucher"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Installment" ADD CONSTRAINT "Installment_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Refund" ADD CONSTRAINT "Refund_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Refund" ADD CONSTRAINT "Refund_installmentId_fkey" FOREIGN KEY ("installmentId") REFERENCES "Installment"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "SeatReservation" ADD CONSTRAINT "SeatReservation_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "SeatReservation" ADD CONSTRAINT "SeatReservation_campId_fkey" FOREIGN KEY ("campId") REFERENCES "Camp"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "VoucherRedemption" ADD CONSTRAINT "VoucherRedemption_voucherId_fkey" FOREIGN KEY ("voucherId") REFERENCES "Voucher"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "VoucherRedemption" ADD CONSTRAINT "VoucherRedemption_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "EmailMessage" ADD CONSTRAINT "EmailMessage_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "session" ADD CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "account" ADD CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "twoFactor" ADD CONSTRAINT "twoFactor_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Unveraenderlicher Preis-Snapshot und Zahlungsplan (Briefing Abschnitt 9).
|
|
-- Der bei Buchung vereinbarte Preis darf auch durch einen Programmfehler oder
|
|
-- einen direkten Datenbankzugriff nicht nachtraeglich veraendert werden.
|
|
-- Eine Vertragsaenderung heisst: stornieren und neu buchen.
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE OR REPLACE FUNCTION booking_snapshot_immutable() RETURNS trigger AS $$
|
|
BEGIN
|
|
IF NEW."reference" IS DISTINCT FROM OLD."reference"
|
|
OR NEW."livemode" IS DISTINCT FROM OLD."livemode"
|
|
OR NEW."idempotencyKey" IS DISTINCT FROM OLD."idempotencyKey"
|
|
OR NEW."pricePhase" IS DISTINCT FROM OLD."pricePhase"
|
|
OR NEW."basePriceCents" IS DISTINCT FROM OLD."basePriceCents"
|
|
OR NEW."phaseDiscountCents" IS DISTINCT FROM OLD."phaseDiscountCents"
|
|
OR NEW."voucherDiscountCents" IS DISTINCT FROM OLD."voucherDiscountCents"
|
|
OR NEW."totalCents" IS DISTINCT FROM OLD."totalCents"
|
|
OR NEW."planType" IS DISTINCT FROM OLD."planType"
|
|
OR NEW."priceSnapshot" IS DISTINCT FROM OLD."priceSnapshot"
|
|
OR NEW."priceLockedUntil" IS DISTINCT FROM OLD."priceLockedUntil"
|
|
OR NEW."voucherId" IS DISTINCT FROM OLD."voucherId"
|
|
THEN
|
|
RAISE EXCEPTION 'Preis-Snapshot der Buchung % ist unveraenderlich', OLD."id";
|
|
END IF;
|
|
RETURN NEW;
|
|
END
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER booking_snapshot_immutable
|
|
BEFORE UPDATE ON "Booking"
|
|
FOR EACH ROW EXECUTE FUNCTION booking_snapshot_immutable();
|
|
|
|
CREATE OR REPLACE FUNCTION installment_plan_immutable() RETURNS trigger AS $$
|
|
BEGIN
|
|
IF NEW."bookingId" IS DISTINCT FROM OLD."bookingId"
|
|
OR NEW."seq" IS DISTINCT FROM OLD."seq"
|
|
OR NEW."amountCents" IS DISTINCT FROM OLD."amountCents"
|
|
OR NEW."dueAt" IS DISTINCT FROM OLD."dueAt"
|
|
THEN
|
|
RAISE EXCEPTION 'Rate % ist Teil des vereinbarten Zahlungsplans und unveraenderlich', OLD."id";
|
|
END IF;
|
|
RETURN NEW;
|
|
END
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER installment_plan_immutable
|
|
BEFORE UPDATE ON "Installment"
|
|
FOR EACH ROW EXECUTE FUNCTION installment_plan_immutable();
|
|
|
|
-- Plausibilitaet auf Datenbankebene.
|
|
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_amounts_check"
|
|
CHECK ("totalCents" > 0 AND "basePriceCents" > 0 AND "phaseDiscountCents" >= 0
|
|
AND "voucherDiscountCents" >= 0 AND "paidCents" >= 0 AND "refundedCents" >= 0
|
|
AND "totalCents" = "basePriceCents" - "phaseDiscountCents" - "voucherDiscountCents");
|
|
ALTER TABLE "Installment" ADD CONSTRAINT "Installment_amount_check"
|
|
CHECK ("amountCents" > 0 AND "seq" BETWEEN 1 AND 3 AND "refundedCents" >= 0);
|
|
ALTER TABLE "Camp" ADD CONSTRAINT "Camp_limits_check"
|
|
CHECK ("capacity" >= 0 AND "stammmodelQuota" >= 0 AND "reservationMinutes" BETWEEN 30 AND 1440
|
|
AND "finalInstallmentLeadDays" >= 0 AND "minInstallmentGapDays" >= 1);
|
|
ALTER TABLE "Voucher" ADD CONSTRAINT "Voucher_limits_check"
|
|
CHECK ("maxRedemptions" >= 1 AND "code" = upper("code"));
|