Files
sase.tr/apps/api/drizzle/0022_discount_codes.sql
Semih Yesilyurt 346ebaa0e6
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
feat(billing): indirim kodu sistemi (admin panel + Stripe promo + ödeme)
Admin paneli (admin@sase.tr) kod üretir/takip eder, ödeme sayfası kodu
uygular. Kodlar Stripe Coupon + Promotion Code olarak yaşar (limit/süre/
kullanım Stripe redemption'da enforce edilir); yerel discount_codes aynası
panel listeleme + checkout-anı preview içindir.

- migration 0022_discount_codes + schema (discount_codes)
- DiscountCodesModule: admin CRUD (@Roles admin) + /discount-codes/validate (login)
- StripeService: createPromotion / deactivatePromotion / getPromotionRedemptions
  / previewDiscount + resolvePlanAmount; createCheckoutSession opsiyonel
  discountCode -> discounts[{promotion_code}] + metadata.discount_code; webhook
  gerçek tahsilatı (session.amount_total) yazar + ayna times_redeemed++
- web: /dashboard/admin/discount-codes paneli + ödeme adımı indirim alanı
  (validate preview -> indirimli özet -> kod checkout'a); tr/en çeviriler
- 7 birim test (previewDiscount: % / sabit / süre / geçersiz/pasif/dolu/limit)

Not: 2026-04-22 Stripe API promotionCodes.create `promotion:{type:'coupon'}`
kullanıyor (üst-seviye `coupon` değil). dev'de Stripe key yok -> CREATE dev'de
503; E2E için dev'e Stripe TEST key gerekir.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 03:40:18 +03:00

35 lines
1.5 KiB
SQL

-- Discount codes for checkout promotions. Each row mirrors a Stripe Coupon +
-- Promotion Code; Stripe enforces the redemption cap / expiry at checkout while
-- this table powers the admin panel's listing + usage tracking and lets us
-- preview a code without a per-render Stripe call. Amounts in kuruş (TRY
-- smallest unit), matching plans.price* / payments.amount.
CREATE TABLE IF NOT EXISTS "discount_codes" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"code" varchar(50) NOT NULL,
"stripe_coupon_id" text,
"stripe_promotion_code_id" text,
"discount_type" varchar(12) NOT NULL,
"percent_off" integer,
"amount_off" integer,
"duration" varchar(12) DEFAULT 'once' NOT NULL,
"duration_in_months" integer,
"max_redemptions" integer,
"times_redeemed" integer DEFAULT 0 NOT NULL,
"expires_at" timestamp with time zone,
"is_active" boolean DEFAULT true NOT NULL,
"note" text,
"created_by" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "discount_codes" ADD CONSTRAINT "discount_codes_created_by_users_id_fk"
FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE set null;
EXCEPTION WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE UNIQUE INDEX IF NOT EXISTS "discount_codes_code_idx" ON "discount_codes" USING btree ("code");
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "discount_codes_active_idx" ON "discount_codes" USING btree ("is_active");