Files
Aislo/resources/tester/test_806_1_labor_view.py
T
eomsangdonandClaude Sonnet 5.5 2d9a469fc7 feat(806-1): 구조물 조합 일위대가 보기 = 일위대가 컨테이너 한 부품 · 단가산출 줄 = 그 SK 문서 모달(수식 탭 · 저장 = 그 SK)
- 조합 상세 · 카드 · 서고 모두 Labor_Table 한 부품 — 조합 전용 칸(면적 잇기 · 수량산출 모달 · 규격 열 · 다이어그램)은 새 Labor_Combo
- 단가산출(SK) 참조 줄 누름 = 새 Labor_SkEdit — 그 SK 문서를 단가산출 상세 부품(수식 탭 첫 화면)으로 열고 [저장] = 수식 저장 → SK 문서 저장 → 일위대가 금액 다시 셈 · 위 층 SK = 읽기만 · 두 번 눌러도 모달 하나
- 옛 조합 전용 표 · 단가산출 보기 모달(Labor_SangeunModal) 지움 · 전국 자재 줄은 Labor_Table 이 그림
- 새 시험 test_806_1_labor_view · 소스 지킴 시험 12 개를 새 자리(Labor_Table · Labor_RowModal · Labor_SkEdit)로 고침 — 옛 Detail 자리 문구가 없어져 낡았음

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 16:31:49 +09:00

122 lines
6.2 KiB
Python

# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
"""PLAN 806-1 — 구조물 조합 일위대가 보기 = 일위대가 컨테이너 부품 한 벌 · 단가산출 줄 = 그 SK 문서 모달(요구 698).
- 화면(소스 지킴) = 조합 상세 · 카드 · 서고 모두 `Labor_Table` 한 부품 · 조합 전용 칸은 `Labor_Combo` · 옛 조합 전용 표 ·
단가산출 보기 모달 걷음 · 단가산출 줄 누름 = `Labor_SkEdit`(수식 탭 부품 · 저장 = 그 SK 문서) · 부품 상자 · 700 줄
- 금액(서버) = 같은 문서 · 같은 SK → 같은 금액(전후 같음) · 모달 [저장] 길(`store.write` sangeun) 뒤엔 그 SK 를 가리킨 줄 금액이
따라 바뀜 · 되돌리면 원래 금액
"""
import re
from decimal import Decimal
from pathlib import Path
import pytest
from M02_MasterTemplete import M02_Labor_Doc as labor
from M02_MasterTemplete import M02_Labor_Ref as refs
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from M02_MasterTemplete import M02_Sangeun_Calc as calc
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
ROOT = Path(__file__).resolve().parents[2]
M02 = ROOT / "M02_MasterTemplete"
PCT = "GC001109" # 원/㎡ · 인력 둘 + 「노무비 * 3 / 100」
COVER = {"덮개": {"labor:LB000036#0": {"qty": 0.5}}}
def _src(name: str) -> str:
return (M02 / name).read_text("utf-8")
def test_조합_상세_카드_서고_한_부품():
detail = _src("M02_MasterTemplete_Labor_Detail.ts")
table = _src("M02_MasterTemplete_Labor_Table.ts")
assert "return mountLaborTable(host, doc, opt);" in detail # 입구 하나
assert "logicTable" not in detail and "afterRowDrag" not in detail # 옛 조합 전용 표 걷음
assert not (
M02 / "M02_MasterTemplete_Labor_SangeunModal.ts"
).exists() # 옛 단가산출 보기 모달 걷음
assert 'opt.mode === "precombo" ? null : createCombo(' in table # 조합 = 컨테이너 + 덧칸
for text in ("openSkEdit({", "specBar(cur,", "specCells(block, cur,", "dg?.draw("):
assert text in table, text
assert "수량: fresh()" in table # 새 줄 수량 — 조합 = 면적을 따름
combo = _src("M02_MasterTemplete_Labor_Combo.ts")
assert "openQtyModal({" in combo and "linkAreaCell(" in combo and "saveTemplate(" in combo
def test_단가산출_줄은_SK_문서_모달_저장은_그_SK():
table = _src("M02_MasterTemplete_Labor_Table.ts")
modal = _src("M02_MasterTemplete_Labor_SkEdit.ts")
assert 'ref.키.startsWith("SK-")' in modal # SK 참조 줄만
assert "if (isSkRef(row.참조) && !opt.calc)" in table # 셈 주입(프로젝트 복사본)엔 옛 줄 모달
assert "readOnly: !edit || row.참조.층 !== opt.layer," in table # 위 층 SK = 읽기만
assert re.search(r'readTemplate\(layer, "sangeun", opt\.ref\.키, null, opt\.ref\.주인\)', modal)
assert re.search(
r'saveTemplate\(\s*layer,\s*"sangeun",\s*opt\.ref\.키', modal
) # 저장 = 그 SK 문서
assert (
"mountSangeunDetail(host, doc," in modal and "source: true" in modal
) # 수식 탭 부품 그대로
assert "await handle.flush();" in modal # 수식 저장 먼저 → 문서 저장
assert "if (!opt.readOnly) head.append(ok);" in modal # 읽기만 = [저장] 없음
assert "if (opened.has(at)) return;" in modal # 빨리 두 번 눌러도 하나
assert "closed: (done) => alive && done && recalc()," in table # 저장했으면 금액 다시 셈
def test_부품상자만_700줄_명사형():
for name in (
"M02_MasterTemplete_Labor_Table.ts",
"M02_MasterTemplete_Labor_Combo.ts",
"M02_MasterTemplete_Labor_SkEdit.ts",
"M02_MasterTemplete_Labor_Detail.ts",
):
text = _src(name)
assert len(text.splitlines()) <= 700, name
assert not re.search(r"""\bel\(\s*["'](button|input|select)["']""", text), name
assert not re.search(r"""createElement\(\s*["'](button|input|select)["']""", text), name
assert "#" not in "".join(re.findall(r"color:\s*[^;]+", text)), name
def _total(layer: Path, sk: str, qty: float) -> Decimal:
"""그 층 일위대가 한 벌(SK 참조 줄 하나 · 수량 qty)의 1 단위 합계."""
with store.at(layer):
ref = {"층": "personal", "주인": refs.here()[1], "키": sk}
doc = labor.clean({"담은로직": [{"로직": "", "참조": ref, "수량": {"손": qty}}]})
return Decimal(str(labor.calc(doc, {})["반영합"]["계"]))
def test_모달_저장_뒤_금액_따라감_되돌리면_같음(world):
"""모달 [저장] = SK 문서 쓰기(`store.write`) — 그 SK 를 가리킨 일위대가 줄 금액이 바뀌고 · 되돌리면 전후 같음."""
personal = world["personal"]
with store.at(personal):
key = refs.create(
"sangeun", {"이름": "sub1 시험", "단위": "㎡", "바탕": {"로직": PCT}, "더한줄": []}
)["이름"]
got = store.read("sangeun", key)
ver0, doc0 = got["판"], got["문서"]
before = _total(personal, key, 2)
assert before == _total(personal, key, 2) and before > 0 # 같은 문서 · 같은 SK = 같은 금액
with store.at(personal):
cut = {**doc0, **COVER}
ver1 = store.write("sangeun", key, ver0, calc.clean_doc(cut, refs.here()))["판"]
changed = _total(personal, key, 2)
assert changed != before # 품 0.5 로 바뀜 — 일위대가 금액이 그 SK 를 따라감
with store.at(personal):
store.write("sangeun", key, ver1, doc0)
assert _total(personal, key, 2) == before # 되돌림 = 전후 같음
def test_옛_판_저장_409(world):
"""모달 [저장]이 낡은 판으로 쓰면 서버가 막음(같은 SK 를 다른 창이 먼저 고침)."""
personal = world["personal"]
with store.at(personal):
key = refs.create(
"sangeun", {"이름": "sub1 시험2", "단위": "㎡", "바탕": {"로직": PCT}, "더한줄": []}
)["이름"]
got = store.read("sangeun", key)
store.write("sangeun", key, got["판"], {**got["문서"], "이름": "다른 창이 고침"})
with pytest.raises(store.StoreError) as why:
store.write("sangeun", key, got["판"], got["문서"])
assert why.value.status == 409