diff --git a/control/seed.py b/control/seed.py index 87f1e8e..40d1024 100644 --- a/control/seed.py +++ b/control/seed.py @@ -4,11 +4,35 @@ control/seed.py Idempotent seeding of the baseline plans (upsert by `code`). Mirrors the plan-tier matrix in MULTI_TENANT_PLAN.md §6. Safe to re-run — re-running updates existing plan rows in place rather than creating duplicates. + +stripe_price_id values are read from the environment at seed time so this +file never contains live keys. Set before running: + + export STRIPE_PRICE_STARTER=price_xxx + export STRIPE_PRICE_PRO=price_yyy + export STRIPE_PRICE_ENTERPRISE=price_zzz + +Rows where the env var is absent keep their current stripe_price_id value +(existing rows) or get NULL (new rows) — no data is lost on a partial run. """ +import os + +from dotenv import load_dotenv +load_dotenv() + from control.base import control_session from control.models import Plan +# Read Stripe price IDs from the environment; fall back to None so the +# seeder is safe to run even when Stripe is not yet configured. +_STRIPE_PRICES = { + 'free': None, # Free plan is never sold via Stripe + 'starter': os.environ.get('STRIPE_PRICE_STARTER'), + 'pro': os.environ.get('STRIPE_PRICE_PRO'), + 'enterprise': os.environ.get('STRIPE_PRICE_ENTERPRISE'), +} + PLAN_DEFS = [ dict(code='free', name='Free', max_users=3, max_facilities=2, @@ -38,17 +62,27 @@ PLAN_DEFS = [ def seed_plans(): - """Upsert baseline plans. Returns (created_count, updated_count).""" + """Upsert baseline plans. Returns (created_count, updated_count). + + stripe_price_id is only written when the corresponding env var is set — + existing values are never overwritten with None on a partial run. + """ created, updated = 0, 0 with control_session() as s: for d in PLAN_DEFS: plan = s.query(Plan).filter_by(code=d['code']).first() + price_id = _STRIPE_PRICES.get(d['code']) if plan is None: - s.add(Plan(**d)) + plan = Plan(**d) + plan.stripe_price_id = price_id # None is fine for new rows + s.add(plan) created += 1 else: for k, v in d.items(): setattr(plan, k, v) + # Only overwrite stripe_price_id when the env var is present. + if price_id is not None: + plan.stripe_price_id = price_id updated += 1 return created, updated @@ -56,3 +90,6 @@ def seed_plans(): if __name__ == '__main__': c, u = seed_plans() print(f'Plans seeded — created={c} updated={u}') + for code, pid in _STRIPE_PRICES.items(): + label = pid or '(not set — env var absent)' + print(f' {code}: stripe_price_id = {label}')