working dev environment

This commit is contained in:
2026-06-18 08:29:03 +00:00
parent 6fc00b8ce9
commit 57b882128d
21 changed files with 200 additions and 210 deletions
+68 -10
View File
@@ -1,14 +1,18 @@
"""
Seed script: populates the database with station data.
Idempotent — safe to run multiple times. Uses get-or-create (upsert) for each entity.
Usage:
DATABASE_URL=postgresql://... python -m app.seed
(or from the repo root: cd backend && python seed.py)
KMTN_DATABASE_URL=... python seed.py
(run from the backend/ directory)
"""
import asyncio
from datetime import date
from sqlalchemy import select
from app.database import async_session
from app.models import Program, Event, DonationTier
@@ -90,29 +94,83 @@ TIERS: list[dict] = [
]
# ── Helpers ────────────────────────────────────────────────
async def _upsert_program(session, data: dict) -> None:
"""Get-or-create a program matched on (day_of_week, time)."""
existing = await session.execute(
select(Program).where(
Program.day_of_week == data["day_of_week"],
Program.time == data["time"],
)
)
program = existing.scalar_one_or_none()
if program:
for key, value in data.items():
setattr(program, key, value)
else:
session.add(Program(**data))
async def _upsert_event(session, data: dict) -> None:
"""Get-or-create an event matched on (date, title)."""
existing = await session.execute(
select(Event).where(
Event.date == data["date"],
Event.title == data["title"],
)
)
event = existing.scalar_one_or_none()
if event:
for key, value in data.items():
setattr(event, key, value)
else:
session.add(Event(**data, active=True))
async def _upsert_tier(session, data: dict) -> None:
"""Get-or-create a donation tier matched on name."""
existing = await session.execute(
select(DonationTier).where(DonationTier.name == data["name"])
)
tier = existing.scalar_one_or_none()
if tier:
for key, value in data.items():
setattr(tier, key, value)
else:
session.add(DonationTier(**data))
# ── Main ──────────────────────────────────────────────────
async def seed():
async def seed() -> None:
"""Populate the database with station data (idempotent)."""
async with async_session() as session:
# Programs
for data in PROGRAMS:
session.add(Program(**data))
await _upsert_program(session, data)
await session.commit()
print(f" ✓ Seeded {len(PROGRAMS)} programs")
# Events
for data in EVENTS:
event = Event(**data, active=True)
session.add(event)
await _upsert_event(session, data)
await session.commit()
print(f" ✓ Seeded {len(EVENTS)} events")
# Tiers
for data in TIERS:
session.add(DonationTier(**data))
await _upsert_tier(session, data)
await session.commit()
print(f" ✓ Seeded {len(TIERS)} donation tiers")
async def truncate_all() -> None:
"""Remove all seed data from the database."""
async with async_session() as session:
await session.execute(Program.__table__.delete())
await session.execute(Event.__table__.delete())
await session.execute(DonationTier.__table__.delete())
await session.commit()
print(" ✓ Truncated all tables")
if __name__ == "__main__":
asyncio.run(seed())