fleettickets/run_migrations.py
david kiania 4631cc6382 feat: fleettickets — INC/CRQ ticket ingestion, geocoding + read-schema
Standalone module extracted from the tracksolid repo (was migrations 21-23 +
tools/import_tickets.py). Owns the `tickets` schema in the shared tracksolid_db.

- migrations/01_tickets_schema.sql: consolidated final-state schema (tickets.inc/
  crq raw-jsonb-first, geo_clusters + geo_locations gazetteers, geom trigger,
  reporting.fn_tickets_for_map)
- import_tickets.py: rustfs bucket ingest + cluster/location geocoding
  (LocationIQ/OpenCage, viewbox-bounded + cluster-distance guard)
- run_migrations.py, shared.py (self-contained), pyproject, .env.example, README

The DB stays in tracksolid_db; dashboard_api keeps serving /webhook/tickets; the
Tickets map stays a FleetOps tab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 20:13:50 +03:00

56 lines
1.8 KiB
Python

"""
run_migrations.py — fleettickets · apply SQL migrations in order.
Applies migrations/*.sql (lexical order) against DATABASE_URL, tracking applied
files in tickets.schema_migrations. Migrations are idempotent, so re-running is
safe. Run: `python run_migrations.py`.
"""
from __future__ import annotations
import glob
import os
import psycopg2
MIG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "migrations")
def main() -> None:
dsn = os.environ.get("DATABASE_URL")
if not dsn:
raise SystemExit("DATABASE_URL is not set")
conn = psycopg2.connect(dsn)
conn.autocommit = False
try:
with conn.cursor() as cur:
cur.execute("CREATE SCHEMA IF NOT EXISTS tickets")
cur.execute(
"CREATE TABLE IF NOT EXISTS tickets.schema_migrations "
"(filename text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now())"
)
conn.commit()
cur.execute("SELECT filename FROM tickets.schema_migrations")
applied = {r[0] for r in cur.fetchall()}
for path in sorted(glob.glob(os.path.join(MIG_DIR, "*.sql"))):
fn = os.path.basename(path)
if fn in applied:
print(f" skip {fn}")
continue
print(f" apply {fn}")
with open(path, encoding="utf-8") as f:
cur.execute(f.read())
cur.execute(
"INSERT INTO tickets.schema_migrations (filename) VALUES (%s) "
"ON CONFLICT DO NOTHING",
(fn,),
)
conn.commit()
print("migrations up to date.")
finally:
conn.close()
if __name__ == "__main__":
main()