diff --git a/resources/tester/test_812_9_machine_link.py b/resources/tester/test_812_9_machine_link.py index cf0985253..8fa2870c9 100644 --- a/resources/tester/test_812_9_machine_link.py +++ b/resources/tester/test_812_9_machine_link.py @@ -24,7 +24,14 @@ for p in (ROOT, HERE): from M02_MasterTemplete import M02_Elem_Alias as ea # noqa: E402 from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402 -from test_815_1_import_link import aliases # noqa: E402 — M01 별칭 칸 임시 +from test_815_1_import_link import aliases, no_aliases # noqa: E402 — M01 별칭 칸 임시 + + +@pytest.fixture(autouse=True) +def _blank_aliases(): + """진짜 마스터 기계 별칭 내용 · 수와 무관 — 별칭이 필요한 시험은 스스로 넣음.""" + with no_aliases("EQ"): + yield def one(name: str, spec: str = "") -> tuple[str, str, str]: @@ -160,10 +167,11 @@ def test_combo_many_part() -> None: def test_alias_first_master_column() -> None: """마스터 기계 줄 「별칭」 칸(815-2 옮김) — 이름만 별칭 = 그 기종 → 규격으로 하나 · 통째 별칭 · 할증 글 · 후보 여럿 = `test_815_1_import_link.test_alias_machine`.""" - got = mf.find("아스팔트페이버(피니셔)", "3.0m") - assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == ( - mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip - assert mf.find("크레인(트럭)", "10Ton")["판정"] == mf.MANY + with aliases("EQ", FIVE): # 다섯만 넣음(더 있어도 비워져 있음) + got = mf.find("아스팔트페이버(피니셔)", "3.0m") + assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == ( + mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip + assert mf.find("크레인(트럭)", "10Ton")["판정"] == mf.MANY # 크레인 별칭은 비움 · 여럿 def test_combo_money_same() -> None: diff --git a/resources/tester/test_815_1_import_link.py b/resources/tester/test_815_1_import_link.py index 9f5677f95..9db3f4ed5 100644 --- a/resources/tester/test_815_1_import_link.py +++ b/resources/tester/test_815_1_import_link.py @@ -60,6 +60,11 @@ def aliases(table: str, pairs: dict[str, str]): clear() +def no_aliases(table: str): + """그 표 별칭 칸을 시험 동안 모두 비움 — 진짜 마스터에 별칭이 더 들어가도 시험이 안 흔들림.""" + return aliases(table, {k: "" for k in ea.book()["줄"][table]}) + + # ── 별칭 풀이 ───────────────────────────────────────────────────────────── def test_alias_names_rule() -> None: assert am.names("") == [] and am.names(None) == [] @@ -99,16 +104,20 @@ def test_est_code_first() -> None: # ── K2 별칭 → 요소 ─────────────────────────────────────────────────────────── def test_alias_machine() -> None: - assert mf.find("에어 호스", "1.91cm")["판정"] == mf.NONE - with aliases("EQ", {"EQ000129": '"크레인(트럭) 15Ton"', "EQ000193": "아스팔트페이버(피니셔)"}): + with no_aliases("EQ"): + assert mf.find("에어 호스", "1.91cm")["판정"] == mf.NONE + assert mf.find("크레인(트럭)", "15Ton")["판정"] != mf.ALIAS # 별칭 전 + with ( + no_aliases("EQ"), + aliases("EQ", {"EQ000129": '"크레인(트럭) 15Ton"', "EQ000193": "아스팔트페이버(피니셔)"}), + ): got = mf.find("크레인(트럭)", "15Ton") # 이름 + 규격 통째 별칭 = 그 EQ assert (got["판정"], got["키"]) == (mf.ALIAS, "EQ000129") assert mf.find("크레인(트럭)", "15Ton(할증125%)")["키"] == "EQ000129" # 할증 글 안 봄 got = mf.find("아스팔트페이버(피니셔)", "3.0m") # 이름 별칭 = 그 기종 → 규격으로 하나 assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == (mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip - with aliases("EQ", {"EQ000129": "크레인 갑", "EQ000130": "크레인 갑"}): + with no_aliases("EQ"), aliases("EQ", {"EQ000129": "크레인 갑", "EQ000130": "크레인 갑"}): assert mf.find("크레인 갑")["판정"] == mf.MANY # 같은 별칭 둘 = 후보 여럿 - assert mf.find("크레인(트럭)", "15Ton")["판정"] != mf.ALIAS # 되돌림 def test_alias_material() -> None: diff --git a/resources/tester/test_815_2_alias_column.py b/resources/tester/test_815_2_alias_column.py index 4907feef4..c6e766b78 100644 --- a/resources/tester/test_815_2_alias_column.py +++ b/resources/tester/test_815_2_alias_column.py @@ -104,7 +104,8 @@ def test_M01_길은_시스템_관리자만() -> None: def test_마스터_기계_별칭_다섯_옮김_장부_걷음() -> None: rows = {r["키"]: r for r in json.loads((REAL / MACHINE).read_text(encoding="utf-8"))["줄"]} - assert {k: r.get("별칭") for k, r in rows.items() if r.get("별칭")} == FIVE + have = {k: r.get("별칭") for k, r in rows.items() if r.get("별칭")} + assert FIVE.items() <= have.items() # 다섯이 들어 있음 · 사용자가 더 넣어도 통과 assert not (ROOT / "resources" / "master_template" / "실무자료" / "맞춤.json").exists() @@ -137,8 +138,9 @@ def _alias_app(role: str = "SYSTEM_ADMIN") -> TestClient: def test_모아_보기_다섯_수기_넣은_것_바로(copy: Path, suggest_file: Path) -> None: client = _alias_app() rows = client.get("/api/m01/alias").json()["줄"] - assert {r["키"]: r["별칭"] for r in rows if r["갈래"] == "기계"} == FIVE - assert all(r["들어옴"] == "수기" for r in rows) + machine = {r["키"]: r["별칭"] for r in rows if r["갈래"] == "기계"} + assert FIVE.items() <= machine.items() # 다섯이 들어 있음 · 더 있어도 통과 + assert all(r["들어옴"] == "수기" for r in rows if r["키"] in FIVE) one = next(r for r in rows if r["키"] == "EQ000248") assert [p["글"] for p in one["조각"]] == ["바이브레이트 봉상후렉시블"] res = client.post("/api/m01/alias/save", json={"키": "LB000001", "별칭": "시험A,시험B"}) diff --git a/resources/tester/test_816_1_dump_1ton.py b/resources/tester/test_816_1_dump_1ton.py index 2d60b8358..5aeec06bb 100644 --- a/resources/tester/test_816_1_dump_1ton.py +++ b/resources/tester/test_816_1_dump_1ton.py @@ -22,6 +22,7 @@ from M01_MasterData import M01_MasterData_Store as m01 # noqa: E402 from M02_MasterTemplete import M02_Doc_Import as di # noqa: E402 from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402 from M02_MasterTemplete import M02_Machine_Hourly as mh # noqa: E402 +from test_815_1_import_link import no_aliases # noqa: E402 — M01 별칭 칸 임시 ml = importlib.import_module("master_doc_link") mc = importlib.import_module("master_doc_calc") @@ -58,6 +59,11 @@ def test_gf145_reads_price() -> None: def test_find() -> None: + with no_aliases("EQ"): # 진짜 마스터 별칭 있든 없든 같은 결과 + _find() + + +def _find() -> None: for spec in ("1.0Ton", "1톤", "1ton"): got = mf.find("덤프트럭", spec) assert got["키"] == NEW and got["판정"] == mf.LINKED, spec diff --git a/resources/tester/test_816_2_machine_parts.py b/resources/tester/test_816_2_machine_parts.py index 12e74aaf0..25e6e6f7b 100644 --- a/resources/tester/test_816_2_machine_parts.py +++ b/resources/tester/test_816_2_machine_parts.py @@ -15,6 +15,8 @@ import sys from functools import lru_cache from pathlib import Path +import pytest + ROOT = Path(__file__).resolve().parents[2] HERE = Path(__file__).resolve().parent for p in (ROOT, HERE): @@ -27,10 +29,19 @@ from M02_MasterTemplete import M02_San_Emit as em # noqa: E402 from M02_MasterTemplete import M02_San_Estx as estx # noqa: E402 from M02_MasterTemplete import M02_San_Xlsx as sx # noqa: E402 +from test_815_1_import_link import aliases, no_aliases # noqa: E402 — M01 별칭 칸 임시 + MAIN = ROOT / "resources/knowledge/original/경쟁사 프로그램/EST Plus 2/다산소프트/2026-07-main.estx" COMBO = ("대형브레이카", "+굴착기(1.0㎥)") +@pytest.fixture(autouse=True) +def _blank_aliases(): + """같은 파일 대조는 별칭이 없는 상태에서 봄 — 진짜 마스터 별칭 내용 · 수와 무관.""" + with no_aliases("EQ"): + yield + + @lru_cache(maxsize=1) def _tables() -> dict: return estx.tables(MAIN.read_bytes()) @@ -68,6 +79,13 @@ def test_samples() -> None: assert got[0]["까닭"].startswith(mf.MADE) and "크레인(타이어)" in got[0]["까닭"] +def test_alias_first() -> None: + """별칭이 있으면 같은 파일 대조보다 먼저(크레인(트럭) 10Ton 별칭 = EQ000128) · 별칭 없으면 여럿.""" + assert _keys("크레인(트럭)", "10Ton", None) == [(mf.MANY, None)] + with aliases("EQ", {"EQ000128": '"크레인(트럭) 10Ton"'}): + assert _keys("크레인(트럭)", "10Ton", None) == [(mf.ALIAS, "EQ000128")] + + def test_file_values_only() -> None: """파일 값이 우리 표와 달라도 같은 파일 대조로 가름 · 우리 표 값과 같아도 같은 파일에 짝 없으면 그대로.""" odd = {"손료": [[9999.0, 1.0]], "주연료": 1.0, "조종원": True} # 우리 표에 없는 값 diff --git a/resources/tester/test_816_3_chainsaw.py b/resources/tester/test_816_3_chainsaw.py index f47169922..ebf7fc2ec 100644 --- a/resources/tester/test_816_3_chainsaw.py +++ b/resources/tester/test_816_3_chainsaw.py @@ -1,7 +1,7 @@ """816-3 지킴 — 가져온 「엔진톱」 = 우리 체인톱 EQ000620(요구 771 · 방향 장부 N2). -(a) 별칭 길 — 사용자가 EQ000620 「별칭」 칸에 「엔진톱 18", 엔진톱」 을 넣으면(시험 = 임시 별칭 · 마스터엔 - 안 넣음) 인치 따옴표가 깨지지 않고 「엔진톱 18"」 · 「엔진톱」(규격 빔) → EQ000620 · 다른 톱 · 다른 규격은 안 이음 +(a) 별칭 길 — 사용자가 EQ000620 「별칭」 칸에 「엔진톱 18", 엔진톱」 을 넣으면(시험 = 임시 별칭 · 진짜 마스터 + 별칭은 시험 안에서 비움) 인치 따옴표가 깨지지 않고 「엔진톱 18"」 · 「엔진톱」(규격 빔) → EQ000620 · 다른 톱 · 다른 규격은 안 이음 (b) 시간당 = GF000337 「체인톱 시간당 기계경비」 = 산림품셈 1 일 1 대당(2-1-1 휘발유 · 체인오일 · 잡품 · 2-2-1 손료) ÷ 8 — GF000076 체인톱 줄(1 일 1 대당) 단가 그대로 · 수량 × 시간환산 (c) 이음 한 길 — `M02_Machine_Hourly.hourly` · `M02_Doc_Import.hourly_link` = GF000337(기계 입력 없음) @@ -23,7 +23,7 @@ from M01_MasterData import M01_MasterData_Store as m01 # noqa: E402 from M02_MasterTemplete import M02_Doc_Import as di # noqa: E402 from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402 from M02_MasterTemplete import M02_Machine_Hourly as mh # noqa: E402 -from test_815_1_import_link import aliases # noqa: E402 — M01 별칭 칸 임시 +from test_815_1_import_link import aliases, no_aliases # noqa: E402 — M01 별칭 칸 임시 ml = importlib.import_module("master_doc_link") mc = importlib.import_module("master_doc_calc") @@ -37,11 +37,11 @@ def _calc(key: str) -> dict: def test_alias() -> None: am = importlib.import_module("master_alias") - assert not m01.loaded()[1].get(SAW).get("별칭") # 별칭 값 = 사용자 몫 - assert mf.find("엔진톱", '18"')["키"] is None + with no_aliases("EQ"): # 진짜 마스터 별칭 있든 없든 — 별칭 전 = 못 이음 + assert mf.find("엔진톱", '18"')["키"] is None for text in ('엔진톱 18", 엔진톱', '"엔진톱 18"", 엔진톱'): assert am.names(text) == ['엔진톱 18"', "엔진톱"], text - with aliases("EQ", {SAW: '엔진톱 18", 엔진톱'}): + with no_aliases("EQ"), aliases("EQ", {SAW: '엔진톱 18", 엔진톱'}): for name, spec in (("엔진톱", '18"'), ("엔진톱", ""), ("엔진톱", '18 "')): got = mf.find(name, spec) assert (got["판정"], got["키"]) == (mf.ALIAS, SAW), (name, spec)