Files
Aislo/resources/tester/test_b09_bill_sheet_view.py
T

99 lines
4.3 KiB
Python

"""B09 내역서 화면 자료 — 화면이 곱하거나 더하지 않게 서버가 싣는 칸 (PLAN 12장 1차).
겨누는 것
① 내역 줄 성분 단가 × 수량 = 성분 금액(성분마다 절사) — 화면은 실린 값만 찍음
② 머리글 줄 금액 = 아래 줄 금액의 합(성분마다) · 본체 합계엔 안 들어감
③ 일위대가 호표 번호 — 내역에 처음 쓰인 차례 · 같은 호표는 한 번 · 안에서 부르는 호표는 뒤에
④ 단산 목록 — 부르는 일위대가 전부 · 성분 금액
"""
from __future__ import annotations
from decimal import Decimal
from functools import lru_cache
from B09_Estimation.B09_Estimation_BillOfQuantities import bill_line, build_bill
from B09_Estimation.B09_Estimation_PriceBook import (
Money3,
PriceBook,
PriceDetail,
PriceKind,
PriceTitle,
)
from B09_Estimation.B09_Estimation_UnitPrice import _slots, build_unit_prices
from B09_Estimation.B09_Estimation_UnitPriceSheet import build_unit_price_sheet
@lru_cache(maxsize=1)
def _bill():
payload = {
"work_items": [
{"work_item_code": "FP-09-03-02", "name": "토사깍기", "unit": "㎥", "quantity": 123.4},
{"work_item_code": "FP-09-12-01", "name": "측구터파기", "unit": "㎥", "quantity": 7},
{"work_item_code": "FP-09-03-02", "name": "토사깍기", "unit": "㎥", "quantity": 5},
],
"materials": [],
}
return build_bill(payload, build=build_unit_prices())
def test_줄_성분_단가와_금액이_실린다() -> None:
priced = [r for r in _bill().rows if not r.is_group and r.amount_krw is not None]
assert priced
for row in priced:
unit = Money3(row.unit_material_krw, row.unit_labor_krw, row.unit_expense_krw)
line = bill_line(unit, row.quantity)
assert (line.material, line.labor, line.expense) == (
row.material_krw,
row.labor_krw,
row.expense_krw,
)
assert row.amount_krw == line.total
body = row.as_dict()
assert body["price_code"] == row.price_code and body["unit_labor_krw"] is not None
def test_머리글_줄은_아래_줄_합이고_본체엔_안_든다() -> None:
bill = _bill()
detail_total = sum(r.amount_krw or 0 for r in bill.rows if not r.is_group)
assert bill.body_total_krw == detail_total
for group in (r for r in bill.rows if r.is_group):
children = [
r
for r in bill.rows
if not r.is_group and r.item_no.startswith(f"{group.item_no}-") and r.amount_krw
]
assert group.amount_krw == sum(r.amount_krw for r in children)
assert group.labor_krw == sum(r.labor_krw for r in children)
def test_호표_번호는_처음_쓰인_차례이고_안에서_부르는_호표는_뒤에() -> None:
book = PriceBook()
book.add_title(PriceTitle("L", PriceKind.LABOR, "보통인부", slots=_slots(Decimal(100000))))
for code in ("B-A", "B-B", "B-C"):
book.add_title(PriceTitle(code, PriceKind.UNIT_PRICE, code))
book.add_detail(PriceDetail("B-C", "L", Decimal(1)))
book.add_detail(PriceDetail("B-A", "B-C", Decimal(2))) # A 안에서 C 를 부름
book.add_detail(PriceDetail("B-B", "L", Decimal(1)))
class Row:
def __init__(self, code: str) -> None:
self.price_code, self.name, self.spec, self.unit = code, code, "", "㎥"
sheet = build_unit_price_sheet([Row("B-B"), Row("B-A"), Row("B-B"), Row("")], book)
assert [(e.number, e.code) for e in sheet.entries] == [(1, "B-B"), (2, "B-A"), (3, "B-C")]
assert sheet.entries[1].as_dict()["label"] == "제 2 호표"
assert sheet.entries[1].money.labor == 200000
def test_내역에_호표_목록과_단산_목록이_함께_실린다() -> None:
bill = _bill()
codes = [e.code for e in bill.unit_price_sheet.entries]
used = list(dict.fromkeys(r.price_code for r in bill.rows if r.price_code))
assert [c for c in codes if c in used] == used # 안에서 부르는 호표가 끼어도 차례는 그대로
for entry in bill.price_basis.entries:
body = entry.as_dict()
assert body["unit_price_codes"] and Money3(
*(int(body[k]) for k in ("material_krw", "labor_krw", "expense_krw"))
).total == int(body["unit_price_krw"].split(".")[0])