#!/usr/bin/env python3 """Delete specific fixed_costs rows by id, after showing what they are. Written for clearing the three smoke-test rows that were inflating the P&G run rate. Deliberately explicit: it prints each row, writes a JSON backup of them, and does nothing at all unless you pass --confirm. # 1. Dry run — prints the rows and writes the backup, deletes nothing python3 scripts/pb-delete-fixed-costs.py [ ...] # 2. For real python3 scripts/pb-delete-fixed-costs.py [ ...] --confirm The backup is a plain JSON array of the full records, so a row can be recreated by POSTing it back to /api/collections/fixed_costs/records. """ import json import sys from datetime import datetime from pb_env import http, superuser_token args = [a for a in sys.argv[1:] if not a.startswith("--")] confirm = "--confirm" in sys.argv if not args: sys.exit("Pass one or more fixed_costs record ids. See --help in the docstring.") TOKEN = superuser_token() rows = [] for rid in args: code, rec = http("GET", f"/api/collections/fixed_costs/records/{rid}", token=TOKEN) if code != 200: sys.exit(f" ✗ could not read {rid}: {code} {rec}") rows.append(rec) print(f"\n{len(rows)} row(s) targeted:\n") total = 0.0 for r in rows: cost = r.get("cost") or 0 total += cost print( f" {r['id']} {str(r.get('date_logged',''))[:10]} " f"R {cost:>12,.2f} {r.get('description','')}" ) print(f"\n total: R {total:,.2f}") stamp = datetime.now().strftime("%Y%m%d-%H%M%S") backup = f"/tmp/fixed-costs-deleted-{stamp}.json" with open(backup, "w") as f: json.dump(rows, f, indent=2) print(f" backup written to {backup}") if not confirm: print("\nDry run — nothing deleted. Re-run with --confirm to delete.") sys.exit(0) print() for r in rows: code, resp = http( "DELETE", f"/api/collections/fixed_costs/records/{r['id']}", token=TOKEN ) if code in (200, 204): print(f" ✓ deleted {r['id']} {r.get('description','')}") else: print(f" ✗ FAILED {r['id']}: {code} {resp}", file=sys.stderr) print("\nDone. Reload the Overview — the P&G figure should drop accordingly.")