#!/usr/bin/env python3 """Continue WP-SD7 draft plans: submit, approve, execute, verify, close.""" from __future__ import annotations import os import sys from pathlib import Path HERE = Path(__file__).resolve().parent sys.path.insert(0, str(HERE)) from run_wp_sd7_api_loop import ( # noqa: E402 TENANTS, approve_until_done, complete_actions, login, request, unwrap, ) from run_wp_sd7_module_readiness import connect # noqa: E402 EVIDENCE = Path(__file__).resolve().parents[4] / "doc" / "plan" / "UAT留证" / "2026-08-17-智慧诊断正式落地" def _message(body) -> str | None: if not isinstance(body, dict): return None inner = unwrap(body) if isinstance(inner, dict) and inner.get("message"): return inner.get("message") return body.get("message") def continue_plan(token: str, plan: dict) -> dict: plan_id = plan.get("id") or plan.get("Id") st, sub = request("POST", "/api/AdoSmartOpsImprovementPlan/submitApproval", {"id": plan_id}, token) submit_msg = _message(sub) submit_failed = st >= 400 or (isinstance(submit_msg, str) and ("失败" in submit_msg or "拒绝" in submit_msg)) if submit_failed: return { "planId": str(plan_id), "planNo": plan.get("planNo") or plan.get("PlanNo"), "module": plan.get("moduleCode") or plan.get("ModuleCode"), "submitHttp": st, "submitMessage": submit_msg, "loopClosed": False, } approve = approve_until_done(token, plan_id) st2, started = request("POST", "/api/AdoSmartOpsImprovementPlan/startExecution", {"id": plan_id}, token) started_body = unwrap(started) or {} actions, plan2 = complete_actions(token, started_body if started_body else plan) st3, ver = request( "POST", "/api/AdoSmartOpsImprovementPlan/submitVerification", {"id": plan_id, "verifyResult": "INSUFFICIENT_DATA", "verifyRemark": "样本不足时与自动评价一致"}, token, ) ver_body = unwrap(ver) or {} st4, closed = request("POST", "/api/AdoSmartOpsImprovementPlan/close", {"id": plan_id}, token) closed_body = unwrap(closed) or {} return { "planId": str(plan_id), "planNo": plan.get("planNo") or plan.get("PlanNo"), "module": plan.get("moduleCode") or plan.get("ModuleCode"), "submitHttp": st, "submitMessage": submit_msg, "approveSteps": [{"http": x.get("http"), "done": x.get("done")} for x in approve], "startHttp": st2, "startStatus": started_body.get("status") or started_body.get("Status"), "verifyHttp": st3, "auto": ver_body.get("autoVerifyResult") or ver_body.get("AutoVerifyResult"), "closeHttp": st4, "closeStatus": closed_body.get("status") or closed_body.get("Status"), "loopClosed": (closed_body.get("status") or closed_body.get("Status")) == "closed", } def main() -> None: password = os.environ.get("AIDOP_UAT_PASSWORD", "").strip() tenant_code = os.environ.get("AIDOP_UAT_TENANT", "A") if not password: raise SystemExit("AIDOP_UAT_PASSWORD required") tenant = TENANTS[tenant_code] token = login(tenant["account"], tenant["tenant_id"], password) conn = connect() try: with conn.cursor() as cur: cur.execute( """ SELECT Id, PlanNo, ModuleCode, Status, RootCause FROM ado_smart_ops_improvement_plan WHERE TenantId=%s AND Status='draft' AND RootCause LIKE '[WP-SD7/%%' ORDER BY ModuleCode, Id DESC """, (int(tenant["tenant_id"]),), ) rows = cur.fetchall() finally: conn.close() latest_by_module = {} skipped_duplicates = [] for row in rows: module = row["ModuleCode"] if module in latest_by_module: skipped_duplicates.append(row["Id"]) continue latest_by_module[module] = { "id": row["Id"], "planNo": row["PlanNo"], "moduleCode": module, "status": row["Status"], } report = { "tenant": tenant_code, "source": "db_latest_draft", "skippedDuplicates": skipped_duplicates, "plans": [], } for module in sorted(latest_by_module): report["plans"].append(continue_plan(token, latest_by_module[module])) out = EVIDENCE / f"07-api-continue-{tenant_code}.json" out.write_text(__import__("json").dumps(report, ensure_ascii=False, indent=2), encoding="utf-8") print(out) print("closed", sum(1 for x in report["plans"] if x.get("loopClosed")), "of", len(report["plans"])) if __name__ == "__main__": main()