까닭 — B08 인계의 조각 수량은 「합계」인데(그쪽 시험이 지킴: BOX 동바리 3.92×10 · 포장 97.66㎥) B09 가 Σ(조각 단가 × 조각 수량) 을 1단위 단가로 보고 줄 수량을 또 곱했음. 평떼 718.14㎡ 가 720배(42억)로 섰음(2026-09-15 랩탑 서브 실측). 고침 — 계약은 그대로 두고 읽는 쪽을 고침. 합계를 그대로 금액으로 쓰고 단가는 나눠서 보임. 재·노·경 성분 셋도 같이. 계약을 코드 가까이 못박음 — 두 자리(composite_parts 칸 · _composite_row). ⭐ 시험도 고침 — 종전이 줄 수량 1 로만 재서 못 잡았음. _line(parts, quantity) 로 열고 수량 2·10·718.14 로 잼 · 성분 셋도 따로. 빨강 4 확인한 뒤 고쳤음. ⚠ 지금 검증 프로젝트엔 값이 선 묶음 줄이 0 이라 금액 변화는 안 드러남 — BOX·포장·집수정·녹화가 서면 그때 제 값으로 섬. 전체 시험 2136 통과 · 28 건너뜀 · 1 xfail · 1 실패는 내 변경과 무관한 노임 신뢰도 시험(아래 보고). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Prk9BCHG1EMAywk9k8wegA
86 lines
3.7 KiB
Python
86 lines
3.7 KiB
Python
"""조립(묶음) 줄이 조각의 「일부만」·「밑수 없음」 을 올림 — 2026-09-14 브레인 ㉱ 첫째(구조 결함).
|
||
|
||
종전 `_composite_row` 는 조각 제목이 **있기만 하면** 금액에 더했음 → 조각 단가가 일부 몫만 섰거나(인력만)
|
||
밑수를 모르는 표여도 조립 줄이 **온전한 금액처럼** 섰음. 보통 줄은 그 둘을 막는데 조립 줄만 새던 자리.
|
||
⇒ 조각마다 보통 줄과 같은 두 검사 — 걸리면 금액을 안 세우고 어느 조각이 왜인지 사유.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
|
||
from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill
|
||
from B09_Estimation.B09_Estimation_UnitPrice import cached_build
|
||
|
||
|
||
def _composite(parts: list[dict], quantity: str = "1") -> dict:
|
||
return {
|
||
"work_items": [
|
||
{
|
||
"work_item_code": None,
|
||
"name": "시험 묶음",
|
||
"spec": "",
|
||
"unit": "개소",
|
||
"quantity": quantity,
|
||
"in_bill": True,
|
||
"composite_parts": parts,
|
||
"composite_not_ready": [],
|
||
}
|
||
],
|
||
"materials": [],
|
||
}
|
||
|
||
|
||
def _line(parts: list[dict], quantity: str = "1"):
|
||
rows = build_bill(_composite(parts, quantity)).rows
|
||
return next(r for r in rows if r.code is None and r.name == "시험 묶음")
|
||
|
||
|
||
def test_일부만_선_조각이_있으면_묶음_금액을_안_세우고_까닭() -> None:
|
||
build = cached_build()
|
||
partial = next(c for c in build.partial_ratio if f"B-{c}" in build.book.titles)
|
||
line = _line([{"code": partial, "quantity": 1}])
|
||
assert line.amount_krw is None, (partial, line.amount_krw)
|
||
assert partial in line.note and "일부만" in line.note, line.note
|
||
|
||
|
||
def test_밑수_없는_조각도_같이_막음() -> None:
|
||
build = cached_build()
|
||
missing = next(c for c in build.basis_missing if f"B-{c}" in build.book.titles)
|
||
line = _line([{"code": missing, "quantity": 1}])
|
||
assert line.amount_krw is None and "밑수" in line.note, (missing, line.note)
|
||
|
||
|
||
def test_온전한_조각만이면_종전대로_금액() -> None:
|
||
line = _line([{"code": "FP-09-15-02", "quantity": 2}])
|
||
assert line.amount_krw and line.amount_krw > 0, line.note
|
||
|
||
|
||
# ── 줄 수량이 1 이 아닐 때 — 2026-09-15 랩탑 서브가 찾은 부풀음 ──
|
||
#: ⭐ **인계 조각 수량은 「합계」다** — B08 계약이고 그쪽 시험이 지킴
|
||
#: (BOX 동바리 3.92×10 · 포장 97.66㎥).
|
||
#: 그래서 `Σ(조각 단가 × 조각 수량)` 이 이미 **그 줄 전체 금액**이다.
|
||
#: 줄 수량을 또 곱하면 배로 부푼다. 종전 시험이 **줄 수량 1 로만 재서** 못 잡았다 —
|
||
#: 평떼 718.14㎡ 가 720배(42억)로 섰다.
|
||
_PART = {"code": "FP-09-15-02", "quantity": 2}
|
||
|
||
|
||
@pytest.mark.parametrize("quantity", ["2", "10", "718.14"])
|
||
def test_묶음_금액은_줄_수량을_다시_안_곱한다(quantity) -> None:
|
||
"""조각이 합계이므로 **줄 수량이 몇이든 금액은 같다**. 단가는 그 금액 ÷ 수량으로 보인다."""
|
||
one = _line([_PART])
|
||
many = _line([_PART], quantity)
|
||
assert one.amount_krw and many.amount_krw, (one.amount_krw, many.amount_krw)
|
||
assert many.amount_krw == one.amount_krw, (quantity, many.amount_krw, one.amount_krw)
|
||
assert many.unit_price_krw < one.unit_price_krw, (quantity, many.unit_price_krw)
|
||
|
||
|
||
def test_묶음_성분도_줄_수량만큼_안_부푼다() -> None:
|
||
"""재·노·경 셋도 같이 봐야 함 — 합계만 보면 성분이 부푼 것을 놓친다."""
|
||
one, many = _line([_PART]), _line([_PART], "10")
|
||
assert (many.material_krw, many.labor_krw, many.expense_krw) == (
|
||
one.material_krw,
|
||
one.labor_krw,
|
||
one.expense_krw,
|
||
)
|