배정 프로젝트: 뿌리뽑기 줄만 사유가 「하위 후보 6건」→「입력이 필요합니다」 · 소림·0.7 넣으면 55원/㎡ × 17,698㎡ = 973,414(되돌림) · 전체 1935 통과 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
71 lines
3.5 KiB
Python
71 lines
3.5 KiB
Python
"""9-21 제근 굴착기 크기 칸 — 2026-09-14 브레인 판정(산출 조건 칸 · 제안 0.7㎥ · 비면 사유).
|
|
|
|
9-21 품은 굴착기 0.2·0.7 × 임목축적 등급(소·중·밀) 여섯 갈래인데 B08 은 등급만 보내 B09 가 못 고름.
|
|
⇒ 매핑 `variant_template` 이 크기·등급 두 입력을 한 값(「0.7·소림」)으로 엮고, 범위 별칭(FP-09-21)이
|
|
그 값을 B09 갈래(「굴착기(무한궤도) 0.7 · 소」)로 잇는다 — 갈래 키 표기는 별칭표 한 곳만 앎.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from B08_Quantity.B08_Quantity_Engine_EarthworkSummary import ( # noqa: E402
|
|
ROOT_REMOVAL_EXCAVATOR_SIZES,
|
|
ROOT_REMOVAL_EXCAVATOR_SUGGESTED,
|
|
)
|
|
from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff # noqa: E402
|
|
from B08_Quantity.B08_Quantity_Engine_Preparation import STAND_VOLUME_CLASSES # noqa: E402
|
|
|
|
|
|
def _row(**inputs) -> dict:
|
|
summary = {"rows": [{"group": "지장목제거", "item": "뿌리뽑기", "spec": "", "unit": "㎡",
|
|
"amount": 1000.0, "application_ratio_pct": 100.0}]} # fmt: skip
|
|
rows = build_handoff(summary_table=summary, **inputs)["work_items"]
|
|
return next(r for r in rows if r["work_item_code"] == "FP-09-21")
|
|
|
|
|
|
def test_크기와_등급을_한_갈래_값으로_엮어_내역_금액이_섬() -> None:
|
|
from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill
|
|
|
|
inputs = {"stand_volume_class": "소림", "root_removal_excavator_m3": "0.7"}
|
|
row = _row(**inputs)
|
|
assert row["variant_value"] == "0.7·소림" and not row["blocked_kind"], row
|
|
summary = {"rows": [{"group": "지장목제거", "item": "뿌리뽑기", "spec": "", "unit": "㎡",
|
|
"amount": 1000.0}]} # fmt: skip
|
|
bill = build_bill(build_handoff(summary_table=summary, **inputs))
|
|
line = next(r for r in bill.rows if r.code == "FP-09-21")
|
|
assert line.price_code == "B-FP-09-21#굴착기(무한궤도)0.7·소", line.note
|
|
assert line.amount_krw and int(line.amount_krw) > 0, line.note
|
|
|
|
|
|
def test_크기가_비면_금액_없이_입력_사유_등급은_그대로_실음() -> None:
|
|
row = _row(stand_volume_class="중림")
|
|
assert row["variant_value"] == "중림" # 판정 Ⓑ — 등급 갈래를 잃지 않음
|
|
assert row["blocked_kind"] == "input_missing" and "굴착기" in row["blocked_reason"], row
|
|
assert _row()["blocked_kind"] == "input_missing"
|
|
|
|
|
|
def test_선택지는_마스터_갈래_키의_크기_제안은_0_7_근거_10_12_1() -> None:
|
|
from B09_Estimation.B09_Estimation_ResourceAxis import load_work_item_master
|
|
|
|
node = next(
|
|
n for n in load_work_item_master()["work_items"] if n["work_item_code"] == "FP-09-21"
|
|
)
|
|
sizes = {key.split(")")[1].split("·")[0].strip() for key in node["variant_keys"]}
|
|
assert sizes == set(ROOT_REMOVAL_EXCAVATOR_SIZES)
|
|
value, basis = ROOT_REMOVAL_EXCAVATOR_SUGGESTED
|
|
assert value == "0.7" and "10-12-1" in basis
|
|
# 크기 × 등급 여섯이 모두 별칭으로 B09 갈래에 닿음
|
|
from common_util.common_util_aliases import alias_target, load_aliases
|
|
|
|
rows = load_aliases("variant")
|
|
for size in ROOT_REMOVAL_EXCAVATOR_SIZES:
|
|
for grade in STAND_VOLUME_CLASSES:
|
|
target = alias_target(rows, f"{size}·{grade}", "FP-09-21", "2026-01-01")
|
|
assert target in node["variant_keys"], (size, grade, target)
|