Files
Aislo/resources/tester/test_806_1_labor_view.py
T
eomsangdonandClaude Opus 5.5 f5d3347d1e fix(808-1): 줄 쌓기 수정 3차 — 수량 칸 식 글 칸 + 출처 꼬리표 · 글꼴 M01 = M02 · M02 머리 [단가 갱신][재생성] · 일위대가 줄 모달 일원화
- 수량 칸(요구 701-1) = 늘 식 글 칸(Q_특별인부) + 출처 꼬리표(표 = 표 고르기) · 눌러도 안 바뀜 · 표 값 기호에 수 = 그 값만(직접 입력) · 꼬리표 한 곳(sourceTag)
- 글꼴(701-2) = 줄 쌓기 화면이 정함(14px · M02 가 부모 16px 을 받던 것)
- M02 머리(701-3) = [초기화] 와 [되돌림] 뜻 다름 → [초기화] 이름 「M01 값으로」 · [단가 갱신][재생성] = 보기 고르기 옆 머리 칸(수식 보기만)
- 일위대가 단가산출 줄 모달(701-5) = 페이지 머리와 같음(보기 고르기 · [단가 갱신] · [재생성] · [저장])
- 일위대가 로직 줄 모달(701-4 · 5) = 옛 [옵션] · [단가산출로도 저장] · [항목 추가] · [율 줄 추가] 걷음 · 보기 고르기 없이 상세만 + 안내(온 단가산출) ·
  줄 문서 키 SK-000000 이 수식 문서를 읽어 404 · 「못 읽음」 이던 것 고침
- 시험: test_804_7 낡은 소스 기대(꼬리표 조건 글) 고침 + 808-1 · test_806_1 808-1 모달

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 18:52:03 +09:00

141 lines
7.5 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
def test_808_1_모달_머리_일원화():
"""808-1(요구 701-4 · 5) — 단가산출 줄 모달 머리 = 페이지 머리(보기 고르기 · [단가 갱신] · [재생성]) ·
로직 줄 모달(저장된 일위대가 줄 = 펼친 로직 줄 · 740-1) = 옛 [옵션] · [단가산출로도 저장] · [항목 추가] · [율 줄 추가] 없음 ·
보기 고르기 없이 상세만 + 안내(온 단가산출) · 줄 문서 키 SK-000000 = 수식 문서 안 읽음(404 없음)."""
sk = _src("M02_MasterTemplete_Labor_SkEdit.ts")
assert "slot,\n" in sk and "head.append(slot);" in sk
row = _src("M02_MasterTemplete_Labor_RowModal.ts")
for gone in ("AlsoSk", "createCheckbox", "openLaborInput", "saveAsSk", "Labor_Option"):
assert gone not in row, gone
assert "actions: row.참조 ? [slot, ...tools] : tools," in row and 't("FromSk")' in row
assert "slot: o.slot," in _src("M02_MasterTemplete_Labor_RowSk.ts")
detail = _src("M02_MasterTemplete_Sangeun_Detail.ts")
assert "...(opt.slot\n ? []" in detail # 머리 칸 있으면 옛 단추 줄 없음
assert "children: [tabs.picker, tabs.tools]" in detail
assert r"/^SK-(?!0{6})\d{6}$/" in detail
tabs = _src("M02_MasterTemplete_Sangeun_Tabs.ts")
assert 'if (!k && !opt.page && view === "stack")' in tabs