feat(M01): 조합 알약 키 「이름|단위」 · 쓰는 구조물 열이 있으면 조합 지우기 막음
- 알약 키를 첫 로직 코드에서 「이름|단위」 로 — 로직을 빼고 더하고 차례를 바꿔도 같은 물량이면 같은 키 - 조합 지우기 전 집계표 · 구조물집계표조합의 「일위대가」 칸을 훑어 쓰는 열이 있으면 409 + 구조물 이름들 - 시험 셋 더함(키 안 바뀜 · 쓰는 조합 못 지움 · 안 쓰는 조합 지워짐) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoyUwuTFiDJfvCfHpvKKzp
This commit is contained in:
@@ -8,16 +8,21 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
from config import config_system
|
||||
from M01_MasterData import M01_MasterData_Store as store
|
||||
|
||||
cm, mk, mcb = store.cm, store.mk, store.mcb
|
||||
|
||||
FILE = mcb.FILE
|
||||
OWNERS = mcb.OWNERS
|
||||
_MT = config_system.PROJECT_ROOT / "resources" / "master_template"
|
||||
# 조합을 쓰는 열이 적힌 곳 — 집계표(정본) · 구조물집계표조합(SS 장부) · 시험이 바꿈
|
||||
USERS = (_MT / "table" / "구조물집계표.json", _MT / "구조물집계표조합.json")
|
||||
|
||||
|
||||
def _path() -> Path:
|
||||
@@ -150,7 +155,8 @@ def combo_inputs(key: str) -> dict:
|
||||
"""조합 알약 — 담은 로직마다 결과단위 분모(원/㎥ → ㎥)가 물량 하나.
|
||||
|
||||
이름 = 로직 이름 끝 괄호 뗀 것(「(인력)」·「(장비)」 한 알약) · 같은 이름 · 단위면 합침 ·
|
||||
키 = 그 알약 첫 로직 키 · `배` = 분모 앞 수(원/10㎡ → 10 · 1 이면 안 줌) · 돈 아닌 로직은 빠짐.
|
||||
키 = 「이름|단위」(로직을 빼고 더하고 차례를 바꿔도 같은 물량이면 같은 키) ·
|
||||
`배` = 분모 앞 수(원/10㎡ → 10 · 1 이면 안 줌) · 돈 아닌 로직은 빠짐.
|
||||
`조건` 은 자리만(설계 조건 고르기 · 범위는 알약에 안 넣음).
|
||||
"""
|
||||
row = _find(_read()[0], key)
|
||||
@@ -168,7 +174,9 @@ def combo_inputs(key: str) -> dict:
|
||||
# ponytail: 분모가 여럿(「원/㎡ · 원/㎥(단위당 따름)」)이면 「㎡ · ㎥」 한 글 — 입력이 고름
|
||||
unit = " · ".join(dict.fromkeys(u for _, u in per))
|
||||
name = _TAIL.sub("", str(got.get("이름") or code)) or code
|
||||
pill = pills.setdefault((name, unit), {"키": code, "이름": name, "단위": unit, "로직": []})
|
||||
pill = pills.setdefault(
|
||||
(name, unit), {"키": f"{name}|{unit}", "이름": name, "단위": unit, "로직": []}
|
||||
)
|
||||
pill["로직"].append(code)
|
||||
times = per[0][0]
|
||||
if len(per) == 1 and times and float(times) != 1:
|
||||
@@ -207,9 +215,28 @@ def combo_edit(key: str, version: str, combo_: dict, owner: str = "") -> dict:
|
||||
return {**done, "combo": _find(store.read(FILE)[0], key)}
|
||||
|
||||
|
||||
def combo_users(key: str) -> list[str]:
|
||||
"""이 조합을 「일위대가」 로 쓰는 구조물 열 이름들 — 집계표 · SS 장부를 함께 봄."""
|
||||
names: dict[str, str] = {}
|
||||
for path in USERS:
|
||||
if not path.is_file():
|
||||
continue
|
||||
doc = json.loads(path.read_text(encoding="utf-8"))
|
||||
for col in doc.get("열") or doc.get("줄") or []:
|
||||
if col.get("일위대가") != key:
|
||||
continue
|
||||
head = col.get("머리") or [col.get(k) for k in ("종류", "분류1", "분류2", "분류3")]
|
||||
cid = str(col.get("id") or col.get("열"))
|
||||
names.setdefault(cid, " ".join(str(h) for h in head if h and str(h).strip()) or cid)
|
||||
return list(names.values())
|
||||
|
||||
|
||||
def combo_delete(key: str, version: str) -> dict:
|
||||
data, _ = _read()
|
||||
_find(data, key)
|
||||
if users := combo_users(key):
|
||||
msg = f"구조물 {len(users)} 곳이 쓰는 조합이라 못 지움 — {' · '.join(users)}"
|
||||
raise store.StoreError(409, {"errors": [msg], "users": users})
|
||||
if store.read(FILE)[1] != version:
|
||||
raise store.StoreError(409, {"stale": [FILE]})
|
||||
return _write([{"op": "delete", "key": key}], version)
|
||||
|
||||
Reference in New Issue
Block a user