"""B01 대시보드 홈 API (PLAN 547) — 프로젝트 카드 요약 · 역할별 홈.""" from typing import Any import aiomysql from fastapi import APIRouter, Depends, Query from common_util.common_util_auth import verify_session from config.config_db import get_db_pool from .B01_Dashboard_Summary import project_summaries router = APIRouter(prefix="/api/dashboard", tags=["B01_Dashboard"]) SUMMARY_LIMIT = 200 async def visible_project_ids(session: dict[str, Any]) -> list[str]: """보이는 프로젝트(최근 수정 순) — 시스템 관리자 = 전부 · 회사 = 회사 전체 · 없으면 내 것.""" where, args = "p.deleted_at IS NULL", () if session["role"] != "SYSTEM_ADMIN": if session.get("company_id"): where, args = where + " AND p.company_id = %s", (int(session["company_id"]),) else: where, args = where + " AND p.user_id = %s", (int(session["user_id"]),) pool = get_db_pool() async with pool.acquire() as connection, connection.cursor(aiomysql.DictCursor) as cursor: await cursor.execute( f"SELECT p.id FROM projects p WHERE {where} " "ORDER BY p.updated_at DESC, p.created_at DESC", args, ) return [str(r["id"]) for r in await cursor.fetchall()] @router.get("/projects/summary") async def projects_summary( ids: str | None = Query(None, max_length=8000, description="쉼표로 이은 프로젝트 id"), session: dict[str, Any] = Depends(verify_session), ): """카드 요약 — ids 없으면 보이는 프로젝트 전부(최근 수정 순) · 안 보이는 id 는 빠짐.""" visible = await visible_project_ids(session) if ids: allowed = set(visible) wanted = dict.fromkeys(pid.strip() for pid in ids.split(",")) visible = [pid for pid in wanted if pid in allowed] return {"status": "success", "projects": await project_summaries(visible[:SUMMARY_LIMIT])}