Files
Aislo/resources/tester/test_823_1_imported_swap.py
T
eomsangdonandClaude Opus 5.5 8bb22b39b1 fix(823-1): 불러온 단가산출 기계 바꿔 끼움 = 그 줄만 우리 값 즉시 · 바꿈 표시 · 되돌리기
- 원인: 다시 고르기(repick)가 엑셀 값 기억을 일부러 남김(812-9) → 엑셀 단가 기준 보기가 바꾼 기계 줄도 옛 엑셀 값으로 셈 · 이름만 바뀜
- 이은 가져온 줄을 다른 것으로 = 엑셀 값 뗌 · 연결 `바꿈` = 원래 연결 · 이름 · 규격 · 원래 것 다시 고름 = 되돌림 · 못 이은 줄 고름(812-9)은 그대로
- 줄에 「바꿈」 배지 + [되돌리기] · 머리 「바꾼 줄 n — 원본과 다름」 · 인력 · 재료 바꿈도 같은 길
- 서버: 바꾼 줄 있으면 셈 색인 = 로직 사본 위 · 저장 때 셈이 읽은 줄(내 기계 등)을 로직 사본에 박음(822-1 사본 규칙)
- 옛 칸 지문: 파일 24554.0 = 화면 왕복 24554 — 가져온 식 수식 저장 뒤 페이지 [저장] 409(「그 사이 양식이 바뀜」) 막음
- 시험 test_823_1_imported_swap 5(+ 헬퍼 helper_823_1_swap.cjs)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 18:54:16 +09:00

