- 시공능력 Q 로 선 기계 줄(굴착기·도자·직접 작업량·다짐·암 잎)은 D(단가산출)에 달고 B 는 D 를 수량 1 로 부름 - 종전 PriceBasis 의 껍데기 D(D → B) 걷음 — 「단산 N」은 D 를 품은 줄에만(갈래 줄도 실제 단가 코드로 찾음) - 자원 집계가 B→B·B→D 참조를 끝까지 풀어 기계 사용료에 닿음(종전 조용히 버림) · 모르는 종류는 드러냄 - 조합 16% 바꿔 달기·공종 근거 문구가 D 줄도 봄 - 전후 대조: B·X 420 제목 금액 전부 같음 · 검증 프로젝트 내역 본체 122,924,846 그대로 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
98 lines
4.3 KiB
Python
98 lines
4.3 KiB
Python
"""성토·성토면다짐에 단가가 서는가 (2026-09-09 밤).
|
|
|
|
**왜 안 서고 있었나** — 둘 다 원문에는 값이 다 있는데 서로 다른 까닭으로 막혀 있었다.
|
|
|
|
9-16-1 노체포설 계수표(K·f·E·㎝)는 붙었는데 **기종이 [주]에만 있어** 못 골랐음
|
|
→ 시공능력 공식이 안 돌아 단가가 통째로 안 섬
|
|
9-17-1 비탈면 다짐 **표가 한 장도 없음** — 값이 절 제목에 있음(「A = 77.7 ㎡/시간」)
|
|
→ 표만 보는 조립이 그 공종을 아예 안 봄
|
|
|
|
⚠ 그동안 인계에는 물량이 그대로 실려 **성토 13,150.2㎥ · 성토면다짐 12,350.3㎡ 가 금액 없이**
|
|
내역에 서 있었다. 그래서 아래 셋을 못으로 박는다.
|
|
|
|
① 두 공종에 단가가 선다 · ② 단위가 원문과 같다(㎥·㎡) · ③ 근거가 줄에 남는다
|
|
④ 부착 콤팩터 손료가 함께 붙는다 — 이름이 빈 카탈로그 줄이라 놓치던 자리
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from decimal import Decimal
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from B09_Estimation.B09_Estimation_FactorChoices import MACHINE_CHOICES # noqa: E402
|
|
from B09_Estimation.B09_Estimation_MachineProductivity_Reference import ( # noqa: E402
|
|
SOURCE_TEXT_CAPACITY,
|
|
direct_capacity_rows,
|
|
)
|
|
from B09_Estimation.B09_Estimation_UnitPrice import ( # noqa: E402
|
|
cached_build,
|
|
load_work_item_master,
|
|
)
|
|
|
|
|
|
def _build():
|
|
return cached_build()
|
|
|
|
|
|
def test_노체포설에_단가가_선다() -> None:
|
|
build = _build()
|
|
title = build.book.titles.get("B-FP-09-16-01")
|
|
assert title is not None, "노체포설 일위대가가 안 섰습니다"
|
|
assert title.unit == "㎥"
|
|
assert build.book.resolve("B-FP-09-16-01").total > 0
|
|
|
|
|
|
def test_노체포설_기종은_주에서_왔음을_적는다() -> None:
|
|
"""⚠ 기본값을 어디서 가져왔는지 안 적으면 임의 값과 구별이 안 된다."""
|
|
entry = MACHINE_CHOICES["FP-09-16-01"]
|
|
assert entry["default_code"] == "0201-0070" # 무한궤도 굴착기 0.7㎥
|
|
assert entry["source"] == "note"
|
|
assert any("9-16-1" in line for line in entry["basis"])
|
|
|
|
|
|
def test_비탈면다짐에_단가가_선다() -> None:
|
|
build = _build()
|
|
title = build.book.titles.get("B-FP-09-17-01")
|
|
assert title is not None, "비탈면 다짐 일위대가가 안 섰습니다"
|
|
assert title.unit == "㎡"
|
|
assert build.book.resolve("B-FP-09-17-01").total > 0
|
|
|
|
|
|
def test_비탈면다짐은_원문_작업량을_그대로_쓴다() -> None:
|
|
"""② 77.7 은 원문 값이다 — 지어낸 수가 아님을 줄에 남긴다."""
|
|
build = _build()
|
|
# 층 차례 X → D → B(2026-09-13) — 작업량(Q) 줄은 D(단가산출)에, B 는 D 를 1 로 부름.
|
|
assert [(r.ref_code, r.quantity) for r in build.book.details["B-FP-09-17-01"]] == [
|
|
("D-FP-09-17-01", Decimal(1))
|
|
]
|
|
rows = build.book.details["D-FP-09-17-01"]
|
|
assert rows, "상세 줄이 없습니다"
|
|
for row in rows:
|
|
# 시간 = 1 ÷ 77.7 ㎡/시간
|
|
assert row.quantity == Decimal(1) / Decimal("77.7")
|
|
assert "9-17-1" in row.note and "77.7" in row.note
|
|
|
|
|
|
def test_부착_콤팩터_손료가_함께_붙는다() -> None:
|
|
"""④ 카탈로그에 **이름이 빈 줄**(0240-0007)이라 이름으로만 가리면 놓친다."""
|
|
build = _build()
|
|
refs = {row.ref_code for row in build.book.details["D-FP-09-17-01"]} # 층 차례 — D 에 삶
|
|
assert "X-0240-0007" in refs, refs
|
|
# 본체 굴착기는 조합 사용 층(잡재료 16%)으로 바뀌어야 한다 — 품셈 제8장 [주]⑤.
|
|
assert any(ref.startswith("X-0201-0070#") for ref in refs), refs
|
|
assert "0240-0007" not in build.incomplete_machines
|
|
|
|
|
|
def test_제목에만_있는_작업량은_표에서_온_것과_안_겹친다() -> None:
|
|
"""⚠ 같은 기종이 표에도 있으면 두 번 세면 안 된다."""
|
|
master = load_work_item_master()
|
|
node = next(w for w in master["work_items"] if w["work_item_code"] == "FP-09-17-01")
|
|
rows = direct_capacity_rows(node)
|
|
codes = [row["machine_code"] for row in rows]
|
|
assert len(codes) == len(set(codes))
|
|
assert set(codes) == {entry["machine_code"] for entry in SOURCE_TEXT_CAPACITY["FP-09-17-01"]}
|