Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
77 lines
4.2 KiB
Python
77 lines
4.2 KiB
Python
"""초류종자살포 5-24-1·2 뿜어붙이기 — 2026-09-15 브레인 판정 ①②′④ (③ 물탱크는 `test_b09_water_tank_operating`).
|
||
|
||
산림 5-24 표(㎡당): 종자 0.025 · 복합비료 0.1 · 화이버 0.18 · 합성접착제 0.1 · 색소 0.002 kg ·
|
||
종자살포기 2,500-3,000ℓ 0.0024h · 트럭 4.5ton 0.0024h · 물탱크 5,500ℓ 0.0036h · 조경공 0.0007 · 보통인부 0.0004
|
||
[주]⑤ 「건설공사 표준품셈 공통부문 4-1-2 초류종자 살포」 참조
|
||
① 트럭 4.5ton → 덤프트럭 4.5(0602-0045) — 카탈로그에 「트럭」 없음(원문 애매) · 거창 실무 「덤프트럭 (4.5Ton)」
|
||
②′ 종자살포기 → 취부기 11.94㎾(7750-0016) · **손료만** — 원문 규격은 ℓ(탱크 용량) · 건설 4-1-3 「취부기 11.94kW」 ·
|
||
거창 실무 「종자살포기 : 취부기(녹생토)」 · 8-4 운전경비표에 7750 줄 없음(원문 없음) · 거창도 손료 20,295 만
|
||
디젤엔진 11.19㎾ 는 거창만 따로 세움 — 산림 5-24 · 건설 4-1-3 표 둘 다에 없어 안 넣고 어긋남만 기록
|
||
④ 종자 규격 후보 넷(생태복원형 초본·목본 · 초본류 · 목본류) — 화약류 길: 「자재 단가」 칸 · 넣은 쪽 하나가 붙음
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from decimal import ROUND_FLOOR, Decimal
|
||
|
||
from B09_Estimation.B09_Estimation_KnownGaps import known_gap_note
|
||
from B09_Estimation.B09_Estimation_MachineExpenseSheet import machine_expense_sheets
|
||
from B09_Estimation.B09_Estimation_UnitPrice import cached_build
|
||
|
||
CODES = ("FP-05-24-01", "FP-05-24-02")
|
||
SEEDS = ("AR-M-f89c57d4", "AR-M-d52b8fc1", "AR-M-8f852514", "AR-M-e39ee36e")
|
||
|
||
|
||
def _rows(book, code: str) -> dict[str, Decimal]:
|
||
return {r.ref_code: r.quantity for r in book.details[f"B-{code}"]}
|
||
|
||
|
||
def test_트럭은_덤프트럭_종자살포기는_취부기_물탱크까지_표_시간대로() -> None:
|
||
build = cached_build()
|
||
for code in CODES:
|
||
rows = _rows(build.book, code)
|
||
assert rows["X-0602-0045"] == Decimal("0.0024"), rows
|
||
assert rows["X-7750-0016"] == Decimal("0.0024"), rows
|
||
assert rows["X-7204-0055"] == Decimal("0.0036"), rows
|
||
left = " ".join(build.unattached.get(code, []))
|
||
assert "트 럭" not in left and "종자살포기" not in left, left
|
||
assert code not in build.component_gaps, build.component_gaps.get(code)
|
||
|
||
|
||
def test_취부기는_손료만으로_서고_사유가_붙음() -> None:
|
||
build = cached_build()
|
||
assert not any(m.startswith("7750-0016") for m in build.incomplete_machines)
|
||
money = build.book.resolve("X-7750-0016")
|
||
assert money.material == 0 and money.labor == 0
|
||
assert (
|
||
money.expense.quantize(Decimal(1), rounding=ROUND_FLOOR) == 20295
|
||
) # 거창 46,603,000 × 4,355
|
||
notes = " ".join(r.note for r in build.book.details["X-7750-0016"])
|
||
assert "8-4" in notes and "거창" in notes, notes
|
||
sheet = next(s for s in machine_expense_sheets(build) if s["code"] == "X-7750-0016")
|
||
assert sheet["gaps"] == [] and "8-4" in sheet["attachment_note"], sheet
|
||
|
||
|
||
def test_종자는_후보_넷_칸_넣은_하나만_붙고_둘이면_사유() -> None:
|
||
none = cached_build()
|
||
for code in CODES:
|
||
assert all(code in none.material_uses.get(seed, []) for seed in SEEDS)
|
||
left = " ".join(none.unattached.get(code, []))
|
||
assert "종자 — 규격 미정" in left and "종 자" not in left, left
|
||
one = cached_build(material_prices=(("AR-M-8f852514", "20000", "견적"),))
|
||
assert _rows(one.book, "FP-05-24-01")["AR-M-8f852514"] == Decimal("0.025")
|
||
assert "종자" not in " ".join(one.unattached.get("FP-05-24-01", []))
|
||
two = cached_build(
|
||
material_prices=(("AR-M-8f852514", "20000", "견적"), ("AR-M-e39ee36e", "30000", "견적"))
|
||
)
|
||
rows = _rows(two.book, "FP-05-24-01")
|
||
assert "AR-M-8f852514" not in rows and "AR-M-e39ee36e" not in rows
|
||
assert "하나만" in " ".join(two.unattached.get("FP-05-24-01", []))
|
||
|
||
|
||
def test_사유는_어긋남을_나란히() -> None:
|
||
note = known_gap_note("FP-05-24-01")
|
||
for word in ("트럭", "덤프트럭", "ℓ", "취부기", "손료만", "디젤엔진"):
|
||
assert word in note, (word, note)
|
||
assert known_gap_note("FP-05-24-02") == note
|