190 lines
8.9 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.
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
"""823-1 불러온 단가산출 바꿔 끼움(요구 800-1 · 801-1) — 임시 storage.
엑셀 단가 기준에서 이은 기계 줄을 다른 기계로 = 그 줄만 우리 값(엑셀 값 뗌 · `바꿈` = 원래) ·
다른 줄 엑셀 값 그대로 · 되돌리기 · 원래 것 다시 고름 = 되돌림 · 내 기계로 ·
저장 뒤 로직 사본에 박힘 · 「바꾼 줄 n」 · 인력 바꿈 같은 길 ·
못 이은 기계 고름(812-9) = 엑셀 값 그대로 · 옛 칸 지문 24554.0 = 24554.
"""
from __future__ import annotations
import copy
import json
import os
import subprocess
from M02_MasterTemplete import M02_Doc_Copy as dc
from M02_MasterTemplete import M02_Doc_Import as dim
from M02_MasterTemplete import M02_Doc_Sk as dsk
from M02_MasterTemplete import M02_Doc_Sk_Path as path
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from M02_MasterTemplete import M02_MyMachine as mym
from M02_MasterTemplete import M02_Sangeun_Imported as imp
from resources.tester.test_822_1_copy_gap import _move
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
HERE = os.path.dirname(__file__)
DIG = "GC000267" # 굴착기 시간당 경비
NOW, NEW, NEW_EQ = "'0201-0070'", "'0201-0100'", "EQ000022" # 0.7㎥ → 1.0㎥
XL = {"노무비": 59020, "재료비": 19473, "경비": 24554}
MAN, MAN2 = "LB000002", "LB000001" # 보통인부 → 다른 직종
def _at(folder, fn, *args):
with store.at(folder):
return fn(*args)
def _ts(doc: dict, steps: list[dict]) -> list[dict]:
proc = subprocess.run(
["node", os.path.join(HERE, "helper_823_1_swap.cjs")],
input=json.dumps(
dc.ml._norm({"문서": doc, "걸음": steps}), ensure_ascii=False, default=str
),
capture_output=True,
text=True,
encoding="utf-8",
)
assert proc.returncode == 0, proc.stderr[-3000:]
return json.loads(proc.stdout)
def _made(folder) -> tuple[str, dict]:
"""가져온 식 SK — 기계 줄(GC000267 0.7㎥ · 엑셀 묶음) + 인력 줄(보통인부 · 엑셀 단가)."""
mach = {
"종류": "로직", "이름": "굴착기(무한궤도)", "규격": "0.7㎥", "단위": "hr", "수량": "0.1",
"값묶음": XL, "이음": f"로직({DIG}, 기계={NOW}, 지역='전국평균', 보정작업='해당 없음')",
} # fmt: skip
man = {"종류": "인력", "이름": "보통인부", "단위": "인", "수량": "0.5", "비목": "노무비",
"단가": 165545, "이음": MAN} # fmt: skip
row = {"이름": "sub3임시 바꿈", "결과단위": "원/㎥", "호표": [mach, man]}
key = _at(folder, lambda: imp.create(row, None, "sub3임시 바꿈")["이름"])
return key, _at(folder, path.read, key)
def _vars(doc: dict) -> dict:
return {dc.md.var_id(v): v for v in doc["변수"]}
def _sym(doc: dict, kind: str) -> tuple[int, str]:
"""(금액 줄 차례, 단가 기호) — 기계 = 단가산출 연결 · 인력 = 요소 연결."""
by = _vars(doc)
for i, line in enumerate(doc["금액"]):
var = by.get(str(line.get("단가")))
if var and (var["연결"].get("갈래") == ("단가산출" if kind == "기계" else "요소")):
return i, dc.md.var_id(var)
raise AssertionError(kind)
def _lines(ans: dict) -> list:
return [None if x.get("금액") is None else float(x["금액"]) for x in ans.get("줄") or []]
def _pick(i, sym, kind, key, name, spec="", **given):
p = {"키": key, "이름": name, **({"규격": spec} if spec else {})}
p |= {"입력": given} if given else {}
return {"고름": {"i": i, "id": sym, "kind": kind, "p": p}}
def test_swap_machine_excel_basis(world, monkeypatch):
"""기계 0.7 → 1.0㎥ = 그 줄 우리 값 · 인력 줄 엑셀 그대로 · TS 보기 = 서버 보기 ·
되돌리기 · 원래 것 다시 고름."""
me = world["personal"]
key, got = _made(me)
doc, was = got["문서"], got["셈"]
i, sym = _sym(doc, "기계")
j, man = _sym(doc, "인력")
steps = _ts(
doc,
[
_pick(i, sym, "기계", DIG, "굴착기(무한궤도)", "1.0㎥", 기계=NEW),
{"되돌림": {"i": i, "id": sym}},
_pick(i, sym, "기계", DIG, "굴착기(무한궤도)", "1.0㎥", 기계=NEW),
_pick(i, sym, "기계", DIG, "굴착기(무한궤도)", "0.7㎥", 기계=NOW),
],
)
swapped = steps[0]["문서"]
link = _vars(swapped)[sym]["연결"]
assert steps[0]["바꾼줄"] == 1 and "엑셀" not in link and link["입력"]["기계"] == NEW
assert link["바꿈"]["연결"]["엑셀"] == XL and link["바꿈"]["규격"] == "0.7㎥"
# TS 엑셀 보기 = 서버 보기(짝) — 바꾼 줄 = 연결 · 인력 = 숫자
assert dc.ml._norm(steps[0]["엑셀보기"]) == dc.ml._norm(dim.view(swapped, "엑셀"))
assert _vars(steps[0]["엑셀보기"])[man]["연결"]["갈래"] == "숫자"
# 서버 미리 셈 — 기계 줄 = 우리 값(1.0㎥) · 인력 줄 엑셀 그대로
look = _at(me, path.preview, key, {"문서": swapped})["셈"]
sk = _at(me, lambda: store.read("sangeun", key)["문서"])
ours = dim.run(swapped, {**sk, "가져온": {**sk["가져온"], "단가기준": "우리"}})
assert _lines(look)[i] == _lines(ours)[i] != _lines(was)[i]
assert _lines(look)[j] == _lines(was)[j]
assert look["계"] != was["계"]
# 되돌리기 · 원래 것 다시 고름 = 처음 문서 그대로
for at in (1, 3):
assert steps[at]["바꾼줄"] == 0
assert dc.ml._norm(steps[at]["문서"]) == dc.ml._norm(doc)
# 저장 → 다시 읽음 그대로 · 바꾼 기계 줄이 로직 사본에 · M01 가격 바뀌어도 그대로
판 = _at(me, path.read, key)["판"]
_at(me, path.save, key, {"문서": swapped, "판": 판})
again = _at(me, path.read, key)
assert again["셈"]["계"] == look["계"] and dim.swapped(again["문서"]) == 1
kept = _at(me, lambda: store.read("sangeun", key)["문서"]["사본"])
assert NEW_EQ in {r["키"] for r in [*kept["로직"], *kept["단가"]]}
_move(monkeypatch, NEW_EQ)
assert _at(me, path.read, key)["셈"]["계"] == look["계"]
def test_swap_to_my_machine(world):
"""내 기계로 바꿔 끼움 = 그 내 기계 시간당 값 · 저장 뒤 사본에."""
me = world["personal"]
made = _at(me, mym.create, {"이름": "sub3임시기계", "규격": "1㎾", "방식": "바로",
"값": {"가격": 1000, "손료계수": 2000}}) # fmt: skip
row = made["줄"]
key, got = _made(me)
doc = got["문서"]
i, sym = _sym(doc, "기계")
arg = f"'{row['원문번호']}'"
steps = _ts(doc, [_pick(i, sym, "기계", mym.logic_key(row), row["이름"], 기계=arg)])
swapped = steps[0]["문서"]
assert steps[0]["바꾼줄"] == 1
look = _at(me, path.preview, key, {"문서": swapped})["셈"]
hour = made["시간당"]["계"]
assert abs(_lines(look)[i] - hour * 0.1) < 1 # 수량 0.1 × 시간당
판 = _at(me, path.read, key)["판"]
_at(me, path.save, key, {"문서": swapped, "판": 판})
kept = _at(me, lambda: store.read("sangeun", key)["문서"]["사본"])
assert row["키"] in {r["키"] for r in [*kept["로직"], *kept["단가"]]}
def test_swap_labor_same_way(world):
"""인력 직종 바꿔 끼움 = 같은 길(바꿈 · 우리 값 · 되돌리기)."""
me = world["personal"]
key, got = _made(me)
doc, was = got["문서"], got["셈"]
j, man = _sym(doc, "인력")
steps = _ts(doc, [_pick(j, man, "인력", MAN2, "다른 직종"), {"되돌림": {"i": j, "id": man}}])
link = _vars(steps[0]["문서"])[man]["연결"]
assert steps[0]["바꾼줄"] == 1 and "엑셀" not in link and link["바꿈"]["연결"]["키"] == MAN
look = _at(me, path.preview, key, {"문서": steps[0]["문서"]})["셈"]
assert _lines(look)[j] != _lines(was)[j]
assert dc.ml._norm(steps[1]["문서"]) == dc.ml._norm(doc)
def test_unlinked_machine_pick_keeps_excel(world):
"""못 이은 가져온 기계 줄(숫자 연결) 고름 = 이음(812-9) — 엑셀 값 그대로 · 바꿈 아님."""
me = world["personal"]
_, got = _made(me)
doc = copy.deepcopy(got["문서"])
i, sym = _sym(doc, "기계")
_vars(doc)[sym]["연결"] = {"갈래": "숫자", "값": XL}
steps = _ts(doc, [_pick(i, sym, "기계", DIG, "굴착기(무한궤도)", "0.7㎥", 기계=NOW)])
link = _vars(steps[0]["문서"])[sym]["연결"]
assert steps[0]["바꾼줄"] == 0 and link["엑셀"] == XL and "바꿈" not in link
def test_old_fp_float_roundtrip():
"""파일 24554.0 · 화면 왕복 24554 = 같은 옛 칸 지문(페이지 [저장] 409 막음)."""
one = {"가져온": {"로직": {"호표": [{"자원": {"단가": {"S": 24554.0, "q": 0.5}}}]}}}
two = {"가져온": {"로직": {"호표": [{"자원": {"단가": {"S": 24554, "q": 0.5}}}]}}}
one["가져온"]["단가기준"] = two["가져온"]["단가기준"] = "엑셀"
assert dsk.old_fp(one) == dsk.old_fp(two)