Files
Aislo/B08_Quantity/B08_Quantity_Router_Earthwork.py
T
eomsangdonandClaude Opus 5.5 e857819d2e feat(B08): 토공 탭 — 보조 탭 넷(토공집계표 · 토적표 · 평균운반거리 · 종방향 무대운반거리) · 토적표 견본 칸 (PLAN 69-2 · 69-3)
- 토적표 칸 = 사용자 견본 32칸 · 보정량계 = 절토 보정량만 · 면 계열(면고르기 · 지장목제거 · 제근 · 노면정리) 거리 = B07 횡단 수량 함수 · 면적 = 앞뒤 평균 × 측점 거리
- 토공집계표 · 운반 시트 = 거창 실무 워크북 같은 이름 시트 칸 · 식 · Q · L = 저장된 유토곡선 배분(서버 · 읽기만)
- 시험 test_69_b08_earthwork_tabs.py · 보정량계 시험 정함대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
2026-10-06 23:05:36 +09:00

60 lines
2.6 KiB
Python

"""B08 토공 탭 길 (PLAN 61-3 · 69-2) — 읽기만, 아무 파일 · DB 에도 쓰지 않음.
GET /api/projects/{id}/quantity/earthwork
토적표 + 토공집계표 + 평균운반거리 · 종방향 무대운반거리
운반 Q · L = 종단 레코드에 저장된 유토곡선 배분(`mass_haul.haul_plan`) — B07 토적도와 같은 정본.
단면적 = 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_longitudinal_section,
get_workflow_route_context,
)
from B08_Quantity.B08_Quantity_Engine_Earthwork import StationArea, build_table
from B08_Quantity.B08_Quantity_Engine_Earthwork_Summary import haul_lists, summary_rows
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)
section = await get_longitudinal_section(connection, project_id, 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]
table = build_table(stations, factors)
mass_haul = ((section or {}).get("data") or {}).get("mass_haul") or {}
haul = haul_lists(mass_haul.get("haul_plan"))
return {
**table,
"summary": summary_rows(table["totals"], haul),
"haul": haul,
"haul_saved": bool(mass_haul.get("haul_plan")),
"route_id": route_id,
"confirmed": confirmed,
}