"""워크플로우 단계별 상태 테이블 생성 및 기존 프로젝트 백필 마이그레이션 스크립트.""" import asyncio import sys from pathlib import Path import aiomysql # Import DB config sys.path.append(str(Path(__file__).parent.parent)) from common_util.common_util_workflow_state import STAGE_KEYS from config.config_db import DB_HOST, DB_NAME, DB_PASSWORD, DB_PORT, DB_USER async def migrate(): print("Database connecting...") connection = await aiomysql.connect( host=DB_HOST, port=DB_PORT, user=DB_USER, password=DB_PASSWORD, db=DB_NAME, charset="utf8mb4", ) try: async with connection.cursor() as cursor: # 1. 테이블 생성 sql_file = Path(__file__).parent / "006_workflow_state.sql" print(f"Executing schema from {sql_file.name}...") sql_content = sql_file.read_text(encoding="utf-8") # Remove USE aislo_db; to avoid issues if any, but splitting is fine statements = [stmt.strip() for stmt in sql_content.split(";") if stmt.strip()] for stmt in statements: await cursor.execute(stmt) print("Table project_workflow_stages created successfully.") await connection.commit() # 2. 기존 프로젝트 백필 async with connection.cursor(aiomysql.DictCursor) as cursor: await cursor.execute("SELECT id, status FROM projects") projects = await cursor.fetchall() print(f"Found {len(projects)} existing projects to backfill.") for proj in projects: proj_id = proj["id"] status = proj["status"] or "NEW" print(f"Backfilling project {proj_id} with status '{status}'...") # 각 단계별 상태 매핑 결정 # 0=FILE_INPUT, 1=SURFACE, 2=ROUTE, 3=PROFILE_CROSS # 4=DESIGN_DETAIL, 5=QUANTITY, 6=ESTIMATION states = ["NOT_STARTED"] * 7 if status == "NEW": pass elif status in ("FILE_INPUT_PROCESSING", "FILE_INPUT_FAILED"): states[0] = "IN_PROGRESS" if "PROCESSING" in status else "FAILED" elif status == "FILE_UPLOADED": states[0] = "COMPLETE" elif "WF1" in status: states[0] = "COMPLETE" if "ANALYZING" in status: states[1] = "IN_PROGRESS" elif "FAILED" in status: states[1] = "FAILED" else: states[1] = "COMPLETE" elif "WF2" in status: states[0] = "COMPLETE" states[1] = "COMPLETE" if "ANALYZING" in status: states[2] = "IN_PROGRESS" elif "FAILED" in status: states[2] = "FAILED" else: states[2] = "COMPLETE" elif "WF3" in status: states[0] = "COMPLETE" states[1] = "COMPLETE" states[2] = "COMPLETE" if "ANALYZING" in status: states[3] = "IN_PROGRESS" elif "FAILED" in status: states[3] = "FAILED" else: states[3] = "COMPLETE" elif "WF4" in status: states[0] = "COMPLETE" states[1] = "COMPLETE" states[2] = "COMPLETE" states[3] = "COMPLETE" if "ANALYZING" in status: states[4] = "IN_PROGRESS" elif "FAILED" in status: states[4] = "FAILED" else: states[4] = "COMPLETE" elif "WF5" in status: states[0] = "COMPLETE" states[1] = "COMPLETE" states[2] = "COMPLETE" states[3] = "COMPLETE" states[4] = "COMPLETE" if "ANALYZING" in status: states[5] = "IN_PROGRESS" elif "FAILED" in status: states[5] = "FAILED" else: states[5] = "COMPLETE" elif "WF6" in status: states[0] = "COMPLETE" states[1] = "COMPLETE" states[2] = "COMPLETE" states[3] = "COMPLETE" states[4] = "COMPLETE" states[5] = "COMPLETE" if "ANALYZING" in status: states[6] = "IN_PROGRESS" elif "FAILED" in status: states[6] = "FAILED" else: states[6] = "COMPLETE" elif status in ("DONE", "CONFIRMED"): for i in range(7): states[i] = "COMPLETE" # DB에 단계별 정보 입력 (ON DUPLICATE KEY UPDATE로 덮어쓰기 안전) for stage_no, stage_key in enumerate(STAGE_KEYS): state = states[stage_no] progress = 100 if state == "COMPLETE" else 0 await cursor.execute( """ INSERT INTO project_workflow_stages ( project_id, stage_no, stage_key, state, progress_percent ) VALUES (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE state = %s, progress_percent = %s """, (proj_id, stage_no, stage_key, state, progress, state, progress), ) await connection.commit() print("Backfill complete!") return True except Exception as e: print(f"Migration / Backfill failed: {e}") await connection.rollback() return False finally: connection.close() if __name__ == "__main__": success = asyncio.run(migrate()) sys.exit(0 if success else 1)