Files
Aislo/resources/tester/test_m02_hopyo_screen.py
T
eomsangdonandClaude Opus 5.5 56f606f331 feat(일위대가실무): 324-4 화면 — 좌측 「일위대가 실무자료」 판 · 본 화면(호표 표 · 줄 맞춤 · 확정 · 빠진 줄 · 값 비교) · [로직 추가] 「실무 호표」 줄
- 좌측 판(Hopyo_Side): 일위대가 사전조합 아래 · 구조물 조합 층 · 쓰기 권한 없으면 [엑셀 올리기] 꺼짐 · 숨은 file 입력 .xls,.xlsx · 파일 줄 → 본 화면
- 본 화면(Hopyo_View): 파일 · 시트 · 호표 수 · 검산 · 맞춤 n/m · 호표 표 + 찾기 · [지우기] / 호표 줄 표(갈래 · 품명 · 규격 · 수량 · 단위 · 엑셀 단가 · 맞춤 · 대상 · 입력값 · 환산) · [고르기](후보 5 + 다른 로직 · 자재 찾기 → 미리 채움) · [확정] · [빼기] · [되살림] · [같음 모두 확정] · 빠진 줄 · [사전조합 만들기] → 값 비교 · 다시 씀이면 [새로 만들기](확인 뒤 덮음)
- [로직 추가](Hopyo_Pick · Labor_Pick 늦은 덧줄 `more` · 종류 고르기): 문서 층 · 위 층 호표 줄(맞춤 n/m) → 고르면 서버가 문서 층 사전조합을 만들고 참조 줄(별칭 = 호표 품명) · 빠진 줄 알림 · 프로젝트 층 없음
- Labor_Detail: 제자리 넷 줄(가져오기 · pick 별칭 받음 · withHopyo) · 693 줄 그대로
- 서버: GET /layers/{층}/hopyo-picks(이 층 · 위 층 · 이 층 기억)
- 색 = 공용 토큰(밝음 · 어두움) · 시험 test_m02_hopyo_screen 4 + hopyo-picks 1 · typecheck 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
2026-10-14 22:27:57 +09:00

