QuranFlow Admin · meeting prep
The 5 decisions we'd like to walk through together. Each question is standalone — you don't need any other context to answer it. Each has a recommended default (what we'd do if no decision is made), but the plan is to discuss them in the meeting rather than route them as email.
U2 is BLOCKING — we need the answer to write the migration regardless of whether the meeting happens. The other four have defaults that will ship if no input is given.
QuestionOn the Payment Overview page, should "Active" include students whose payment is currently failing (Past Due)? Or should Past Due be its own separate category?
Recommended defaultCombine them. Show one merged "Active" count that includes Active + Past Due + Trialing. Past Due students still appear separately in the alert section below the metrics.
Why we're askingThis decision changes the headline number on 5 different screens (Payment Overview, Active Enrollment, Dashboard alert tile, Promoted Students, Family Plans badge, Composition reporting).
QuestionHow many days before a scholarship renewal date should the system show "Renewing Soon" (early heads-up) versus "Action Needed" (urgent)?
Recommended default30 days = Renewing Soon · 7 days = Action Needed.
Why we're askingDifferent days suit different review cadences — if you review weekly, 30/7 works; if you review monthly, you might want 45/14 or 60/14. Stored as settings so trivial to change later.
QuestionConfirm the coupon strategy for Family Plans and Scholarships: 6 fixed Stripe coupons (one per discount tier: 0%, 10%, 20%, 30%, 40%, 50%), swapped on each subscription instead of creating one coupon per family member. A new boolean column coupons.auto_managed flags these system-owned coupons. A nightly orphan-sweep cron cleans up unreferenced ones.
Recommended defaultShip as designed (per-percentage-shared, deterministic IDs, auto-managed flag, nightly sweep).
Why we're askingEngineering shape decision that affects how the production code handles coupon lifecycle. Replaces the legacy "one Stripe coupon per family member" pattern (which grew linearly with users).
QuestionIn the existing production database, do coupons and couponsToken create one Stripe coupon per master coupons row (Shape A), or one Stripe coupon per couponsToken row (Shape B)?
DefaultNONE. We can't write the migration without this answer.
Why we're askingThe migration script needs to know how the legacy data maps to the new shape. Only your team knows because your team built the legacy system; we have no access to the production PHP.
QuestionConfirm the schema design for the billing_alerts table that handles which subsystem (Stripe webhook vs nightly cron) is the authoritative writer for each alert row. Specifically:
billing_alert_source_enum with values webhook | cronidempotency_key text UNIQUE constraint (so duplicate writes are silently rejected)event_created_at timestamptz column (so stale events can be detected and ignored)stripe_invoice_id text indexed column (for fast lookup)billing_webhook_dead_letter table (for events that fail processing)billing_alerts_archive table with 90-day retentionRecommended defaultShip as designed. Three concrete race conditions (duplicate writes, stale resurrection, retry duplication) are all closed.
Why we're askingEngineering design decision. Three race conditions are documented in the source doc; the proposed schema closes all three.