feat(793-3b): 불러오기 단산 줄 = 가져온 식 단가산출 모달 — 블록 → 가져온 식 SK 길 · 검산 · 엑셀/우리 단가 · 이음 고르기 · 근거 세 단 · 우리 기초로 바꾸기 · 입력 필요 · 줄 잇기 · 결과 칩
- 서버: 올림 때 산근 시트 둠(실무자료/산근/<HP>.json · HP 지울 때 같이) · POST …/sangeun/from-hopyo(블록 → 793-2a 내보내기 → 793-2 만들기 · 같은 내용 = 그 SK 다시 씀 · 옛 HP 409) · STmate 끝전 = 엑셀 계와 맞는 쪽 - 화면: [수정] 모달 단산 줄 · 오른쪽 블록 판 [가져온 식으로 열기](새) → 시트 모달 + 머리 판 · [이 줄에 잇기] = 줄 고른 것 SK(입력 필요 남으면 확인 막힘) · 단산 줄 결과 칩 - 시험: test_793_3b_import_screen 6 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""793-3b 지킴 — 불러오기 단산 줄 = 가져온 식 단가산출 모달(요구 646 · 647 · 652 갈래 C).
|
||||
|
||||
- 서버 길 `…/sangeun/from-hopyo` — 올림 때 산근 시트 둠(`실무자료/산근/<HP>.json`) →
|
||||
블록 → 793-2a 내보내기 → 793-2 가져온 식 SK(만들 층 · 엑셀 단가 그대로 · 검산 = 엑셀) ·
|
||||
같은 내용 = 그 SK 다시 씀 · 산근 없는 옛 HP = 409 · HP 지우면 산근도 지움 ·
|
||||
STmate 블록 끝전 = 엑셀 계와 맞는 쪽
|
||||
- 화면 소스 — [수정] 모달 단산 줄 · 오른쪽 블록 판 [가져온 식으로 열기] · 시트 모달
|
||||
(`Sangeun_Detail`) · 머리 판(검산 · [우리 단가로] / [엑셀 단가로] · [원본 글 보기] ·
|
||||
[이음 고르기] · 근거 세 단 · [우리 기초로 바꾸기] · 입력 필요 붉은 칸) ·
|
||||
[이 줄에 잇기] = 줄 고른 것 SK · 결과 칩 · 「새」 배지 · 부품 상자만 · 700 줄
|
||||
임시 storage(`client` 마당) · M01 원본 그대로.
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import helper_m02_hopyo_golden as golden
|
||||
import pytest
|
||||
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_Sangeun_FromHopyo as fh
|
||||
from M02_MasterTemplete import M02_Sangeun_Router as sangeun_router
|
||||
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 = ("Hopyo_Imported", "Hopyo_ImportedPanel", "Hopyo_Check", "Hopyo_CheckRows", "Hopyo_Block")
|
||||
|
||||
|
||||
def _src(name: str) -> str:
|
||||
return (M02 / f"M02_MasterTemplete_{name}.ts").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _skcount() -> int:
|
||||
folder = layers.personal_dir(7, 42) / "sangeun"
|
||||
return len(list(folder.glob("*.json"))) if folder.exists() else 0
|
||||
|
||||
|
||||
def _open(client, no=18):
|
||||
body = {"층": "personal", "키": KEY, "번": no}
|
||||
return client.post(f"{API}/sangeun/from-hopyo", json=body)
|
||||
|
||||
|
||||
# ── 서버 길 ───────────────────────────────────────────────────────────
|
||||
def test_단산_블록_가져온_식_만들기_다시씀_지움(client):
|
||||
client.app.include_router(sangeun_router.router)
|
||||
before = master_hash()
|
||||
assert _post(client).status_code == 200
|
||||
folder = layers.personal_dir(7, 42)
|
||||
assert fh.has(folder, KEY)
|
||||
made = _open(client)
|
||||
assert made.status_code == 200, made.text
|
||||
got = made.json()
|
||||
assert got["이름"].startswith("SK-") and got["다시씀"] is False
|
||||
assert got["단가기준"] == "엑셀" and got["검산"]["같음"] is True
|
||||
assert round(got["검산"]["셈"]["계"]) == 30369 # 북부청임도 단산18 문양거푸집 = 엑셀
|
||||
n = _skcount()
|
||||
again = _open(client).json()
|
||||
assert again["이름"] == got["이름"] and again["다시씀"] is True and _skcount() == n
|
||||
with store.at(folder):
|
||||
doc = store.read("sangeun", got["이름"])["문서"]
|
||||
assert doc["바탕"] is None and doc["가져온"]["원본"]["엑셀금액"]["계"] == 30369
|
||||
assert _open(client, 99999).status_code == 404
|
||||
fh._path(folder, KEY).unlink() # 산근 없는 옛 HP = 다시 올림
|
||||
old = _open(client)
|
||||
assert old.status_code == 409 and old.json()["detail"] == fh.RELOAD
|
||||
assert _post(client).status_code == 200 and fh.has(
|
||||
folder, KEY
|
||||
) # 같은 엑셀 다시 올림 = 산근 채움
|
||||
assert client.delete(f"{API}/hopyo/{KEY}").status_code == 200
|
||||
assert not fh.has(folder, KEY) # HP 지우면 산근도
|
||||
assert master_hash() == before
|
||||
|
||||
|
||||
RULES = [("봉화", "D00102", "비목버림"), ("동부청영월", "D00003", "합버림_큰나머지")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("tag", "code", "rule"), RULES)
|
||||
def test_STmate_끝전_엑셀_계와_맞는_쪽(tag, code, rule):
|
||||
from M02_MasterTemplete import M02_San_Book as book
|
||||
from M02_MasterTemplete import M02_San_Stmate as stm
|
||||
|
||||
if not golden.FILES[tag].exists():
|
||||
pytest.skip(f"실무 엑셀 없음 {tag}")
|
||||
data = book.load(golden.FILES[tag])
|
||||
blk = next(b for b in data["블록"] if b["코드"] == code)
|
||||
assert fh._rule(blk, stm.parse_block(blk["몸"]), data["단가"]) == rule
|
||||
|
||||
|
||||
# ── 화면 소스 ─────────────────────────────────────────────────────────
|
||||
def test_단산_줄_길_잇기():
|
||||
check, rows, block = _src("Hopyo_Check"), _src("Hopyo_CheckRows"), _src("Hopyo_Block")
|
||||
assert "openImported({" in check and "onLink: (p) => kit.edit(row, [p])" in check
|
||||
assert "imported }" in check.split("const ctx = ")[1].split(";")[0]
|
||||
assert 'L("M02_CheckImported")' in rows and "row.번 !== undefined && ctx.imported" in rows
|
||||
assert 'import("./M02_MasterTemplete_Hopyo_Imported")' in block # 돌림 import 피함
|
||||
assert 'L("M02_CheckImported")' in block and "dataset.checkNew" in block
|
||||
imp = _src("Hopyo_Imported")
|
||||
assert '"/sangeun/from-hopyo"' in imp and "/sangeun/imported/${how}" in imp
|
||||
assert "mountSangeunDetail(" in imp and "saveTemplate(" in imp and "openModal({" in imp
|
||||
assert "skPick(sk" in imp and "o.onLink" in imp # [이 줄에 잇기] = 줄 고른 것 SK
|
||||
for how in ('run("price"', 'run("link"', 'run("to-base"'):
|
||||
assert how in imp, how
|
||||
locale = (ROOT / "ui_template/ui_template_locale_m2_judge.ts").read_text(encoding="utf-8")
|
||||
assert 'M02_CheckImported: ["가져온 식으로 열기"' in locale
|
||||
|
||||
|
||||
def test_머리_판_결과_칩():
|
||||
panel = _src("Hopyo_ImportedPanel")
|
||||
for word in (
|
||||
"ToOurs",
|
||||
"ToExcel",
|
||||
"Source",
|
||||
"Link",
|
||||
"ToBase",
|
||||
"PickBase",
|
||||
"Need",
|
||||
"Same",
|
||||
"Diff",
|
||||
):
|
||||
assert f'tx("{word}")' in panel, word
|
||||
assert "newBadge()" in panel and "data-basis-tiers" in panel and "TIERS.map(" in panel
|
||||
assert 'f.setError(tx("Need"))' in panel # 입력 필요 = 붉은 칸
|
||||
model = (M02 / "logic/M02_Hopyo_Imported_Model.ts").read_text(encoding="utf-8")
|
||||
assert '["확정", "근접", "사람"]' in model and "필요: need" in model
|
||||
assert "입력 필요 ${need.length}" in model and '"가져온 식 있음"' in model
|
||||
rows = _src("Hopyo_CheckRows")
|
||||
assert "rowChips(ctx.kit.picksOf(row))" in rows and "dataset.judgeResult" in rows
|
||||
assert not re.search(r"from \"@ui|document\.|fetch\(|sessionStorage\.", model) # 순수
|
||||
|
||||
|
||||
def test_부품상자만_700줄_공용_안_고침():
|
||||
for name in MINE:
|
||||
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
|
||||
for name in ("Labor_Rows", "Labor_SangeunModal", "Sangeun_Detail", "Sangeun_Sheet"):
|
||||
assert "Hopyo_Imported" not in _src(name), name # 공용 쪽은 새 모달을 모름
|
||||
Reference in New Issue
Block a user