Files
Aislo/M02_MasterTemplete/M02_Doc_MatchSk.py
T
eomsangdonandClaude Opus 5.5 26bf63b726 feat(810-4): 연결 찾기 엔진 — 가져온 식 ↔ 우리 M01 기초 · 확정일 때만 우리 기초 사본으로 바꾸기 · 되돌리기
- 새 M02_Doc_Match(서버 단독) — 후보(결과단위 · 노임 키 · 재료 · 기계 · 품셈 절 번호) · 옵션 풀이(줄 수량 · 단가가 의존하는 선택 · 입력 변수만 돌려 좁힘 · 글 근거 값 유지) · 줄 대조(같음 · 단가 차이 · 단위 환산 · 기계 규격 · 비목 · 율 값 · 율 줄 · 공구손료 유무 · 줄 없음 · 끝수 · 옵션 글) · 판정 확정(다른 항 0 · 원 단위 같음) / 근접 / 없음(가까운 후보 보이기만)
- 새 M02_Doc_MatchSk — 찾기 = SK 가져온.원본.연결후보 적음 · 바꾸기 = 서버가 다시 찾아 확정만 같은 키에 M01 사본 SK(바탕 · 입력값 = 찾은 옵션) · 원래 몸 = 가져온보관 · 되돌리기 · 근접 · 없음 409
- 길 POST /api/m02/layers/{층}/sangeun/{키}/match {할일 찾기 · 바꾸기 · 되돌리기}(층 쓰기)
- M02_Sangeun_Imported clean — 가져온보관 칸 받음 · M02_Doc_Import 형제 SK 가 우리 기초 사본이면 그 수식 문서로 셈(연결 안 끊김)
- 화면 — 원문 패널 「어디서 왔나」 카드 맨 위 판정 띠(띠 알림 부품) · 확정 = [우리 기초 사본으로 바꾸기] · 근접 · 없음 = 단추 없음 + 다른 항 자세히 · 안 찾음 = [우리 기초와 연결 찾기] · 바꾼 SK = [가져온 식으로 되돌리기] · 저장 안 한 고침 있으면 막음 · 끝나면 SK 다시 엶(새 판)
- 시험 test_810_4_match(판정 셋 · 요구 704 파형강관 Φ800 = GF000179 근접 · 단위 환산 × 6 · 기계 규격 · 율 줄 · 옵션 풀이 · 줄 대조 · 바꾸기 = M01 사본 셈 · 되돌리기 · 근접 409 · 형제 사본 · 전수 S8104_ALL) · helper_810_4_sweep
- 낡은 시험 글 대조 고침 — 717_2b(View 다시 엶 mount) · 750_2(createSangeunSide(opt.match)) · 807_1(원문 패널에 SK 문서 넘김)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 21:52:41 +09:00

105 lines
4.6 KiB
Python

