feat: (upgrade) implement per-passenger fare class upgrade with configurable policies

This commit is contained in:
Abubeker Yasin
2026-09-02 16:18:36 +03:00
parent 31121db07b
commit e914aaeb53
34 changed files with 2705 additions and 34 deletions

View File

@@ -0,0 +1,65 @@
-- Fare-class upgrade (policy US-17). One policy row per fare class — fare classes map 1:1 onto
-- coach types — plus a per-request table recording the frozen quote.
--
-- Structure only, and additive/idempotent. Policy data lives in prisma/seed.ts.
-- CreateTable
CREATE TABLE IF NOT EXISTS "passenger"."UpgradePolicy" (
"id" TEXT NOT NULL,
"coachTypeId" TEXT NOT NULL,
"rank" INTEGER NOT NULL DEFAULT 0,
"feePercent" INTEGER NOT NULL DEFAULT 0,
"feeMinMinor" INTEGER NOT NULL DEFAULT 0,
"feeWaived" BOOLEAN NOT NULL DEFAULT false,
"isUpgradable" BOOLEAN NOT NULL DEFAULT true,
"isTargetable" BOOLEAN NOT NULL DEFAULT true,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "UpgradePolicy_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX IF NOT EXISTS "UpgradePolicy_coachTypeId_key" ON "passenger"."UpgradePolicy"("coachTypeId");
DO $$ BEGIN
ALTER TABLE "passenger"."UpgradePolicy"
ADD CONSTRAINT "UpgradePolicy_coachTypeId_fkey" FOREIGN KEY ("coachTypeId")
REFERENCES "passenger"."CoachType"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
-- CreateTable
CREATE TABLE IF NOT EXISTS "passenger"."BookingUpgrade" (
"id" TEXT NOT NULL,
"bookingId" TEXT NOT NULL,
"leg" INTEGER NOT NULL DEFAULT 1,
"status" TEXT NOT NULL DEFAULT 'PENDING_PAYMENT',
"requestedBy" TEXT NOT NULL,
"scheduleId" TEXT NOT NULL,
"items" JSONB NOT NULL,
"holdId" TEXT,
"oldFareMinor" INTEGER NOT NULL,
"newFareMinor" INTEGER NOT NULL,
"fareDifferenceMinor" INTEGER NOT NULL,
"feeMinor" INTEGER NOT NULL,
"amountDueMinor" INTEGER NOT NULL,
"supplementaryChargeId" TEXT,
"expiresAt" TIMESTAMP(3),
"appliedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "BookingUpgrade_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX IF NOT EXISTS "BookingUpgrade_supplementaryChargeId_key" ON "passenger"."BookingUpgrade"("supplementaryChargeId");
CREATE INDEX IF NOT EXISTS "BookingUpgrade_bookingId_status_idx" ON "passenger"."BookingUpgrade"("bookingId", "status");
DO $$ BEGIN
ALTER TABLE "passenger"."BookingUpgrade"
ADD CONSTRAINT "BookingUpgrade_bookingId_fkey" FOREIGN KEY ("bookingId")
REFERENCES "passenger"."Booking"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
-- No data seeding here on purpose. This migration creates structure only; the ladder itself is
-- business policy and is seeded separately by `seedUpgradePolicies` in prisma/seed.ts
-- (`pnpm prisma:seed`), so a production deploy never silently writes fare rules nobody approved.