Files
cma-management/backend/scripts/migrate_verify_fix_20260830.py
T

85 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""verify-engine-fix-20260830 DB 迁移脚本
1. kpi_values.entity_id 回填:kpi_id → kpi_definitions.entity_id(现有 67 条 NULL
2. action_plans.status 'done' → 'completed'(枚举修正;当前 0 条,防御性执行)
执行前先 SELECT 预览影响行数,再执行 UPDATE,最后回查验证。
用法: venv/bin/python3 scripts/migrate_verify_fix_20260830.py
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from sqlalchemy import text
from app.database import get_engine
def main():
engine = get_engine()
with engine.connect() as conn:
# ── 1. 预览 ──
preview_null = conn.execute(text(
"SELECT COUNT(*) AS cnt FROM kpi_values kv "
"LEFT JOIN kpi_definitions kd ON kv.kpi_id = kd.id "
"WHERE kv.entity_id IS NULL AND kd.entity_id IS NOT NULL"
)).fetchone()
preview_orphan = conn.execute(text(
"SELECT COUNT(*) AS cnt FROM kpi_values kv "
"LEFT JOIN kpi_definitions kd ON kv.kpi_id = kd.id "
"WHERE kv.entity_id IS NULL AND kd.id IS NULL"
)).fetchone()
preview_done = conn.execute(text(
"SELECT COUNT(*) AS cnt FROM action_plans WHERE status = 'done'"
)).fetchone()
print(f"[预览] 可回填(entity_id NULL 且 kpi 存在): {preview_null.cnt}")
print(f"[预览] 无法回填(kpi 不存在): {preview_orphan.cnt}")
print(f"[预览] action_plans status='done': {preview_done.cnt}")
# ── 2. 执行回填 ──
r = conn.execute(text(
"UPDATE kpi_values kv "
"JOIN kpi_definitions kd ON kv.kpi_id = kd.id "
"SET kv.entity_id = kd.entity_id "
"WHERE kv.entity_id IS NULL AND kd.entity_id IS NOT NULL"
))
print(f"[执行] kpi_values entity_id 回填 {r.rowcount} 条")
# 无法关联的孤儿行(kpi 不存在)→ 置默认 entity_id=1 并留 remark
r2 = conn.execute(text(
"UPDATE kpi_values kv "
"LEFT JOIN kpi_definitions kd ON kv.kpi_id = kd.id "
"SET kv.entity_id = 1, kv.remark = CONCAT(COALESCE(kv.remark, ''), '; verify-fix-20260830 孤儿行默认entity_id=1') "
"WHERE kv.entity_id IS NULL AND kd.id IS NULL"
))
if r2.rowcount:
print(f"[执行] 孤儿行置默认 entity_id=1: {r2.rowcount} 条")
else:
print("[执行] 无孤儿行需处理")
# ── 3. status done → completed ──
r3 = conn.execute(text(
"UPDATE action_plans SET status = 'completed' WHERE status = 'done'"
))
print(f"[执行] action_plans status done→completed: {r3.rowcount} 条")
conn.commit()
# ── 4. 验证 ──
after_null = conn.execute(text(
"SELECT COUNT(*) AS cnt FROM kpi_values WHERE entity_id IS NULL"
)).fetchone()
after_done = conn.execute(text(
"SELECT COUNT(*) AS cnt FROM action_plans WHERE status = 'done'"
)).fetchone()
print(f"[验证] kpi_values entity_id IS NULL 残留: {after_null.cnt}(目标 0")
print(f"[验证] action_plans status='done' 残留: {after_done.cnt}(目标 0")
if after_null.cnt != 0:
print("[结果] ❌ 回填不彻底,请人工检查")
sys.exit(1)
print("[结果] ✅ 迁移完成")
if __name__ == "__main__":
main()