wip: ops admin panel + migration sync + crud/rbac phase-5 snapshot
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>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user