Files
Aislo/B01_Dashboard/B01_Dashboard_Router_Home.py
T
eomsangdonandClaude Opus 5.5 8b1b286e04 feat(B01): 프로젝트 카드 요약 함수 · API — 단계 · 썸네일 선 · 담당 · 멈춘 날 · 연장 · 측점 · 구조물 (PLAN 547-1)
- B01_Dashboard_Summary.project_summaries(ids) — 쿼리 다섯 번(개수 무관) · 넣은 차례 · 없는 값은 칸 뺌
- 썸네일 = 최신 노선 GeoJSON 중심선 100 점 안쪽 · 0~1 칸(가로세로 비 유지 · y 아래로)
- GET /api/dashboard/projects/summary?ids= — 보이는 프로젝트만(시스템 관리자 전부 · 회사 · 내 것)
- 실측 21 개 0.14 s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 18:01:25 +09:00

48 lines
1.9 KiB
Python

"""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])}