Working-tree checkpoint of in-progress work carried across prior sessions on the feat/crud-rbac branch, committed so it lands on the remote alongside the CI changes. - Operaciones admin panel: apps/api/src/ops (ingest upload, backup / restore / re-import jobs) wired into app.module + RBAC abilities, and the apps/web/src/app/operaciones page. docker-compose gets INGEST_DIR / BACKUP_DIR volumes; .gitignore excludes migration/ingest + backups. - migration/sync.py plus transform_*.py / run_all / config / dbenv / blob_extract adjustments for the additive sync path. - crud/rbac phase-5 web bits: AppShell, api/labels/types libs, globals. - schema.prisma + PLAN/RESUME doc updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
28 lines
1001 B
Python
28 lines
1001 B
Python
"""Shared CLI and SQL helpers for migration modes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
|
|
|
|
def parse_mode() -> tuple[str, bool]:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--env", default="dev")
|
|
parser.add_argument("--sync", action="store_true")
|
|
args = parser.parse_args()
|
|
return args.env, args.sync
|
|
|
|
|
|
def existing_ids(cursor, table: str, key_columns: tuple[str, ...], where: str = "") -> dict[tuple, str]:
|
|
columns = ",".join(("id", *key_columns))
|
|
cursor.execute(f"SELECT {columns} FROM {table} {where}")
|
|
return {tuple(row[1:]): row[0] for row in cursor.fetchall()}
|
|
|
|
|
|
def delete_missing(cursor, table: str, key_columns: tuple[str, ...], seen: set[tuple], where: str) -> int:
|
|
rows = existing_ids(cursor, table, key_columns, where)
|
|
stale = [row_id for key, row_id in rows.items() if key not in seen]
|
|
if stale:
|
|
cursor.executemany(f"DELETE FROM {table} WHERE id=%s", [(row_id,) for row_id in stale])
|
|
return len(stale)
|