feat(B08): 성토/절토를 판정 한 벌로 받아 표준경사 열을 고름 (확정 ⑨ 마무리)
앞서 「성토 열로 잠정」 딱지를 달아 두었던 자리를 채움. 랩탑 메인이 낸 공용 함수 `common_util_structure_face_role(section_mode, side)` 를 **그대로** 부름 — 판정을 두 벌로 짜면 `both_cut` + 「자동」 예외에서 갈리므로 우리 쪽에 다시 안 짬. - 새 저장 키 없음 — 이미 저장되는 `design.section_mode` 와 구조물 `options.side` 만 씀. 라우터가 측점별 단면유형을 모아 넘기고, 구조물은 **가장 가까운 측점** 값을 씀. - ⚠ 못 가르면 `None` 을 **성토로 눅이지 않음** — 종전값 1:0.3 으로 서되 **왜 못 갈랐는지**를 근거 줄에 적음. 임의값이 금액으로 굳으면 안 됨. - 근거 줄에 판정 문구가 그대로 실림 — 「… 1:0.35 · right_cut · 자동(성토 쪽) → 성토면」. 곁들여 — 전면 기울기 칸이 레지스트리에 생겨(`ebdf2988`) 「아직 칸이 없음」 문구와 없는-키 목록에서 뺌. ⚠ 표 밖 값(실무 도면의 S0.7·0.8)은 **막지 않고 그대로** 씀 — 접으면 사용자가 넣은 값이 조용히 다른 값이 됨. 시험으로 잠금. 검증 프로젝트 실측 — 62측점 전부 `right_cut`, 돌쌓기 「자동(성토 쪽)」 → 성토면. 잠정으로 쓰던 열과 **결과는 같고 근거가 값에 생김**. 돌쌓기(메) 21.190㎡(1:0.35) 유지. 시험 747 통과. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,8 @@ from fastapi import APIRouter
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
|
||||
from B06_Section.B06_Section_Repository import get_cross_section_designs
|
||||
from B06_Section.B06_Section_Repository import get_workflow_route_context
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map
|
||||
from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff, load_mapping, summarize
|
||||
@@ -78,6 +80,28 @@ def _collect_structures(
|
||||
return targets, names, sorted(set(skipped))
|
||||
|
||||
|
||||
async def _section_modes(project_id: UUID) -> dict[float, str]:
|
||||
"""측점별 단면유형(`left_cut` 등). 구조물이 **성토면인가 절토면인가**를 가릴 때 쓴다.
|
||||
|
||||
⚠ 새 저장 키를 만들지 않는다 — 이미 저장되는 `design.section_mode` 를 읽기만 한다.
|
||||
못 읽으면 빈 표로 두고, 판정이 「가를 근거 없음」이 되게 한다(성토로 눅이지 않음).
|
||||
"""
|
||||
try:
|
||||
context = await run_with_connection(get_workflow_route_context, project_id)
|
||||
route_id = int((context or {}).get("route_id") or 0)
|
||||
if not route_id:
|
||||
return {}
|
||||
designs = await run_with_connection(get_cross_section_designs, route_id)
|
||||
except Exception:
|
||||
logger.exception("B08 단면유형 조회 실패: project_id=%s", project_id)
|
||||
return {}
|
||||
return {
|
||||
float(item["chainage_m"]): str((item.get("design") or {}).get("section_mode") or "")
|
||||
for item in designs
|
||||
if (item.get("design") or {}).get("section_mode")
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{project_id}/quantity/material-summary")
|
||||
async def get_material_summary(project_id: UUID) -> JSONResponse:
|
||||
"""구조물 원단위와 자재총괄을 **한 응답**으로 낸다.
|
||||
@@ -103,7 +127,7 @@ async def get_material_summary(project_id: UUID) -> JSONResponse:
|
||||
content={"status": "error", "message": "구조물 정본을 읽지 못했습니다."},
|
||||
)
|
||||
|
||||
unit_table = build_unit_table(structures, names)
|
||||
unit_table = build_unit_table(structures, names, await _section_modes(project_id))
|
||||
settings = quantity_settings(project_root)
|
||||
material_table = build_material_table(
|
||||
unit_table,
|
||||
@@ -153,7 +177,7 @@ async def get_handoff(project_id: UUID) -> JSONResponse:
|
||||
)
|
||||
|
||||
structures, names, skipped = _collect_structures(project_root)
|
||||
unit_table = build_unit_table(structures, names)
|
||||
unit_table = build_unit_table(structures, names, await _section_modes(project_id))
|
||||
settings = quantity_settings(project_root)
|
||||
material_table = build_material_table(
|
||||
unit_table, supply_map=settings.get("material_supply") or {}
|
||||
|
||||
Reference in New Issue
Block a user