# -*- coding: utf-8 -*- """786-2 불러오기 [수정] 모달 지킴 — 「확인 — 제N호표」 옛 꼴 되살림 + 새 기능 「새」 표지 (요구 644 · 645). - 우리 금액 길(`/hopyo/{키}/price` · 저장 없음) — 옮기기와 같은 길로 한 줄 문서 → `Labor_Doc.calc`: 예시 1 야면석소운반(단산10 · GC001140 · 입력 필요 0 · 엑셀 1 단위 94,227) · 예시 3 합판거푸집(GC000211 · 높이감률 · 구멍땜 입력 필요 → 0 넣으면 노무 38,291) · 쓰기 0(SC · SK 수 그대로) - 화면 소스 — [수정] = 모달(`openHopyoCheck` · 부품 상자 모달) · 시트 아래 호표 줄 판 몸 없음 · 「새」 배지 · 구조물 조합 공용 부품(`Labor_Rows` · `Labor_MatMarks` · `Labor_Input` · `Labor_Pick`)은 import 만 · 날 button · input · select 0 · 700 줄 임시 storage(`client` 마당) · M01 원본 그대로. """ import re from pathlib import Path from M02_MasterTemplete import M02_Hopyo_Judge as judge from M02_MasterTemplete import M02_Template_Layers as layers # ruff: noqa: F811 from resources.tester.test_m02_hopyo_excel import _post, client, master_hash # noqa: F401 ROOT = Path(__file__).resolve().parents[2] M02 = ROOT / "M02_MasterTemplete" API = "/api/m02/layers/personal" KEY = "HP-000001" MINE = ("Check", "CheckRows", "ToItem", "Rows") SHARED = ("Labor_Rows", "Labor_MatMarks", "Labor_Input", "Labor_Pick", "Labor_Detail", "Structure") def _src(name: str) -> str: return (M02 / f"M02_MasterTemplete_{name}.ts").read_text(encoding="utf-8") def _at(unit, no): return next(r for r in unit["줄"] if r.get("번") == no and "단가산출" in r["갈래"]) def _base(row): part = row["풀이"]["절"][0] cand = next(c for c in part["후보"] if c["키"] == part["고름"]) return {"갈래": "기초", "키": cand["키"], "입력값": cand["바인딩"]["입력값"]} def _count(kind): folder = layers.personal_dir(7, 42) / kind return len(list(folder.glob("*.json"))) if folder.exists() else 0 def test_우리금액_옮기기와_같은_길_저장없음(client): before = master_hash() assert _post(client).status_code == 200 judge.solve_all(layers.personal_dir(7, 42), KEY) made = (_count("precombo"), _count("sangeun")) url = f"{API}/hopyo/{KEY}/price" two = client.get(f"{API}/hopyo-judge/{KEY}/2").json() ten = _at(two, 10) # 예시 1 야면석소운반 got = client.post( url, json={"층": "personal", "호표": 2, "줄": {str(ten["차례"]): [_base(ten)]}} ) assert got.status_code == 200, got.text line = got.json()["줄"][str(ten["차례"])] assert line["까닭"] == [] and line["칸"] == [] assert int(line["금액"]["계"] / ten["수량"]["엑셀"]) == 94227 == ten["단가"]["계"] one = client.get(f"{API}/hopyo-judge/{KEY}/1").json() form = _at(one, 24) # 예시 3 합판거푸집 ex3 = _base(form) need = client.post(url, json={"층": "personal", "호표": 1, "줄": {str(form["차례"]): [ex3]}}) stuck = need.json()["줄"][str(form["차례"])] assert stuck["금액"] is None and stuck["칸"] == ["높이감률", "구멍땜"] ex3["입력값"] = {**ex3["입력값"], "높이감률": 0, "구멍땜": 0} ok = client.post(url, json={"층": "personal", "호표": 1, "줄": {str(form["차례"]): [ex3]}}) money = ok.json()["줄"][str(form["차례"])]["금액"] assert abs(money["노무비"] / form["수량"]["엑셀"] - 38291) <= 2 # 엑셀 노무 38,291(줄 0.1 원 끝수) bad = client.post( url, json={"층": "personal", "호표": 2, "줄": {"0": [{**_base(ten), "금액": 1}]}} ) assert bad.status_code == 422 # 금액 칸 = 서버가 셈 assert (_count("precombo"), _count("sangeun")) == made # 쓰기 0 assert master_hash() == before def test_수정은_모달_줄판몸_없음(): sheet = _src("Hopyo_Sheet") edit = sheet.split("const editButton")[1].split("function paintList")[0] assert "openHopyoCheck({" in edit and "openLines" not in edit assert "createJudgeRows" not in sheet + _src("Hopyo_Rows") check = _src("Hopyo_Check") assert 'from "@ui/ui_template_modal"' in check and "openModal({" in check assert 'L("M02_CheckTitle")' in check and "confirmSuggested(" in check # [호표 제안 모두 확인] assert "runMove(" in check and "[String(no)]: mine" in check # [사전조합 생성] = 이 호표만 assert "h.만든" in check.split("const item = ")[1].split(";")[0] # 옮겨진 뒤만 locale = (ROOT / "ui_template/ui_template_locale_m2_judge.ts").read_text(encoding="utf-8") assert 'M02_CheckTitle: ["확인 — 제{n}호표"' in locale and 'M02_CheckNew: ["새"' in locale def test_새_배지_옛_표_꼴(): rows = _src("Hopyo_CheckRows") assert "createBadge(" in rows and "newBadge()" in rows and "dataset.checkNew" in rows assert "newBadge()" in _src("Hopyo_Check") for part in ("moneyCell(", "PRICE_SLOTS", "markCells(", "markHeads()", '"logic"', '"mat"'): assert part in rows, part assert "M02_CheckApart" in _src("Hopyo_Rows") # 별도계상 줄 = 고름 칩 없이 글 def test_공용파일_import_만_부품상자만_700줄(): texts = {n: _src(f"Hopyo_{n}") for n in MINE} joined = "\n".join(texts.values()) for name in ("Labor_Rows", "Labor_MatMarks", "Labor_Input", "Labor_Pick"): assert f'from "./M02_MasterTemplete_{name}"' in joined, name for name in SHARED: # 공용 쪽은 새 모달을 모름(거꾸로 이음 없음) assert "Hopyo_Check" not in _src(name) and "Hopyo_ToItem" not in _src(name), name for name, text in texts.items(): 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 "