_tmp_sd7_continue_drafts.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/env python3
  2. """Continue WP-SD7 draft plans: submit, approve, execute, verify, close."""
  3. from __future__ import annotations
  4. import os
  5. import sys
  6. from pathlib import Path
  7. HERE = Path(__file__).resolve().parent
  8. sys.path.insert(0, str(HERE))
  9. from run_wp_sd7_api_loop import ( # noqa: E402
  10. TENANTS,
  11. approve_until_done,
  12. complete_actions,
  13. login,
  14. request,
  15. unwrap,
  16. )
  17. from run_wp_sd7_module_readiness import connect # noqa: E402
  18. EVIDENCE = Path(__file__).resolve().parents[4] / "doc" / "plan" / "UAT留证" / "2026-08-17-智慧诊断正式落地"
  19. def _message(body) -> str | None:
  20. if not isinstance(body, dict):
  21. return None
  22. inner = unwrap(body)
  23. if isinstance(inner, dict) and inner.get("message"):
  24. return inner.get("message")
  25. return body.get("message")
  26. def continue_plan(token: str, plan: dict) -> dict:
  27. plan_id = plan.get("id") or plan.get("Id")
  28. st, sub = request("POST", "/api/AdoSmartOpsImprovementPlan/submitApproval", {"id": plan_id}, token)
  29. submit_msg = _message(sub)
  30. submit_failed = st >= 400 or (isinstance(submit_msg, str) and ("失败" in submit_msg or "拒绝" in submit_msg))
  31. if submit_failed:
  32. return {
  33. "planId": str(plan_id),
  34. "planNo": plan.get("planNo") or plan.get("PlanNo"),
  35. "module": plan.get("moduleCode") or plan.get("ModuleCode"),
  36. "submitHttp": st,
  37. "submitMessage": submit_msg,
  38. "loopClosed": False,
  39. }
  40. approve = approve_until_done(token, plan_id)
  41. st2, started = request("POST", "/api/AdoSmartOpsImprovementPlan/startExecution", {"id": plan_id}, token)
  42. started_body = unwrap(started) or {}
  43. actions, plan2 = complete_actions(token, started_body if started_body else plan)
  44. st3, ver = request(
  45. "POST",
  46. "/api/AdoSmartOpsImprovementPlan/submitVerification",
  47. {"id": plan_id, "verifyResult": "INSUFFICIENT_DATA", "verifyRemark": "样本不足时与自动评价一致"},
  48. token,
  49. )
  50. ver_body = unwrap(ver) or {}
  51. st4, closed = request("POST", "/api/AdoSmartOpsImprovementPlan/close", {"id": plan_id}, token)
  52. closed_body = unwrap(closed) or {}
  53. return {
  54. "planId": str(plan_id),
  55. "planNo": plan.get("planNo") or plan.get("PlanNo"),
  56. "module": plan.get("moduleCode") or plan.get("ModuleCode"),
  57. "submitHttp": st,
  58. "submitMessage": submit_msg,
  59. "approveSteps": [{"http": x.get("http"), "done": x.get("done")} for x in approve],
  60. "startHttp": st2,
  61. "startStatus": started_body.get("status") or started_body.get("Status"),
  62. "verifyHttp": st3,
  63. "auto": ver_body.get("autoVerifyResult") or ver_body.get("AutoVerifyResult"),
  64. "closeHttp": st4,
  65. "closeStatus": closed_body.get("status") or closed_body.get("Status"),
  66. "loopClosed": (closed_body.get("status") or closed_body.get("Status")) == "closed",
  67. }
  68. def main() -> None:
  69. password = os.environ.get("AIDOP_UAT_PASSWORD", "").strip()
  70. tenant_code = os.environ.get("AIDOP_UAT_TENANT", "A")
  71. if not password:
  72. raise SystemExit("AIDOP_UAT_PASSWORD required")
  73. tenant = TENANTS[tenant_code]
  74. token = login(tenant["account"], tenant["tenant_id"], password)
  75. conn = connect()
  76. try:
  77. with conn.cursor() as cur:
  78. cur.execute(
  79. """
  80. SELECT Id, PlanNo, ModuleCode, Status, RootCause
  81. FROM ado_smart_ops_improvement_plan
  82. WHERE TenantId=%s AND Status='draft' AND RootCause LIKE '[WP-SD7/%%'
  83. ORDER BY ModuleCode, Id DESC
  84. """,
  85. (int(tenant["tenant_id"]),),
  86. )
  87. rows = cur.fetchall()
  88. finally:
  89. conn.close()
  90. latest_by_module = {}
  91. skipped_duplicates = []
  92. for row in rows:
  93. module = row["ModuleCode"]
  94. if module in latest_by_module:
  95. skipped_duplicates.append(row["Id"])
  96. continue
  97. latest_by_module[module] = {
  98. "id": row["Id"],
  99. "planNo": row["PlanNo"],
  100. "moduleCode": module,
  101. "status": row["Status"],
  102. }
  103. report = {
  104. "tenant": tenant_code,
  105. "source": "db_latest_draft",
  106. "skippedDuplicates": skipped_duplicates,
  107. "plans": [],
  108. }
  109. for module in sorted(latest_by_module):
  110. report["plans"].append(continue_plan(token, latest_by_module[module]))
  111. out = EVIDENCE / f"07-api-continue-{tenant_code}.json"
  112. out.write_text(__import__("json").dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
  113. print(out)
  114. print("closed", sum(1 for x in report["plans"] if x.get("loopClosed")), "of", len(report["plans"]))
  115. if __name__ == "__main__":
  116. main()