feat(M01): PLAN 7-4b 뒤 절반 ④⑤ — 재료_품셈재료.json 을 old/ 로 옮김(MP 직접참조 다 걷음)
되돌렸던 옮기기를 마무리. 앞서 놓친 자리 — 호표 「요소」 칸만 훑어서 덧줄·수량 식 안에 그대로 박힌 MP 참조 16곳(집수정 뚜껑·철망태·쉬즈관·IV전선·백열등· 바퀴숫돌 넷·버너·노즐·테르밋용재·몰드·골무·퓨즈·용접봉)을 못 봤음 — 자재품목에 새 줄 일곱(값 미확보) · 기존 줄 셋(백열등·망태석·용접봉, 가장 맞는 것으로 이음)에 연결하고 식 안의 MP 키 문자열을 그 자재품목 키로 바로 바꿔치기(품셈재료 간접 없이). 재료_품셈재료.json 을 resources/master_data/old/ 로 옮김(지우지 않음) — check_master.load() 가 `*.json` 만 훑어 자동으로 빠짐(코드 안 고쳐도 검사·엔진 다 끊김) · build_품셈재료_고르기.py·build_로직_재료_고르기.py 는 다시 안 돌림(한 번 쓰고 마침). 시험 — 옛길(품셈재료 간접)이 죽지 않았는지 자체 마스터로 확인하는 시험 셋을 고쳐 남김(실화면 대신 합성 데이터) · 이제 못 보는 화면 기능(품셈재료 목록· 연결 안 된 줄 거르기) 시험 둘은 뺌(기능 자체가 오늘 사라짐) · 자재품목 분류 기대표에 새로 이은 것들 더함(스페이셔와 같은 이유로 이름 다른 셋 더 뺌). _틀.md — 재료_품셈재료 절을 「old/ 로 옮김·자료로만 둠」으로 고치고, 7장에 지역·계약종별 고르기 조건 칸을 추가. typecheck 통과 · 관련 시험 107 통과 · 로직 1354개 전수 대조 — 금액 달라짐 0 · 새로 멈춤 0 · 새로 통과 2(GC000374·GF000235, 덧줄 식이 못 풀던 것이 오늘 이어져 정상적으로 풀림). PLAN.md 는 이 워크트리에 7장이 없어(gitignore·기기별 파일) 체크 못 함 — 반복된 자리(문서에 이미 적음). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""마스터 데이터 검사 도구 — 견본 셋 손 계산 · 견본 파일 검사 통과 (`resources/master_data/scripts/check_master.py`)."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from decimal import ROUND_HALF_UP, Decimal
|
||||
from pathlib import Path
|
||||
@@ -432,8 +433,6 @@ def test_토목_보링_심도_가산():
|
||||
files["재료_자재품목.json"]["줄"].append(
|
||||
{"키": "MT999999", "원문번호": "가짜", "물가자료": Decimal(1000)}
|
||||
)
|
||||
for row in files["재료_품셈재료.json"]["줄"]:
|
||||
row["연결"] = row["연결"] or "MT999999" # 못 이은 재료 — 시험용 가짜 연결
|
||||
given = {"층": "점토층", "규격": "BX", "깊이": 35, "심도가산율": 5}
|
||||
got = mf.run(mf.Master(files), "GC000431", given)
|
||||
qty = {x["이름"]: x["수량"] for x in got["줄"]}
|
||||
@@ -695,20 +694,49 @@ def test_노임_갈래_파일_원문_대조():
|
||||
|
||||
|
||||
def test_품셈재료_연결_낮은_값과_출처(whole):
|
||||
"""연결 하나 — 값 열 다섯 가운데 낮은 값 · 출처 = 「<키>.<열>」."""
|
||||
"""연결 하나 — 값 열 다섯 가운데 낮은 값 · 출처 = 「<키>.<열>」.
|
||||
재료_품셈재료.json 은 PLAN 7-4b 뒤 절반이 old/ 로 옮겨 살아 있는 마스터엔 없음 —
|
||||
element() 의 옛길(품셈재료 간접)이 여전히 도는지 자체 마스터로 확인."""
|
||||
row = whole.get("MT004176") # 시멘트
|
||||
low = min(row[s] for s in mm.SLOTS if row.get(s) is not None)
|
||||
value, source = mf.element(whole, "MP:시멘트", {})
|
||||
files = cm.load(["재료_자재품목.json"]) | {
|
||||
"재료_품셈재료.json": {
|
||||
"그룹": "재료",
|
||||
"원문": "품셈재료",
|
||||
"줄": [{"키": "MP900001", "이름": "시멘트", "단위": "kg", "연결": "MT004176"}],
|
||||
}
|
||||
}
|
||||
value, source = mf.element(mf.Master(files), "MP900001", {})
|
||||
assert value == low and source.split(".")[0] == row["키"]
|
||||
|
||||
|
||||
def test_전력은_계약종별로_고름(whole):
|
||||
"""전력은 자재품목이 아니라 유가전력 줄 — 계약종별은 로직 입력 · 그 안에서 낮은 값."""
|
||||
"""전력은 자재품목이 아니라 유가전력 줄 — 계약종별은 로직 입력 · 그 안에서 낮은 값.
|
||||
옛길(품셈재료 연결이 계약종별 조건 묶음)로도 여전히 도는지 자체 마스터로 확인."""
|
||||
assert whole.index["MT"].get("MT000006") is None # 자재품목 전력 2줄 뺌
|
||||
files = cm.load(["재료_유가전력.json"]) | {
|
||||
"재료_품셈재료.json": {
|
||||
"그룹": "재료",
|
||||
"원문": "품셈재료",
|
||||
"줄": [
|
||||
{
|
||||
"키": "MP900002",
|
||||
"이름": "전력",
|
||||
"단위": "㎾h",
|
||||
"연결": {"이름": "전력량요금", "계약종별": "입력"},
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
linked = mf.Master(files)
|
||||
with pytest.raises(mf.FormulaError): # 계약종별 없이는 값이 안 섬
|
||||
mf.element(whole, "MP:전력", {})
|
||||
value, source = mf.element(whole, "MP:전력", {mf.TARIFF: "주택용 저압"})
|
||||
mf.element(linked, "MP900002", {})
|
||||
value, source = mf.element(linked, "MP900002", {mf.TARIFF: "주택용 저압"})
|
||||
assert value == 120 and source == "MO000058.값"
|
||||
# PLAN 7-4b 뒤 절반 — 호표에 조건 묶음을 바로 박아도 같은 길(품셈재료 간접 없이)
|
||||
cond = {"이름": "전력량요금", "계약종별": "입력"}
|
||||
value2, source2 = mf.element(whole, cond, {mf.TARIFF: "주택용 저압"})
|
||||
assert value2 == value and source2 == source
|
||||
|
||||
|
||||
def test_자재품목_열_한_벌():
|
||||
@@ -735,15 +763,31 @@ def test_자재품목_열_한_벌():
|
||||
|
||||
|
||||
def test_품셈재료_자재지역_후보(whole):
|
||||
"""지역 재료 — 입력 없음 · 그 지역 줄 없음 · 규격 여럿은 멈춤 · 하나면 낮은 값."""
|
||||
"""지역 재료 — 입력 없음 · 그 지역 줄 없음 · 규격 여럿은 멈춤 · 하나면 낮은 값.
|
||||
옛길(품셈재료 연결이 지역 조건 묶음)로도 여전히 도는지 자체 마스터로 확인."""
|
||||
files = cm.load(["재료_자재품목.json"]) | {
|
||||
"재료_품셈재료.json": {
|
||||
"그룹": "재료",
|
||||
"원문": "품셈재료",
|
||||
"줄": [
|
||||
{"키": "MP900003", "이름": "모래", "단위": "㎥", "연결": {"이름": "모래", "규격": "", "지역": "입력"}},
|
||||
{"키": "MP900004", "이름": "레미콘", "단위": "㎥", "연결": {"이름": "레미콘", "규격": "", "지역": "입력"}},
|
||||
],
|
||||
}
|
||||
}
|
||||
linked = mf.Master(files)
|
||||
with pytest.raises(mf.FormulaError, match="입력 「자재지역」 없음"):
|
||||
mf.element(whole, "MP:모래", {})
|
||||
mf.element(linked, "MP900003", {})
|
||||
with pytest.raises(mf.FormulaError, match="지역 값 없음"):
|
||||
mf.element(whole, "MP:모래", {"자재지역": "울진"})
|
||||
mf.element(linked, "MP900003", {"자재지역": "울진"})
|
||||
with pytest.raises(mf.FormulaError, match="후보 여럿"):
|
||||
mf.element(whole, "MP:레미콘", {"자재지역": "울진"})
|
||||
value, source = mf.element(whole, "MP:모래", {"자재지역": "수원"})
|
||||
mf.element(linked, "MP900004", {"자재지역": "울진"})
|
||||
value, source = mf.element(linked, "MP900003", {"자재지역": "수원"})
|
||||
assert source.startswith("MT") and value > 0
|
||||
# PLAN 7-4b 뒤 절반 — 호표에 조건 묶음을 바로 박아도 같은 길(품셈재료 간접 없이)
|
||||
cond = {"이름": "모래", "규격": "", "지역": "입력"}
|
||||
value2, source2 = mf.element(whole, cond, {"자재지역": "수원"}, "㎥")
|
||||
assert value2 == value and source2 == source
|
||||
|
||||
|
||||
# ── 재료 고르기 조건 (`_틀.md` 7장) ────────────────────────────────────
|
||||
@@ -955,13 +999,21 @@ def test_고르기_조건_글자_열쇠():
|
||||
assert mm.cond_text({"구분": "레미콘", "대표": "MT900002"}) == "레미콘||||MT900002||"
|
||||
|
||||
|
||||
def test_품셈재료_고르기_칸이_실파일에_있음():
|
||||
"""일괄 변환의 바탕 — 모든 품셈재료 줄에 고르기 칸 · 조건은 자재품목 묶음 안."""
|
||||
whole = cm.master()
|
||||
def test_품셈재료_고르기_칸이_옛_파일에_있음():
|
||||
"""일괄 변환의 바탕(옛 자료) — PLAN 7-4b 뒤 절반이 재료_품셈재료.json 을 old/ 로 옮겨
|
||||
이제 살아 있는 마스터엔 안 읽힘 — 옮기기 전 앞뒤 확인이 남긴 옛 자료 자체를 대고 봄."""
|
||||
market = cm.load(["재료_자재품목.json"])
|
||||
old_pm = json.loads(
|
||||
(cm.MASTER / "old" / "재료_품셈재료.json").read_text(encoding="utf-8"),
|
||||
parse_float=Decimal,
|
||||
parse_int=Decimal,
|
||||
)
|
||||
whole = mf.Master({**market, "재료_품셈재료.json": old_pm})
|
||||
rows = whole.index["MP"]
|
||||
assert rows and all("고르기" in row for row in rows.values())
|
||||
assert any(isinstance(row["고르기"], dict) for row in rows.values())
|
||||
assert cm.check_links(whole) == []
|
||||
assert cm.master().index.get("MP") is None # 살아 있는 마스터엔 이제 없음
|
||||
|
||||
|
||||
def test_로직_일괄_시험계산():
|
||||
|
||||
Reference in New Issue
Block a user