This commit is contained in:
2026-07-10 19:01:33 +09:00
parent e3d66e717c
commit b98affbf99
22 changed files with 1681 additions and 752 deletions
+88 -3
View File
@@ -80,6 +80,67 @@ async def update_user_profile(user_id: int, data: dict[str, Any]) -> dict[str, A
return await get_dashboard_me(user_id)
async def get_workflow_states_for_projects(
cursor: aiomysql.DictCursor, project_ids: list[str]
) -> dict[str, dict[str, Any]]:
if not project_ids:
return {}
format_strings = ",".join(["%s"] * len(project_ids))
await cursor.execute(
f"""
SELECT project_id, stage_no, stage_key, state, progress_percent, params, message,
DATE_FORMAT(started_at, '%%Y-%%m-%%dT%%H:%%i:%%s') AS started_at,
DATE_FORMAT(completed_at, '%%Y-%%m-%%dT%%H:%%i:%%s') AS completed_at
FROM project_workflow_stages
WHERE project_id IN ({format_strings})
ORDER BY project_id, stage_no ASC
""",
tuple(project_ids),
)
rows = await cursor.fetchall()
project_stages = {}
for r in rows:
pid = r["project_id"]
if pid not in project_stages:
project_stages[pid] = []
params_val = None
if r.get("params"):
try:
params_val = (
json.loads(r["params"]) if isinstance(r["params"], str) else r["params"]
)
except Exception:
params_val = r["params"]
project_stages[pid].append(
{
"stage_no": r["stage_no"],
"stage_key": r["stage_key"],
"state": r["state"],
"progress_percent": r["progress_percent"],
"params": params_val,
"message": r["message"],
"started_at": r["started_at"],
"completed_at": r["completed_at"],
}
)
result = {}
for pid in project_ids:
stages = project_stages.get(pid, [])
current_stage = 0
for stage in stages:
if stage["stage_no"] == 0:
continue
prev_stage = stages[stage["stage_no"] - 1]
if prev_stage["state"] == "COMPLETE":
current_stage = stage["stage_no"]
else:
break
result[pid] = {"current_stage": current_stage, "stages": stages}
return result
async def list_user_projects(user_id: int) -> list[dict[str, Any]]:
pool = get_db_pool()
async with pool.acquire() as connection, connection.cursor(aiomysql.DictCursor) as cursor:
@@ -90,7 +151,15 @@ async def list_user_projects(user_id: int) -> list[dict[str, Any]]:
ORDER BY updated_at DESC, created_at DESC""",
(user_id,),
)
return [_project_row(row) for row in await cursor.fetchall()]
rows = await cursor.fetchall()
pids = [r["id"] for r in rows]
states = await get_workflow_states_for_projects(cursor, pids)
result = []
for r in rows:
p_row = _project_row(r)
p_row["workflow_state"] = states.get(r["id"], {"current_stage": 0, "stages": []})
result.append(p_row)
return result
async def list_company_projects(company_id: int) -> list[dict[str, Any]]:
@@ -105,7 +174,15 @@ async def list_company_projects(company_id: int) -> list[dict[str, Any]]:
ORDER BY p.updated_at DESC, p.created_at DESC""",
(company_id,),
)
return [_project_row(row) for row in await cursor.fetchall()]
rows = await cursor.fetchall()
pids = [r["id"] for r in rows]
states = await get_workflow_states_for_projects(cursor, pids)
result = []
for r in rows:
p_row = _project_row(r)
p_row["workflow_state"] = states.get(r["id"], {"current_stage": 0, "stages": []})
result.append(p_row)
return result
async def list_all_projects() -> list[dict[str, Any]]:
@@ -119,7 +196,15 @@ async def list_all_projects() -> list[dict[str, Any]]:
WHERE p.deleted_at IS NULL
ORDER BY p.updated_at DESC, p.created_at DESC"""
)
return [_project_row(row) for row in await cursor.fetchall()]
rows = await cursor.fetchall()
pids = [r["id"] for r in rows]
states = await get_workflow_states_for_projects(cursor, pids)
result = []
for r in rows:
p_row = _project_row(r)
p_row["workflow_state"] = states.get(r["id"], {"current_stage": 0, "stages": []})
result.append(p_row)
return result
async def get_project(project_id: str) -> dict[str, Any] | None: