"""B08 3탭 토적표 길 (PLAN 61-3) — 읽기만, 아무 파일 · DB 에도 쓰지 않음. GET /api/projects/{id}/quantity/earthwork 측점별 횡단 설계 단면적 → 평균단면적법 토적표 단면적 = B06 횡단 설계 저장값(`cross_sections.data.design`) · 노선 = 확정 노선(없으면 최신 노선) · 토량환산계수 = 유토곡선과 같은 `mixed_conversion_factors(quantity_settings)`. """ from __future__ import annotations import asyncio from typing import Any from uuid import UUID from fastapi import APIRouter, HTTPException from B06_Section.B06_Section_Repository import ( get_confirmed_route_context, get_cross_section_designs, get_workflow_route_context, ) from B08_Quantity.B08_Quantity_Engine_Earthwork import StationArea, build_table from B08_Quantity.B08_Quantity_Router_Hydro import _project_root from common_util.common_util_project_settings import mixed_conversion_factors, quantity_settings from config.config_db import get_db_pool router = APIRouter(prefix="/api/projects", tags=["B08 Earthwork"]) @router.get("/{project_id}/quantity/earthwork") async def earthwork_table(project_id: UUID) -> dict[str, Any]: root = await _project_root(project_id) async with get_db_pool().acquire() as connection: context = await get_confirmed_route_context(connection, project_id) confirmed = context is not None context = context or await get_workflow_route_context(connection, project_id) if not context: raise HTTPException(status_code=404, detail="노선이 없습니다 — 노선 · 횡단 설계부터.") route_id = int(context["route_id"]) rows = await get_cross_section_designs(connection, route_id) factors = await asyncio.to_thread(lambda: mixed_conversion_factors(quantity_settings(root))) stations = [StationArea.from_design(row["chainage_m"], row["design"]) for row in rows] return {**build_table(stations, factors), "route_id": route_id, "confirmed": confirmed}