- 원인: 다시 고르기(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>
190 lines
8.9 KiB
Python
190 lines
8.9 KiB
Python
# 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)
|