58 lines
3.1 KiB
Python
58 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Read-only inventory analysis; writes only explicitly requested reports."""
|
|
import argparse
|
|
from datetime import datetime, timezone
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from migration_workflows import delivery_route, workflow_family
|
|
from prepare_business_acceptance_batch import inventory, plan
|
|
|
|
|
|
def report(state):
|
|
groups = {}
|
|
for row in state["rows"]:
|
|
if not delivery_route(row):
|
|
continue
|
|
key = (row["module"], workflow_family(row))
|
|
group = groups.setdefault(key, {"module": key[0], "workflow": key[1], "total": 0,
|
|
"accepted": 0, "reusableReceipts": 0, "missingCases": [], "unrouted": []})
|
|
record_id = row["id"]
|
|
group["total"] += 1
|
|
group["accepted"] += record_id in state["accepted"]
|
|
receipt = state["receipts"].get(record_id, {})
|
|
group["reusableReceipts"] += receipt.get("status") in {"implementation_ready", "implemented_pending_use"}
|
|
if record_id not in state["covered"].get(row["module"], set()) and record_id not in state["accepted"]:
|
|
group["missingCases"].append(record_id)
|
|
if row.get("implementationStatus", "routed") != "routed":
|
|
group["unrouted"].append(record_id)
|
|
return {"schema": "freecad-web-delivery-inventory/v1", "observedAt": datetime.now(timezone.utc).isoformat(),
|
|
"fullScope": len(state["rows"]), "fullAccepted": len(state["accepted"]),
|
|
"deliverySubset": sum(row["total"] for row in groups.values()),
|
|
"deliveryAccepted": sum(row["accepted"] for row in groups.values()),
|
|
"groups": list(groups.values()), "nextDeliveryAcceptance": plan(state, delivery_only=True),
|
|
"note": "Delivery subset orders work; it never replaces full scope or counts receipts as business acceptance."}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--report-prefix", type=Path)
|
|
args = parser.parse_args()
|
|
result = report(inventory())
|
|
if args.report_prefix:
|
|
args.report_prefix.parent.mkdir(parents=True, exist_ok=True)
|
|
args.report_prefix.with_suffix(".json").write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n")
|
|
lines = ["# Migration Delivery Inventory", "", f"Observed: {result['observedAt']}", "",
|
|
f"Full scope: {result['fullAccepted']}/{result['fullScope']} accepted; priority subset: {result['deliveryAccepted']}/{result['deliverySubset']} accepted.",
|
|
"Receipts are reusable work, not business completion. This subset does not remove desktop/supporting scope.", "",
|
|
"| Module | Workflow | Total | Accepted | Receipts | Missing Cases | Unrouted |", "|---|---|---:|---:|---:|---:|---:|"]
|
|
for row in result["groups"]:
|
|
lines.append(f"| {row['module']} | {row['workflow']} | {row['total']} | {row['accepted']} | {row['reusableReceipts']} | {len(row['missingCases'])} | {len(row['unrouted'])} |")
|
|
args.report_prefix.with_suffix(".md").write_text("\n".join(lines) + "\n")
|
|
print(json.dumps({key: value for key, value in result.items() if key != "groups"}, ensure_ascii=False))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|