- 개인 층 재료 고름 = 창 머리 [신규 자재] — 만들어 바로 자재 목록에 넣음(`openNewMaterial`) - 찾아 넣기 창 기계(M01 EQ) 탭 — 「M01 전체」 묶음 안 · 부르는 쪽이 `machine` 을 줄 때만 보임 - 엑셀 연결 = 줄 갈래대로 탭(노임 = 인력 · 기계 = 기계 · 자재 = 재료 · 그 밖 = 기초) — 불러오기 고르기 · 남은 줄 · 못옮김 · 안 이은 줄 연결 모두 같은 창 · 따로 [기계] 단추 걷음 - 낡은 시험 고침(721 · 729-3: 기계 고름 길이 찾아 넣기 창으로 옮김) + 736-2 글 시험 추가 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
131 lines
6.5 KiB
Python
131 lines
6.5 KiB
Python
"""일위대가 불러오기 마법사 안 이은 줄 화면(PLAN 729-3 · 요구서 내역19 1장 8 · 2장 4).
|
|
|
|
헬퍼(`helper_729_3_hopyo_left.cjs` · fetch · sessionStorage 대역)로 진짜 TS 를 돌림 —
|
|
만들기 409 `{까닭, 남은줄}` = StaleError 까닭 글 + 남은 줄 · 남은 수 = 안 만든 호표만(만든 호표는 안 물음) ·
|
|
줄마다 고름(노임 · 기계 · 비율 · 우리에 없음 · 로직) = 확인 창 캐시 → 만들기 몸 그대로 · 0 될 때까지 ·
|
|
일위대가표 안 이은 고정 줄(비율 · 이음 있는 줄 뺌) · 고름 대기 후보 글.
|
|
소스: [끝내기] = 남은 줄 다시 셈 → 있으면 막음(띠 · 표) · 단가산출 칸 · 목록 열 · 화면 요소 = 부품 상자 · 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"
|
|
|
|
|
|
def _line(no: int, kind: str = "자재", state: str = "후보") -> dict:
|
|
match = {"열쇠": f"줄{no}", "상태": state, "체크": False, "대상": []}
|
|
return {"차례": no, "이름": f"줄{no}", "규격": "", "수량": 1, "단위": "㎥", "갈래": kind,
|
|
"단가": {}, "금액": {}, "비고": "", "맞춤": match} # fmt: skip
|
|
|
|
|
|
def _left(no: int, kind: str) -> dict:
|
|
return {"차례": no, "이름": f"줄{no}", "규격": "", "단위": "㎥", "수량": 1, "갈래": kind,
|
|
"까닭": "이을 것 없음", "후보": []} # fmt: skip
|
|
|
|
|
|
LINES = [_line(0, "노임"), _line(1, "기계"), _line(2, "%", "%"), _line(3), _line(4, "단가산출")]
|
|
LEFT = [_left(0, "노임"), _left(1, "기계"), _left(2, "%"), _left(3, "자재"), _left(4, "단가산출")]
|
|
FIXES = [
|
|
{"고정": {"이름": "안이음", "단가": {}, "이음": {"노임": None, "자재": None, "기계": None}}},
|
|
{
|
|
"고정": {
|
|
"이름": "이음",
|
|
"단가": {},
|
|
"이음": {"노임": "LB000002", "자재": None, "기계": None},
|
|
}
|
|
},
|
|
{"고정": {"이름": "비율", "단가": {}, "비율": {"기준": "노무비", "비목": "경비"}}},
|
|
{"로직": "GF000113"},
|
|
]
|
|
|
|
|
|
def _run() -> dict:
|
|
payload = {
|
|
"one": {"키": "HP-000001", "파일": "북부청.xls", "호표": {"이름": "x", "줄": LINES}},
|
|
"made": [1],
|
|
"left": LEFT,
|
|
"fixes": FIXES,
|
|
}
|
|
proc = subprocess.run(
|
|
["node", os.path.join(HERE, "helper_729_3_hopyo_left.cjs")],
|
|
input=json.dumps(payload, ensure_ascii=False),
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
check=False,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_남은_줄_고름_몸_막힘_판정():
|
|
got = _run()
|
|
# 만들기 409 = StaleError · 까닭 글 · 남은 줄 그대로
|
|
assert got["stale"]["name"] == "StaleError" and got["stale"]["message"] == "남음"
|
|
assert got["stale"]["left"] == LEFT
|
|
# 만든 호표(1) 는 안 물음 · 안 만든 호표(2) 만 남은 줄
|
|
assert got["before"] == {"줄": 5, "호표": 1}
|
|
assert all(u.endswith("/layers/personal/hopyo-unlinked") for u in got["unlinkedCalls"])
|
|
assert len(got["unlinkedCalls"]) == 3 # 셈 세 번 × 안 만든 호표 하나
|
|
assert got["half"] == {"줄": 1, "호표": 1}
|
|
assert got["after"] == {"줄": 0, "호표": 0}
|
|
# 고른 것 = 만들기 몸(서버 이음 대상 꼴 · 입력값 없음 · 배 1)
|
|
body = {x["차례"]: x for x in got["body"]}
|
|
assert body[0] == {"차례": 0, "대상": [{"노임": "LB000002", "배": 1}]}
|
|
assert body[1] == {"차례": 1, "대상": [{"기계": "EQ000069", "배": 1}]}
|
|
assert body[2] == {"차례": 2, "대상": [{"비율": "노무비", "배": 1}]} # % 줄 = 밑수 고른 것만
|
|
assert body[3] == {"차례": 3, "뺌": "우리에 없음"}
|
|
assert body[4] == {"차례": 4, "대상": [{"로직": "GF000113", "입력값": {}, "배": 1}]}
|
|
assert got["lastBody"]["줄"] == got["body"] and got["lastBody"]["번"] == 2
|
|
# 일위대가표 띠 = 이음 · 비율 없는 고정 줄만
|
|
assert got["fixes"] == ["안이음"]
|
|
assert got["cand"] == "되메우기 [㎥] · 후보"
|
|
assert got["cand2"] == "되메우기 [㎥] · 다른 점 · 보통인부 품 다름"
|
|
|
|
|
|
def _text(name: str) -> str:
|
|
return (M02 / name).read_text(encoding="utf-8")
|
|
|
|
|
|
def test_마법사_끝내기_막음_단가산출_칸_목록_열():
|
|
wizard = _text("M02_MasterTemplete_Hopyo_Wizard.ts")
|
|
end = wizard.split("async function end()")[1]
|
|
assert end.index("await recount()") < end.index("showConfirmDialog(") # 끝내기 전 다시 셈
|
|
assert "if (leftCount(got).줄)" in end and "openLeft(" in end # 남으면 막음 · 표
|
|
assert "finish.disabled = !!n?.줄;" in wizard # 띠 · 남은 수 · [끝내기] 막음
|
|
assert "sangeunStep(scope, file.키)" in wizard and "/sangeun`" not in wizard
|
|
sk = _text("M02_MasterTemplete_Hopyo_WizardSk.ts")
|
|
assert "makeSangeun(scope, key, picks)" in sk
|
|
assert "picks[no] = { 로직: s.value, ...(need ? { 환산: { 계수: c } } : {}) };" in sk # 계수 칸
|
|
lost = _text(
|
|
"M02_MasterTemplete_Hopyo_Lost.ts"
|
|
) # 못옮김 잇기 = 캐시 모두 · 바탕 = SK 문서 바탕
|
|
assert "const links = Object.values(loadLinks(k));" in lost and "잇기: links," in lost
|
|
assert "로직: doc.바탕.로직, 입력값: doc.입력값 ?? {}" in lost
|
|
assert "row.못옮김?.length && row.단산 !== undefined && row.SK" in _text(
|
|
"M02_MasterTemplete_Hopyo_Left.ts"
|
|
)
|
|
lib = _text("M02_MasterTemplete_Library_List.ts")
|
|
assert 'L("M02_LibUnlinked"), (r) => (r.안이은줄' in lib
|
|
assert "unlinkedBar(doc, edit)" in _text("M02_MasterTemplete_Labor_Grid.ts")
|
|
assert "unlinkedBar(cur, edit &&" in _text("M02_MasterTemplete_Labor_Table.ts") # 일위대가표 띠
|
|
left = _text("M02_MasterTemplete_Hopyo_Left.ts")
|
|
# 일반 사용자 길 — 기계 고름은 찾아 넣기 창(736-2)이 `/logic-lib/elements` 로
|
|
assert "M01_MasterData_UI_Logic_Api" not in left
|
|
assert "/logic-lib/elements?group=" in _text("M02_MasterTemplete_Find_Pick.ts")
|
|
for name in (
|
|
"M02_MasterTemplete_Hopyo_Left.ts",
|
|
"M02_MasterTemplete_Hopyo_WizardSk.ts",
|
|
"M02_MasterTemplete_Labor_Unlinked.ts",
|
|
"M02_MasterTemplete_Hopyo_Lost.ts",
|
|
):
|
|
src = _text(name)
|
|
assert len(src.splitlines()) <= 700, name
|
|
assert 'el("button"' not in src and 'el("input"' not in src, name # 부품 상자만
|
|
assert not re.search(r"#[0-9a-fA-F]{3,6}|rgb\(", src), name # 색 = 공통 값
|