run_uat_s8_exception_fact_seed.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #!/usr/bin/env python3
  2. """Seed recent tenant/factory-scoped S8 exception lifecycle facts."""
  3. from __future__ import annotations
  4. import argparse
  5. import json
  6. from datetime import datetime, timedelta
  7. from typing import Any
  8. from apply_sql_file import connect
  9. DEFAULT_TENANT = 838257186181189
  10. DEFAULT_FACTORY = 1
  11. PREFIX = "UAT-S8-A-"
  12. def seed(tenant_id: int, factory_id: int, dry_run: bool) -> dict[str, Any]:
  13. result: dict[str, Any] = {
  14. "tenantId": tenant_id,
  15. "factoryId": factory_id,
  16. "dryRun": dry_run,
  17. "exceptions": 14,
  18. "closed": 10,
  19. }
  20. conn = connect()
  21. try:
  22. conn.begin()
  23. with conn.cursor() as cur:
  24. if not dry_run:
  25. cur.execute(
  26. "DELETE FROM ado_s8_exception WHERE tenant_id=%s AND exception_code LIKE %s",
  27. (tenant_id, f"{PREFIX}%"),
  28. )
  29. now = datetime.now().replace(microsecond=0)
  30. for index in range(14):
  31. seq = index + 1
  32. source_module = f"S{index % 7 + 1}"
  33. created_at = now - timedelta(days=13 - index, hours=6)
  34. is_closed = index < 10
  35. closed_at = created_at + timedelta(hours=2 + index % 8) if is_closed else None
  36. status = "CLOSED" if is_closed else "ASSIGNED"
  37. severity = ("LOW", "MEDIUM", "HIGH", "CRITICAL")[index % 4]
  38. code = f"{PREFIX}{seq:03d}"
  39. cur.execute(
  40. """
  41. INSERT INTO ado_s8_exception
  42. (tenant_id,factory_id,exception_code,title,description,scene_code,source_type,
  43. status,severity,priority_score,priority_level,
  44. occurrence_dept_id,responsible_dept_id,responsible_group_id,
  45. assignee_id,reporter_id,sla_deadline,timeout_flag,
  46. created_at,updated_at,assigned_at,closed_at,is_deleted,
  47. created_by,updated_by,process_node_code,related_object_code,module_code,
  48. exception_type_code,source_payload,dedup_key,last_detected_at,
  49. consecutive_hit_count,consecutive_miss_count,stage_code,rule_mechanism)
  50. VALUES
  51. (%s,%s,%s,%s,%s,'UAT_OPERATIONS','UAT_GENERATOR',
  52. %s,%s,%s,%s,
  53. 1,1,1,1,1,%s,0,
  54. %s,%s,%s,%s,0,
  55. 'UAT_GENERATOR','UAT_GENERATOR','UAT_STAGE',%s,%s,
  56. 'UAT_EXCEPTION',%s,%s,%s,
  57. 1,0,%s,'RULE')
  58. """,
  59. (
  60. tenant_id,
  61. factory_id,
  62. code,
  63. f"UAT 异常事件 {seq:03d}",
  64. "用于验证 S8 异常数量与处理时效正式汇总链",
  65. status,
  66. severity,
  67. 60 + index,
  68. "P1" if severity in ("HIGH", "CRITICAL") else "P2",
  69. created_at + timedelta(hours=12),
  70. created_at,
  71. closed_at or created_at + timedelta(hours=1),
  72. created_at + timedelta(minutes=15),
  73. closed_at,
  74. f"UAT-OBJECT-{seq:03d}",
  75. source_module,
  76. json.dumps({"source": "uat", "seq": seq}, ensure_ascii=False),
  77. code,
  78. closed_at or created_at + timedelta(hours=1),
  79. source_module,
  80. ),
  81. )
  82. if dry_run:
  83. conn.rollback()
  84. else:
  85. conn.commit()
  86. except Exception:
  87. conn.rollback()
  88. raise
  89. finally:
  90. conn.close()
  91. return result
  92. def main() -> None:
  93. parser = argparse.ArgumentParser()
  94. parser.add_argument("--tenant", type=int, default=DEFAULT_TENANT)
  95. parser.add_argument("--factory", type=int, default=DEFAULT_FACTORY)
  96. parser.add_argument("--dry-run", action="store_true")
  97. args = parser.parse_args()
  98. print(json.dumps(seed(args.tenant, args.factory, args.dry_run), ensure_ascii=False, indent=2))
  99. if __name__ == "__main__":
  100. main()