Files
FreeCADWasmDev/tools/report_migration_delivery.py
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

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())