feat(B09): 인계 계약 시험 + ㉦ 큰돌쌓기 포함자재 가드 + 수량 2자리 표시

인계 계약 시험 (같은 병 재발 방지)
- **B08 이 보내는 칸을 내가 실제로 읽는지** 시험으로 마주 걺. 새 칸이 오면 깨짐.
  안 읽는 칸은 까닭을 함께 적게 함(측점·spec_detail 등)
- 값이 자료형까지 실제로 닿는지도 짝으로 봄 — 이름만 맞고 값이 안 실리면 같은 병

㉦ 가드 신설 (품셈 13-6 [주]① 「고임돌 및 채움 콘크리트 등은 품에 포함」)
- 큰돌쌓기 줄이 서 있는데 **그 구조물이 낳은** 고임돌·채움콘크리트가 자재로도 서면 멈춤
- ⚠ 13-6 한정 — 돌쌓기 13-4 의 고임돌은 정상이라 안 걸림. 짝 시험 2건
- 내 일위대가는 그 둘을 안 세우고 있음을 확인(품셈 표에 없음)

수량 표시
- 내역서 수량을 **소수 2자리**로 보임. 계산은 전정밀 그대로
- 「표시는 2자리, 계산은 전정밀 — 표시값끼리 곱하면 끝자리가 다릅니다」를 표 아래 상시 표시
  (실무 서식 자릿수는 기준 문서에 없어 2자리는 잠정)

검증: pytest 195 통과(신규 5), tsc 0건, 화면 실측 — 15,726.93 · 92.45 로 뜸

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 04:38:03 +09:00
co-authored by Claude Opus 5
parent 56e0351389
commit fecda89e5f
4 changed files with 78 additions and 2 deletions
+37
View File
@@ -245,3 +245,40 @@ def check_drain_pipe_not_double_counted(
"실었습니다 — 윗단 값에 파이프의 노무비·재료비가 이미 들어 있습니다 "
"(품셈 13-6-2 [주]③)."
)
#: 큰돌쌓기(13-6) 품에 **이미 들어 있는** 자재 — 따로 세우면 두 번이다.
#: 근거: 품셈 13-6 [주]① 「고임돌 및 채움 콘크리트 등은 품에 포함」.
#: ⚠ **13-6 한정**이다 — 돌쌓기(13-4)·돌붙임(13-7)에는 이 [주]가 없으므로
#: 그쪽에서 고임돌이 자재로 오는 것은 정상이다. 넓게 잡으면 정상 자재를 지운다.
BOULDER_INCLUDED_MATERIALS = ("고임돌", "채움콘크리트", "채움 콘크리트")
BOULDER_WORK_ITEM_PREFIX = "FP-13-06"
def check_included_materials_not_listed(
*,
work_item_codes: list[str],
materials: list[dict],
name_field: str = "material_name",
source_field: str = "source_structure",
label: str = "큰돌쌓기",
) -> None:
"""㉦ 품에 포함된 자재를 따로 세지 않았는가 (품셈 13-6 [주]①).
큰돌쌓기 줄이 서 있는데 **그 구조물이 낳은** 고임돌·채움콘크리트가 자재로도 서면
같은 것을 두 번 센다. 자재의 `source_structure` 로 **그 구조물에서 온 것만** 본다 —
다른 구조물(돌쌓기 13-4)의 고임돌은 정상이다.
"""
if not any(str(code).startswith(BOULDER_WORK_ITEM_PREFIX) for code in work_item_codes):
return
for material in materials:
name = "".join(str(material.get(name_field) or "").split())
if name not in {"".join(x.split()) for x in BOULDER_INCLUDED_MATERIALS}:
continue
sources = material.get(source_field) or []
if any(label in str(source) for source in sources):
raise DoubleCountError(
f"{label}: 「{material.get(name_field)}」이 자재로도 실렸습니다 — "
"큰돌쌓기 품에 이미 들어 있습니다 (품셈 13-6 [주]① 「고임돌 및 "
"채움 콘크리트 등은 품에 포함」)."
)