133 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""일위대가 실무자료 화면(PLAN 324-4) — 좌측 판 · 본 화면 · [로직 추가] 「실무 호표」 줄.
- 고르기 창 덧줄(Node · fetch 대역): 이 층 · 위 층 호표 줄(맞춤 n/m) · 종류 고르기 ·
고르면 문서 층에 만들기 길 → `lib.pick` 참조 줄(별칭 = 호표 품명) · 프로젝트 층엔 없음 ·
본 화면 글 도우미
- 소스: 좌측 판 자리(사전조합 아래 · 구조물 조합 층 · 쓰기 권한 없으면 올리기 꺼짐 ·
숨은 file 입력) · Labor_Detail 줄 수 그대로 · 새 파일 이름 · 700 줄 · 색 = 공용 토큰
"""
import json
import os
import re
import subprocess
from pathlib import Path
HERE = os.path.dirname(os.path.abspath(__file__))
M02 = Path(HERE).parents[1] / "M02_MasterTemplete"
NEW = ("Hopyo_Api", "Hopyo_Pick", "Hopyo_Side", "Hopyo_View")
def _text(name: str) -> str:
return (M02 / name).read_text(encoding="utf-8")
def _run() -> dict:
row = {
"층": "system",
"주인": None,
"키": "HP-000001",
"파일": "북부청.xls",
"번": 3,
"이름": "임도표지석",
"규격": "910×600×150",
"단위": "개소",
"맞춤": [2, 4],
}
built = {
"참조": {"층": "company", "주인": "7", "키": "SC-000009"},
"이름": "임도표지석",
"다시씀": False,
"빠진줄": [{"차례": 0}],
"비교": {},
}
proc = subprocess.run(
["node", os.path.join(HERE, "helper_m02_hopyo_pick.cjs")],
input=json.dumps({"rows": [row], "built": built}, ensure_ascii=False),
capture_output=True,
text=True,
encoding="utf-8",
check=True,
)
return json.loads(proc.stdout)
def test_고르기_창_실무_호표_줄과_고름():
got = _run()
assert got["calls"][0] == {
"url": "/api/m02/layers/company/hopyo-picks?owner=7",
"method": "GET",
"body": None,
}
assert got["kinds"] == ["logic", "precombo", "hopyo"]
assert got["rows"] == [
{
"kind": "hopyo",
"key": "system||HP-000001|3",
"tag": "실무 호표",
"name": "임도표지석 910×600×150",
"sub": "북부청.xls · 제3호표 · 마스터",
"unit": "개소 · 맞춤 2/4",
}
]
build = got["calls"][1]
assert build["url"] == "/api/m02/layers/company/hopyo-build?owner=7" # 만드는 층 = 문서 층
assert build["body"] == {
"층": "system",
"주인": None,
"키": "HP-000001",
"번": 3,
"새로": False,
}
assert got["picked"] == [
{
"ref": {"층": "company", "주인": "7", "키": "SC-000009"},
"name": "임도표지석",
"alias": "임도표지석",
}
]
assert got["project"] is True # 프로젝트 층 = 덧줄 없음
def test_본_화면_글_도우미():
view = _run()["view"]
assert view["target"] == ["구조물터파기 [㎥]", "레미콘 25-21-120 [㎥]", "제46호표 [㎡]"]
assert view["inputs"] == "횟수=4회사용시, 지역=서울 · ⚠ 못 읽음: 보정작업"
assert view["memory"] == [
{"로직": "GF000101", "입력값": {"지역": "서울"}, "환산": 1},
{"자재": "MT1", "입력값": {}, "환산": 0.5},
None, # 환산 0 = 확정 못 함
None, # 대상 없음
]
def test_좌측_판_자리와_권한():
side = _text("M02_MasterTemplete_UI_Side.ts")
assert 'import { buildHopyoSection } from "./M02_MasterTemplete_Hopyo_Side";' in side
host = side.split('className: "m02-side__lists ui-sidebar-panel"')[1]
assert host.index("precomboSec,") < host.index("section(hopyo.title, hopyo.body),")
assert host.index("section(hopyo.title, hopyo.body),") < host.index("extras ?")
assert "canWrite: canEdit(layer, opt.isAdmin)," in side # 구조물 조합 층 쓰기 권한
assert "hopyo.paint();" in side.split("function paint(): void {")[1]
names = set(re.findall(r"\b\w*[Pp]ractice\w*\b", side))
assert names <= {"buildPracticeSection", "practice", "M02_MasterTemplete_Practice"} # 옛 이름만
assert "LaborSection" not in side and "labor?." not in side and "picked" not in side
hopyo_side = _text("M02_MasterTemplete_Hopyo_Side.ts")
assert 'accept: ".xls,.xlsx"' in hopyo_side and "input.hidden = true;" in hopyo_side
assert "disabled: !opt.canWrite," in hopyo_side and "pageScope()" in hopyo_side
def test_로직_추가_한_곳과_파일_규칙():
detail = _text("M02_MasterTemplete_Labor_Detail.ts")
assert len(detail.splitlines()) == 693 # 줄 수 그대로(제자리 고침)
assert "withHopyo(library)," in detail
assert 'cur.담은로직.push({ 로직: "", 참조: ref, 별칭, 메모: null' in detail
pick = _text("M02_MasterTemplete_Labor_Pick.ts")
assert "more?: () => Promise<PickExtra[]>;" in pick and "...later" in pick
for name in NEW:
text = _text(f"M02_MasterTemplete_{name}.ts")
assert len(text.splitlines()) <= 700, name
css = _text("M02_MasterTemplete_Hopyo.css")
assert "var(--color-" in css and not re.search(r"#[0-9a-fA-F]{3,6}\b", css)
assert '"./M02_MasterTemplete_Hopyo.css"' in _text("M02_MasterTemplete_Hopyo_View.ts")