fix(B08): 실사용자 통과에서 드러난 화면 결함 셋 수정
㉕ 통과(엔진 실행)에서 잡힌 것. - 준비공 사방공 줄에 개발자 키(`soil_guard`)가 그대로 뜨던 자리 수정. 레지스트리 이름을 받아 쓰고, 키는 `type_id` 칸으로만 오감. 문구표에 사방 시설 이름 넷 추가(레지스트리 값 그대로 옮긴 것). - 좌측 「토사」 비율 칸 제거 — 넣어도 버려지던 죽은 칸. 토사 물량은 토적표 값이 그대로 서고, 비율은 암 총량을 갈래로 나눌 때만 쓰임. - 안분 안내 문구를 「암 갈래 입력 합 …」으로 명시. 칸에 100 을 채운 사용자에게 「입력 합 60 %」로 뜨던 자리. - 항목 라벨을 「암 갈래 구성비(%) — 암 총량 기준」으로 바꿈. 시험: 655 passed · 24 skipped (B05 코리도 1건 기존 깨짐, 이 변경과 무관). 사방공 이름 시험 2건 추가, 키를 화면 이름으로 못 박던 옛 시험 1건 정정. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -94,7 +94,7 @@ def _split_by_rock(total: float, source: SummaryInput) -> list[tuple[str, float,
|
||||
given = sum(ratios.values())
|
||||
if given <= 0:
|
||||
return [("암", total, "")]
|
||||
note = "" if abs(given - 100.0) < 1e-9 else f"입력 합 {given:g} % → 100 % 로 안분"
|
||||
note = "" if abs(given - 100.0) < 1e-9 else f"암 갈래 입력 합 {given:g} % → 100 % 로 안분"
|
||||
return [(name, total * ratios[name] / given, note) for name in classes if ratios[name] > 0]
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any, Iterable
|
||||
|
||||
from B08_Quantity.B08_Quantity_Wording import type_label
|
||||
|
||||
#: 사방 시설로 보는 구조물 종류 — **레지스트리의 실제 `type_id` 를 쓴다**(D 그룹 + 흙막이).
|
||||
#: 목록에 없으면 그 노선에 사방공이 **없는** 것이다. 이름을 지어내면 영영 안 걸린다.
|
||||
EROSION_CONTROL_TYPES = frozenset(
|
||||
@@ -200,8 +202,16 @@ def _level_frame_row(slope_rows: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def erosion_rows(structures: Iterable[dict[str, Any]] = ()) -> list[dict[str, Any]]:
|
||||
"""사방공 줄 — 이 노선에 사방 시설이 **있을 때만** 값이 선다."""
|
||||
def erosion_rows(
|
||||
structures: Iterable[dict[str, Any]] = (),
|
||||
names: dict[str, str] | None = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""사방공 줄 — 이 노선에 사방 시설이 **있을 때만** 값이 선다.
|
||||
|
||||
⚠ 줄 이름은 **레지스트리 이름**을 쓴다 — `type_id` 를 그대로 적으면 화면에
|
||||
`soil_guard` 같은 개발자 키가 뜬다(B08 ㉑ 과 같은 병). `names` 가 없으면
|
||||
문구표가 받아 주고, 그것도 없으면 키를 보이되 **지어내지는 않는다**.
|
||||
"""
|
||||
found = sorted(
|
||||
{
|
||||
str(item.get("type_id"))
|
||||
@@ -224,7 +234,8 @@ def erosion_rows(structures: Iterable[dict[str, Any]] = ()) -> list[dict[str, An
|
||||
return [
|
||||
{
|
||||
"group": "사방공",
|
||||
"item": type_id,
|
||||
"item": type_label(type_id, names),
|
||||
"type_id": type_id,
|
||||
"unit": "개소",
|
||||
"amount": None,
|
||||
"status": STATUS_PENDING,
|
||||
@@ -240,10 +251,11 @@ def build_table(
|
||||
structures: Iterable[dict[str, Any]] = (),
|
||||
slope_rows: Iterable[dict[str, Any]] = (),
|
||||
topsoil_thickness_m: float | None = None,
|
||||
names: dict[str, str] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""화면·인계가 그대로 쓰는 모양. **못 서는 줄도 목록에 남는다.**"""
|
||||
rows = preparation_rows(slope_totals, slope_rows, topsoil_thickness_m) + erosion_rows(
|
||||
structures
|
||||
structures, names
|
||||
)
|
||||
return {
|
||||
"columns": ["구분", "공종", "단위", "수량", "상태", "사유"],
|
||||
|
||||
@@ -22,6 +22,7 @@ from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
|
||||
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
|
||||
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map
|
||||
from B06_Section.B06_Section_Repository import (
|
||||
get_cross_section_designs,
|
||||
get_longitudinal_section,
|
||||
@@ -99,11 +100,13 @@ async def get_earthwork_table(project_id: UUID, route_id: int) -> JSONResponse:
|
||||
)
|
||||
)
|
||||
# 준비공·사방공 — 못 서는 줄도 사유와 함께 남긴다(빈 표는 「빠뜨림」과 구별이 안 됨).
|
||||
structures = await _route_structures(project_id)
|
||||
table["preparation"] = build_preparation_table(
|
||||
slope.get("totals") or {},
|
||||
await _route_structures(project_id),
|
||||
structures,
|
||||
slope.get("rows") or [],
|
||||
settings.get("topsoil_thickness_m"),
|
||||
{type_id: definition.name for type_id, definition in structure_type_map().items()},
|
||||
)
|
||||
method, method_is_default = concrete_placing_method(settings)
|
||||
# ⚠ 금액에 바로 걸리는 값이라 「기본값으로 돌고 있음」을 응답에 실어 화면이 띄우게 한다.
|
||||
|
||||
@@ -218,7 +218,10 @@ function buildQuantitySidePanel(
|
||||
panel.append(field(L("B08_Quantity_Side_RockRatios"), ""));
|
||||
for (const name of classes) {
|
||||
// 「암」은 비율을 넣으면 사라지는 되메움 줄이라 비율 칸을 두지 않는다.
|
||||
if (name !== "암") {
|
||||
// 「토사」도 비율 칸을 두지 않는다 — 토사 물량은 토적표의 흙깎기 값이 그대로 서고,
|
||||
// 비율은 **암 총량을 갈래로 나누는 데만** 쓰인다(집계 엔진 `_rock_split`).
|
||||
// 칸을 두면 넣은 값이 조용히 버려져 「입력 합 60 %」 같은 안내가 뜬다(2026-09-08 통과).
|
||||
if (name !== "암" && name !== "토사") {
|
||||
panel.append(
|
||||
numberField(name, draft.rock_ratios_pct[name] ?? 0, (value) => {
|
||||
draft.rock_ratios_pct[name] = value;
|
||||
|
||||
@@ -30,6 +30,11 @@ TYPE_LABELS = {
|
||||
"ford_pavement": "물넘이포장",
|
||||
"ford_bridge": "세월교",
|
||||
"box_culvert": "BOX암거",
|
||||
# 사방 시설 — 레지스트리 이름 그대로 옮긴 것(2026-09-08 확인). 지어낸 이름 아님.
|
||||
"erosion_check": "골막이",
|
||||
"bed_sill": "바닥막이",
|
||||
"check_dam_small": "소형사방댐(복합형)",
|
||||
"revetment": "기슭막이",
|
||||
}
|
||||
|
||||
#: 저장 제원 칸의 사람 이름 + **어디서 채우는지**. 키 이름을 화면에 내보내지 않기 위한 표.
|
||||
|
||||
@@ -657,7 +657,10 @@ export const ui_locales_b2 = {
|
||||
B08_Quantity_Ratio_SeedCut: ["초류종자살포(절토면)", "Seed spray (cut)"],
|
||||
B08_Quantity_Ratio_TreeRemoval: ["지장목제거", "Obstacle removal"],
|
||||
B08_Quantity_Side_RockSet: ["암 갈래 세트", "Rock class set"],
|
||||
B08_Quantity_Side_RockRatios: ["지반 구성비(%)", "Ground composition (%)"],
|
||||
B08_Quantity_Side_RockRatios: [
|
||||
"암 갈래 구성비(%) — 암 총량 기준",
|
||||
"Rock class split (%) of rock volume",
|
||||
],
|
||||
B08_Quantity_Btn_Save: ["저장", "Save"],
|
||||
B08_Quantity_Save_Success: ["산출 조건을 저장했습니다.", "Calculation settings saved."],
|
||||
B08_Quantity_Save_Failed: ["산출 조건을 저장하지 못했습니다.", "Failed to save the settings."],
|
||||
|
||||
Reference in New Issue
Block a user