"""가져온 식 SK ↔ 우리 M01 기초 — 연결 찾기 기록 · 「확정」 때만 우리 기초 사본으로 바꾸기 · 되돌리기
(PLAN 810-4 · 요구 707 · 708 · 709 · 703) — 서버 단독.
찾기(`find`) = 가져온 식 문서(우리 단가로 셈) → `M02_Doc_Match.match` → SK `가져온.원본.연결후보` 에 적음.
바꾸기(`swap`) = 서버가 다시 찾아 「확정」 일 때만 — 같은 SK 키에 M01 사본 SK(바탕 = 그 기초 ·
입력값 = 찾은 옵션 · 802-4a 꼴 · 수식 사본은 저장 때 서버가 찍음)를 씀 · 원래 가져온 식 SK 몸은
`가져온보관` 칸에 그대로 둠 · 일위대가 줄 참조 = 키 그대로(SK 내용만 바뀜 → 금액 다시 셈).
되돌리기(`back`) = `가져온보관` 몸을 그 키에 다시 씀(가져온 식 금액 그대로).
우리 M01 기초는 어느 갈래에서도 안 바뀜(708) · 근접 · 없음 = 바꾸기 409(703).
"""
from __future__ import annotations
from typing import Any
from common_util.common_util_time import utc_now_text
from M02_MasterTemplete import M02_Doc_Copy as dc
from M02_MasterTemplete import M02_Doc_Import as dim
from M02_MasterTemplete import M02_Doc_Match as dm
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from M02_MasterTemplete import M02_Sangeun_Doc as sd
from M02_MasterTemplete import M02_Sangeun_Imported as imp
KEEP = "가져온보관" # 바꾼 SK 의 원래 가져온 식 몸(되돌리기)
_INDEX: dict[str, Any] = {"문서": None, "색인": None}
def _bad(why: str, status: int = 400) -> store.StoreError:
return store.StoreError(status, why)
def index() -> dm.Index:
"""M01 수식 문서 색인 — 폴더가 바뀌면(M01 관리자 고침) 다시."""
docs = dc.folder()
if _INDEX["문서"] is not docs:
_INDEX["문서"], _INDEX["색인"] = docs, dm.Index(docs)
return _INDEX["색인"]
def _read(key: str) -> dict[str, Any]:
if not sd.KEY.match(str(key or "")):
raise _bad("키(SK-######)")
return store.read(sd.KIND, key)
def judge(sk: dict) -> dict[str, Any]:
"""가져온 식 SK → 연결후보(저장 없음)."""
whole = imp._whole()
links_imp = dim.Links(whole, "우리")
doc = dim.of(sk)
links_imp.learn(doc)
got = dm.match(doc, links_imp, index(), dm.ml.Links(whole, dc.folder()))
return {**got, "때": utc_now_text()}
def find(key: str, version: str) -> dict[str, Any]:
"""연결 찾기 → SK `가져온.원본.연결후보` 에 적음 → {연결후보, 판}."""
got = _read(key)
sk = got["문서"]
if not dim.is_imported(sk):
raise _bad("가져온 식 단가산출만 연결을 찾음")
found = judge(sk)
meta = sk[imp.KEY]
new = {**sk, imp.KEY: {**meta, "원본": {**(meta.get("원본") or {}), dm.KEY: found}}}
info = store.write(sd.KIND, key, version or got["판"], new)
return {dm.KEY: found, "판": info.get("판")}
def copy_body(sk: dict, found: dict) -> dict[str, Any]:
"""M01 사본 SK 몸(이름 · 단위 · 구분 그대로 · 바탕 = 찾은 기초 · 입력값 = 찾은 옵션)."""
keep = {k: sk.get(k) for k in ("키", "이름", "단위", "구분", "상세구분") if sk.get(k)}
old = {k: v for k, v in sk.items() if k not in ("키", "종류", KEEP)}
body = {
"덮개": {},
"뺀줄": [],
"더한줄": [],
"고름": {},
"자재표시": {},
} # M01 그대로(고침 없음)
base = {"바탕": {"로직": found["키"]}, "입력값": dict(found.get("옵션") or {})}
return {**keep, **body, **base, KEEP: old}
def swap(key: str, version: str) -> dict[str, Any]:
"""「확정」 일 때만 우리 기초 사본으로 — 서버가 다시 찾음(화면 판정을 믿지 않음)."""
got = _read(key)
sk = got["문서"]
if not dim.is_imported(sk):
raise _bad("가져온 식 단가산출만 바꿈")
found = judge(sk)
if found.get("판정") != dm.SURE:
raise _bad(f"우리 기초와 「확정」 일치가 아님({found.get('판정')}) — 바꾸지 않음", 409)
info = store.write(sd.KIND, key, version or got["판"], copy_body(sk, found))
return {dm.KEY: found, "판": info.get("판")}
def back(key: str, version: str) -> dict[str, Any]:
"""우리 기초 사본 → 원래 가져온 식(보관 몸 그대로)."""
got = _read(key)
old = got["문서"].get(KEEP)
if not isinstance(old, dict) or not old.get(imp.KEY):
raise _bad("되돌릴 가져온 식 없음")
info = store.write(sd.KIND, key, version or got["판"], {**old, "키": key})
return {"판": info.get("판")}