trustbond-backend / backend /scripts /reset_operational_data.py
samuelyitakubayo's picture
Ok
12bf79b
Raw
History Blame Contribute Delete
5.12 kB
#!/usr/bin/env python3
"""
Reset operational data and seed fresh demo records.
PRESERVED (not deleted):
police_users, incident_types, locations, stations, station_coverage_cells,
local_leaders, local_leader_coverage_locations, system_config,
special_assignment_units
CLEARED:
reports (+ evidence, ML predictions, assignments, case links),
cases, hotspots, devices, notifications, audit_logs, user_sessions,
MFA/password-reset codes, deployment_decisions
Then seeds at least 300 new reports (default), devices, cases, and recomputes hotspots.
Usage (from backend directory or container):
python scripts/reset_operational_data.py --yes
python scripts/reset_operational_data.py --yes --count 500
python scripts/reset_operational_data.py --dry-run
python scripts/reset_operational_data.py --clear-only --yes
"""
from __future__ import annotations
import argparse
import logging
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.core.hotspot_auto import create_hotspots_from_reports
from app.core.operational_data_reset import (
TABLES_PRESERVED,
TABLES_TO_CLEAR,
clear_operational_data,
count_operational_rows,
)
from app.database import SessionLocal
from simulate_reports import seed_operational_data
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logger = logging.getLogger("reset_operational_data")
def _print_plan(counts: dict[str, int]) -> None:
total = sum(counts.values())
logger.info("Tables to CLEAR (%d rows total):", total)
for table in TABLES_TO_CLEAR:
n = counts.get(table, 0)
if n:
logger.info(" - %s: %d", table, n)
logger.info("Tables PRESERVED: %s", ", ".join(TABLES_PRESERVED))
def recompute_hotspots(db) -> int:
"""Build hotspot clusters from all non-rejected seeded reports."""
return create_hotspots_from_reports(
db,
analyze_all_reports=True,
time_window_hours=8760,
)
def main() -> int:
parser = argparse.ArgumentParser(description="Clear operational data and reseed TrustBond demo records.")
parser.add_argument(
"--count",
type=int,
default=300,
help="Number of reports to seed (minimum 300). Default: 300",
)
parser.add_argument(
"--devices",
type=int,
default=None,
help="Number of devices to create (default: max(50, count/5))",
)
parser.add_argument(
"--days",
type=int,
default=45,
help="Spread report dates over this many days (default: 45)",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Show row counts that would be deleted; do not change data",
)
parser.add_argument(
"--clear-only",
action="store_true",
help="Only clear operational tables; do not seed or recompute hotspots",
)
parser.add_argument(
"--seed-only",
action="store_true",
help="Skip clear step; only seed and recompute hotspots",
)
parser.add_argument(
"--skip-hotspots",
action="store_true",
help="Do not run hotspot DBSCAN recompute after seeding",
)
parser.add_argument(
"--yes",
"-y",
action="store_true",
help="Confirm destructive reset without interactive prompt",
)
args = parser.parse_args()
if args.count < 300:
parser.error("--count must be at least 300")
db = SessionLocal()
try:
counts = count_operational_rows(db)
_print_plan(counts)
if args.dry_run:
logger.info("Dry run — no changes made.")
return 0
if not args.seed_only:
if not args.yes:
answer = input(
"\nThis will DELETE all operational data listed above. Type RESET to continue: "
).strip()
if answer != "RESET":
logger.info("Aborted.")
return 1
cleared = clear_operational_data(db)
logger.info("Cleared rows: %s", cleared)
if args.clear_only:
logger.info("Clear-only complete.")
return 0
stats = seed_operational_data(
db,
num_reports=args.count,
num_devices=args.devices,
days_back=args.days,
)
logger.info("Seeded: %s", stats)
hotspots_created = 0
if not args.skip_hotspots:
hotspots_created = recompute_hotspots(db)
logger.info("Hotspots recomputed: %d clusters", hotspots_created)
logger.info(
"Done. Preserved reference data; seeded %d reports, %d devices, %d cases, %d hotspots.",
stats["reports"],
stats["devices"],
stats["cases"],
hotspots_created,
)
return 0
except Exception:
db.rollback()
logger.exception("Reset failed")
return 1
finally:
db.close()
if __name__ == "__main__":
raise SystemExit(main())