feat(780-1): 일위대가 밖 단가산출도 판정 · 확인 · 칠 — 모든 블록 · 부름 칸 · 빈 블록 「줄 없음」(요구 627)
- Sangeun: 판정 · 확인 몸 = 모든 블록(북부청 임도 49 → 95) · 줄마다 `부름 [호표 번]`([] = 일위대가 밖) · 밖 블록 = 이름 · 단위 블록 것 · 근거 없음 · 없는 번만 404 · 하위 밖 블록(울진소광 492 → 83)은 확인 목록에 함께 = 하위 먼저 - SkUnit: 줄 0 블록 = 판정 「줄 없음」 고를줄 1 → 확인해도 못만듦(빈 SK 없음) - Marks: 블록마다 `부름` · `줄` · `어긋남` = 모든 블록(밖 포함) · 맞춤셈 `판정` 밖 = None 그대로 - 시험 고침(낡은 기대 = 일위대가 안 블록만): 778-5 units 49 → 95(안 49 따로) · 779-2 어긋남 + 밖 4 · 44 · 48 · 77 · 78 · 779-5 줄 칠 모든 블록 · 778-5 excel misses 밖 블록 5 · 새 시험 test_780_1_sangeun_outside(밖 확인 · 빈 블록 · 울진소광 · 여덟 파일 459) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"""M02 불러오기 엑셀 보기 하이라이트 재료(PLAN 779-2 · 요구서 621 3장 5) — 읽기만(파일 · storage 변화 0).
|
||||
|
||||
블록 `[{번, 판정, SK, 갈래, 못옮김}]` = 단가산출 만들기 결과(`Sangeun.made`) + 맞춤셈 캐시(`Fit.result`)를 읽기만.
|
||||
블록 `[{번, 판정, SK, 갈래, 못옮김, 부름}]` = 단가산출 만들기 결과(`Sangeun.made`) + 맞춤셈 캐시(`Fit.result`)를 읽기만.
|
||||
- `판정` = 그 블록을 부르는 첫 줄의 맞춤셈 판정 상태(맞음 · 다른 점 · 후보 …) · 안 불리거나 셈 전이면 None
|
||||
- `부름` = 부르는 호표 번 [] = 일위대가 밖(780-1) · `어긋남` · `줄` = 모든 블록(밖 포함)
|
||||
- `SK` = 만든 SK 키 · 없으면 None / `갈래` · `못옮김` = 그 SK 본뜬(출처별) · 없으면 None · []
|
||||
줄 상태는 `Match.view` 호표마다 `줄상태 [[차례, 상태, 체크]]` · `만든`(SC 키)로 실려 감.
|
||||
|
||||
@@ -127,7 +128,8 @@ def blocks(folder: Path, key: str, to: Path | None = None) -> list[dict[str, Any
|
||||
cache = (fit.result(folder, key) or {}).get("블록") or {}
|
||||
have = sangeun.made(to, key, here)
|
||||
all_, first = sangeun.calls(hp)
|
||||
units = hunits.Units() if first else None
|
||||
units = hunits.Units() if all_ else None
|
||||
call = sangeun.callers(hp)
|
||||
out = []
|
||||
for no in sorted(all_):
|
||||
line = first.get(no)
|
||||
@@ -142,8 +144,9 @@ def blocks(folder: Path, key: str, to: Path | None = None) -> list[dict[str, Any
|
||||
"SK": sk,
|
||||
"갈래": origin.get("갈래"),
|
||||
"못옮김": origin.get("못옮김") or [],
|
||||
"어긋남": misses(all_[no]) if line else None,
|
||||
"줄": lines(all_[no], units) if line and units else [],
|
||||
"부름": call.get(no, []),
|
||||
"어긋남": misses(all_[no]),
|
||||
"줄": lines(all_[no], units) if units else [],
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
SK = 이름 블록 이름(없으면 줄 품명) · 단위 = 줄 단위(없으면 블록 · 「식」) · 구분 「실무자료」 · 상세구분 = 파일 ·
|
||||
바탕 없음 · 본뜬 = {층 「실무자료」, 키 「HP-###### 단산N」, 파일, 원본, 확인, 갈래 「단위」, 근거 {로직, 이름}, 못옮김 []} ·
|
||||
같은 본뜬(키 · 원본)이 이 층에 있으면 그 키에 덮음 · 만드는 층 = 부르는 층.
|
||||
판정 · 확인 = 모든 블록(780-1 · 요구 627) — 일위대가가 부르는 블록 + 일위대가 밖(내역서 등이 부름) · 줄마다
|
||||
`부름 [호표 번]`([] = 일위대가 밖) · 밖 블록 = 이름 · 단위 블록 것 · 근거 꼬리표 없음(맞춤셈 열쇠 = 부르는 줄).
|
||||
같은 내용(733-1 · `M02_Library_Same` 지문) SK 가 이 층에 있으면 새로 안 만들고 그것을 씀 — 이름 = 먼저 만든 것 ·
|
||||
뒤 출처 = 그 SK `본뜬.또 [그 블록 본뜬 + 이름]`(`made` · `origin_of` 가 읽음) · 다른 출처가 쓰는 SK 는 내용을
|
||||
안 바꿈(바뀌면 떼고 다시 찾음) · 응답 `같은것씀 [{번, 키}]` · 위 층 같은 것 = `위층같음 [{번, 층, 주인, 키}]`(알림만).
|
||||
@@ -89,6 +91,19 @@ def calls(hp: dict[str, Any]) -> tuple[dict[int, dict], dict[int, dict]]:
|
||||
return blocks, first
|
||||
|
||||
|
||||
def callers(hp: dict[str, Any]) -> dict[int, list]:
|
||||
"""{단산 번: 부르는 호표 번 [차례대로 · 겹침 뺌]} — 없는 번 = 일위대가 밖."""
|
||||
out: dict[int, list] = {}
|
||||
for h in hp.get("호표") or []:
|
||||
for line in h.get("줄") or []:
|
||||
ref = line.get("참조") or {}
|
||||
if ref.get("종류") == "단산" and ref.get("번"):
|
||||
got = out.setdefault(int(ref["번"]), [])
|
||||
if h.get("번") not in got:
|
||||
got.append(h.get("번"))
|
||||
return out
|
||||
|
||||
|
||||
def _bad(text: str, status: int = 400) -> store.StoreError:
|
||||
return store.StoreError(status, text)
|
||||
|
||||
@@ -155,6 +170,8 @@ class Maker:
|
||||
|
||||
def basis(self, no: int) -> dict[str, Any] | None:
|
||||
"""근거 꼬리표 = 맞춤셈 1위 기초(참고)."""
|
||||
if no not in self.first: # 일위대가 밖 = 맞춤셈 없음
|
||||
return None
|
||||
entry = self.cache.get(fit.unit_key(self.first[no])) or {}
|
||||
top = (entry.get("차례") or [None])[0]
|
||||
if not top:
|
||||
@@ -175,7 +192,7 @@ class Maker:
|
||||
return {"층": layer, "주인": owner, "키": got} if got else None
|
||||
|
||||
def judge(self, no: int, picks: dict | None = None) -> dict[str, Any]:
|
||||
line, block = self.first[no], self.blocks[no]
|
||||
line, block = self.first.get(no) or {}, self.blocks[no]
|
||||
unit = str(line.get("단위") or block.get("단위") or "").strip()
|
||||
try:
|
||||
got = skunit.judge(block, self.units(), self.ref_of, picks, unit)
|
||||
@@ -206,7 +223,7 @@ class Maker:
|
||||
plan = self.plan(no, sure[no])
|
||||
got = self.judged[no]
|
||||
lost = [r for r in got["줄"] if r["상태"] == units.LINKED and r["차례"] not in got["담음"]]
|
||||
name = self.blocks[no].get("이름") or self.first[no].get("이름")
|
||||
name = self.blocks[no].get("이름") or (self.first.get(no) or {}).get("이름")
|
||||
if plan["갈래"] == skpatch.WAIT or lost:
|
||||
why = plan.get("까닭") or f"하위 「{lost[0]['이름']}」 — 그 블록 먼저 확인"
|
||||
out["못만듦"].append({"번": no, "이름": name, "까닭": why})
|
||||
@@ -217,7 +234,7 @@ class Maker:
|
||||
|
||||
def write(self, no: int, plan: dict, have: str | None) -> str:
|
||||
"""그 블록 SK 를 씀 → 키 — 다른 출처(또)가 쓰는 SK 의 내용은 안 바꿈(바뀌면 떼고 다시 찾음)."""
|
||||
doc = _doc(self.first[no], self.blocks[no], no, self.hp, plan, self.sure)
|
||||
doc = _doc(self.first.get(no) or {}, self.blocks[no], no, self.hp, plan, self.sure)
|
||||
root, mine = store.root(), doc["본뜬"]
|
||||
self.above += [{"번": no, **r} for r in self.same.find_above(root, KIND, doc)]
|
||||
if have:
|
||||
@@ -267,24 +284,31 @@ class Maker:
|
||||
|
||||
def build(folder: Path, key: str, who: Any = None, picks: Any = None) -> dict[str, Any]:
|
||||
"""[단가산출] — 블록마다 줄 판정 · 확인한 블록만 단위 SK → `{블록, 판정 [{번, 이름, 단위, 판정, 고를줄,
|
||||
우리금액, 엑셀금액, 근거, 만든, 줄}], 만듦 [{번, 이름, 키, 갈래, 못옮김}], 못만듦 [{번, 이름, 까닭}], 그대로,
|
||||
우리금액, 엑셀금액, 근거, 만든, 줄, 부름}], 만듦 [{번, 이름, 키, 갈래, 못옮김}], 못만듦 [{번, 이름, 까닭}], 그대로,
|
||||
같은것씀, 위층같음}` · `picks` = 확인 목록."""
|
||||
sure = _sure(picks)
|
||||
maker = Maker(folder, key, who)
|
||||
bad = sorted(set(sure) - set(maker.first))
|
||||
bad = sorted(set(sure) - set(maker.blocks))
|
||||
if bad:
|
||||
raise _bad(f"없는 블록 · 부르는 줄 없음 「단산{bad[0]}」", 404)
|
||||
raise _bad(f"없는 블록 「단산{bad[0]}」", 404)
|
||||
if not maker.done:
|
||||
fit.ensure(folder, key)
|
||||
raise _bad("맞춤 셈 중 — 끝나면 다시 누름", 409)
|
||||
out: dict[str, Any] = {"블록": len(maker.first), "만듦": [], "못만듦": []}
|
||||
out: dict[str, Any] = {"블록": len(maker.blocks), "만듦": [], "못만듦": []}
|
||||
for no in sorted(sure):
|
||||
maker.make(no, sure, out)
|
||||
rows = []
|
||||
for no in sorted(maker.first):
|
||||
line, block = maker.first[no], maker.blocks[no]
|
||||
call = callers(maker.hp)
|
||||
for no in sorted(maker.blocks):
|
||||
line, block = maker.first.get(no), maker.blocks[no]
|
||||
got = maker.judged.get(no) or maker.judge(no)
|
||||
head = {"번": no, "이름": block.get("이름") or line.get("이름"), "단위": line.get("단위")}
|
||||
name = block.get("이름") or (line or {}).get("이름")
|
||||
head = {
|
||||
"번": no,
|
||||
"이름": name,
|
||||
"단위": (line or block).get("단위"),
|
||||
"부름": call.get(no, []),
|
||||
}
|
||||
keep = ("판정", "고를줄", "우리금액", "엑셀금액", "줄")
|
||||
head |= {k: got[k] for k in keep} | {"근거": maker.basis(no)}
|
||||
rows.append({**head, "만든": maker.keys.get(mark(key, no))})
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
줄 판정 = `M02_Hopyo_Units` 잇기(상태 · 방법 · 단위) + 매개값(품 · 시간 · 수량 · 율) · 사용자 고름
|
||||
`{차례: 단위 | {뺌: 까닭}}`(그 줄만 · 꼬리표 「내가 고름」) · 단가 = M01 지금 값으로 다시 셈(`우리금액`) ·
|
||||
엑셀 금액과의 `차` = 참고(엑셀 = 과거 값 · 판정에 안 씀) · 셈 밖 줄 = 상태 「밖」(SK 에 안 들임).
|
||||
블록 판정 = 줄 모음 — 모두 이어짐 = 「옮길 수 있음」 · 아니면 「고를 줄 n」.
|
||||
블록 판정 = 줄 모음 — 모두 이어짐 = 「옮길 수 있음」 · 아니면 「고를 줄 n」 · 줄 0 = 「줄 없음」(고를줄 1 · 빈 SK 막음).
|
||||
단위 SK 더한줄(바탕 없음 · 778-4 꼴) = 인력 `{요소 LB, 수량 품}` · 기계경비 로직 `{로직 GC, 입력값 {기계},
|
||||
수량 시간 × 할증}` · 재료 `{요소 MT, 수량(손료율 든), 별도계상?}`(못 찾은 별도계상 = 0 원 고정 줄) ·
|
||||
율 `{고정 {비율 {기준, 비목}}, 수량 = 율 %}`(줄 목록 = 그 행 줄 `add:#k`) · 하위 `{참조 SK · SC}` · 값 고정 줄.
|
||||
@@ -24,6 +24,7 @@ from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
||||
from M02_MasterTemplete.M02_Hopyo_Words import mtypes
|
||||
|
||||
GOOD = "옮길 수 있음"
|
||||
EMPTY = "줄 없음"
|
||||
OUT, DROP = "밖", "뺌"
|
||||
UNIT = "단위" # 본뜬 갈래
|
||||
MINE = "내가 고름"
|
||||
@@ -85,7 +86,9 @@ def lines(block: dict[str, Any], us: units.Units, picks: dict | None = None) ->
|
||||
|
||||
|
||||
def verdict(rows: list[dict]) -> tuple[str, int]:
|
||||
"""블록 판정 — (「옮길 수 있음」 | 「고를 줄 n」, n)."""
|
||||
"""블록 판정 — (「옮길 수 있음」 | 「고를 줄 n」 | 「줄 없음」, n) · 줄 0 = 1(확인해도 못 만듦)."""
|
||||
if not rows:
|
||||
return EMPTY, 1
|
||||
n = sum(1 for r in rows if r["상태"] not in (units.LINKED, OUT, DROP))
|
||||
return (GOOD if not n else f"고를 줄 {n}"), n
|
||||
|
||||
|
||||
Reference in New Issue
Block a user