fix(b08·b09): 내역 표시 흠 묶음 — 운반 줄 장비 키 · 덤프 거리 14자리 · 규격 갈래 두 번(㉰㉵)

- 운반 줄 이름: 「dozer 운반」 → 「불도저 운반」(매핑 master_name) · 「dump_truck 운반」 → 「덤프 운반」 · 「free_haul 운반」 → 「무대(종방향유용토)」(토공집계 이름)
- 덤프 규격·호표 규격 L: 「L=137.13474461798225m」 → 「L=137.13m」 — 보이기만 둘째 자리 · 호표 열쇠·운반 식은 받은 거리 그대로
- 규격 칸 갈래: 이미 적힌 갈래는 한 번만(`spec_with_variant` · 숫자 경계) — 「Ø800 800」 → 「Ø800」
- 936be972 내역: 흠 줄 6 → 0 · 금액 불변 161,514,889

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
2026-09-15 01:34:52 +09:00
co-authored by Claude Opus 5
parent 490cfe1d08
commit 7dd5dda98b
7 changed files with 88 additions and 14 deletions
@@ -9,6 +9,7 @@
from __future__ import annotations
import re
from decimal import Decimal
from B09_Estimation.B09_Estimation_BillOfQuantities import (
@@ -25,6 +26,7 @@ from B09_Estimation.B09_Estimation_BillOfQuantities import (
from B09_Estimation.B09_Estimation_MachineProductivity_Dump import (
DUMP_PARENT,
LOADING_EQUIPMENT,
distance_label,
dump_child_for,
dump_title_code,
loading_title_code,
@@ -40,6 +42,13 @@ from B09_Estimation.B09_Estimation_UnitPrice import (
)
def spec_with_variant(spec: str, variant: str) -> str:
"""규격에 갈래를 한 번만 — 적힌 갈래(Ø800·리핑암)는 안 붙임(㉵) · 규격 글로 시작하면 갈음."""
if re.search(rf"(?<![\d.]){re.escape(variant)}(?![\d.])", spec): # 숫자 경계: Ø1800 ≠ 800
return spec
return variant if variant.startswith(spec) else f"{spec} {variant}"
def bill_line(unit: Money3, quantity) -> Money3:
"""내역 줄 금액 — **성분마다** `절사(수량 × 성분 단가)`, 줄 합계는 셋의 합(명세 7장).
@@ -362,7 +371,7 @@ def _leaf_row(
return row
price_code = wanted
if not loading:
row.spec = f"{row.spec} L={item.haul_distance_m}m".strip()
row.spec = f"{row.spec} {distance_label(item.haul_distance_m)}".strip()
if price_code not in unit_prices.book.titles:
# B08 은 **의미**(어느 공종·어느 제원)만 보내고 갈래 키는 우리가 만든다.
# 못 맞추면 후보를 보이는 길로 내려간다 — 가까운 갈래를 임의로 고르지 않는다.
@@ -374,8 +383,7 @@ def _leaf_row(
default = unit_prices.default_variants.get(node.code)
if picked is not None:
price_code = picked
variant = str(item.variant_value) # 규격 글로 시작하는 갈래는 한 번만(면고르기)
row.spec = variant if variant.startswith(row.spec) else f"{row.spec} {variant}"
row.spec = spec_with_variant(row.spec, str(item.variant_value))
elif default is not None:
# 표에 없거나 안 준 암질(풍화암·암) — **원문이 정한 갈래**로만 선다(9-4-1 [주]① 평균).
price_code = f"{price_code}#{default[0]}"
@@ -170,6 +170,15 @@ def dump_title_code(work_item_code: str, distance_m: Decimal) -> str:
return f"B-{work_item_code}#L{distance_m.normalize():f}m"
def distance_label(distance_m: Decimal) -> str:
"""보이는 운반거리 「L=137.13m」 — 소수 둘째 자리까지(㉰ 2026-09-14 · 가중평균이 14자리로 떴음).
⚠ **보이기만** 줄임 — 호표 열쇠(`dump_title_code`)·운반 식은 받은 거리 그대로 씀.
"""
shown = Decimal(distance_m).quantize(Decimal("0.01")).normalize()
return f"L={shown:f}m"
def attach_dump_hauls(build: Any, master: dict[str, Any], distances_m: tuple[Decimal, ...]) -> None:
"""거리마다 덤프 운반 일위대가를 세운다 — X(덤프트럭 15ton) → D → B.
@@ -226,7 +235,7 @@ def attach_dump_hauls(build: Any, master: dict[str, Any], distances_m: tuple[Dec
kind=PriceKind.UNIT_PRICE,
name=f"{names.get(DUMP_PARENT) or '덤프운반'} "
f"{names.get(code) or material.label}",
spec=f"L={distance.normalize():f}m",
spec=distance_label(distance),
unit="㎥",
)
)