70 lines
2.2 KiB
Python
70 lines
2.2 KiB
Python
|
|
#!/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 <id> [<id> ...]
|
||
|
|
|
||
|
|
# 2. For real
|
||
|
|
python3 scripts/pb-delete-fixed-costs.py <id> [<id> ...] --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.")
|