fix(B08): 코드 없는 줄에 막힘 표시를 붙임 — 금액이 조용히 빠지던 자리
랩탑 메인이 화면에서 잡음: 「측구터파기 · 굴삭기+브레카」가 work_item_code null 인데 blocked_kind 도 null 이라 아무 말 없이 금액만 빠졌음. 인계본의 bill_flag_warnings·unmatched_work_items 에는 이미 실려 있었음 — 목록은 있는데 줄에 표시가 없었던 것. 줄 단위로 보는 쪽(B09·화면)은 목록을 안 봄. 같은 모양이 여덟 줄이었음(흙깎기·측구터파기·도자운반 둘·덤프운반 둘·지장목제거·큰돌쌓기). - 토공 줄: 코드가 없으면 시공법 미지정이면 input_missing, 매핑을 못 이었으면 unit_data_missing 으로 갈라 답. 다음에 할 일이 다름(사용자 입력 vs 매핑 작업). - 운반 줄: 같은 규칙. 무대(free_haul)는 품에 포함이라 안 세우는 것이지 막힌 게 아니므로 표시를 안 답. - 불변식 시험을 세움 — 코드도 막힘 표시도 없이 내역에 서는 줄이 하나라도 있으면 깨짐. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,9 +131,22 @@ def _earthwork_rows(
|
||||
elif mismatch is not None:
|
||||
spec_detail = f"집계 {amount:,.2f} {unit} (품셈 밑수 {mismatch[0]})"
|
||||
unit, amount = mismatch[0], 0.0
|
||||
# ⚠⚠ **코드가 없으면 반드시 막힘 표시를 단다**(2026-09-09 랩탑 메인 제보).
|
||||
# 종전에는 `unmatched_work_items` 목록과 `bill_flag_warnings` 에만 실려,
|
||||
# **줄 단위로 보는 쪽**(B09·화면)이 「코드도 없고 막힘 표시도 없는 멀쩡한 줄」로
|
||||
# 읽었다 — 금액이 조용히 빠졌다(측구터파기·흙깎기 「굴삭기+브레카」).
|
||||
# ⇒ 오늘 세운 규칙 「막혔다고 말하기 전에 `blocked_kind` 를 볼 것」의 **뒤집힌 얼굴**:
|
||||
# 보는 쪽을 고쳤으면 **다는 쪽도** 빠짐없이 달아야 한다.
|
||||
blocked_kind = mismatch[1] if mismatch else None
|
||||
blocked_reason = mismatch[2] if mismatch else ""
|
||||
if code is None and not is_subtotal:
|
||||
label = f"{group}({ground})" if ground else group
|
||||
unmatched.append(f"{label} — {method_note}" if method_note else label)
|
||||
if blocked_kind is None:
|
||||
# 시공법을 고르면 풀리는 자리와, 품셈을 아직 못 이은 자리를 **갈라 적는다** —
|
||||
# 다음에 할 일이 다르다(하나는 사용자 입력, 하나는 매핑 작업).
|
||||
blocked_kind = BLOCKED_INPUT_MISSING if method_note else BLOCKED_UNIT_DATA_MISSING
|
||||
blocked_reason = method_note or f"{label} 의 품셈 공종을 아직 못 이었습니다"
|
||||
rows.append(
|
||||
{
|
||||
"work_item_code": code,
|
||||
@@ -162,9 +175,9 @@ def _earthwork_rows(
|
||||
"secondary_axes": None,
|
||||
"spec_class": None,
|
||||
"spec_class_basis": "",
|
||||
# 토공 줄도 막힐 수 있다 — 품셈 밑수와 단위가 다르면 그 사유가 실린다.
|
||||
"blocked_kind": mismatch[1] if mismatch else None,
|
||||
"blocked_reason": mismatch[2] if mismatch else "",
|
||||
# 토공 줄도 막힐 수 있다 — 밑수 어긋남과 **코드 없음** 둘 다 여기 실린다.
|
||||
"blocked_kind": blocked_kind,
|
||||
"blocked_reason": blocked_reason,
|
||||
"composite_not_ready": None,
|
||||
# 합계 줄과 무대 줄은 값은 내되 내역에 안 선다.
|
||||
"in_bill": bool(row.get("in_bill", True)) and not is_subtotal and mismatch is None,
|
||||
@@ -191,6 +204,13 @@ def _haul_rows(
|
||||
in_bill = bool(row.get("in_bill", True)) and entry.get("in_bill", True)
|
||||
if code is None and in_bill:
|
||||
unmatched.append(f"운반({equipment})")
|
||||
# ⚠ 코드가 없으면 **줄에 막힘 표시를 단다**(2026-09-09) — 목록에만 실으면 줄 단위로
|
||||
# 보는 쪽이 「멀쩡한 줄」로 읽어 금액이 조용히 빠진다(도자운반·덤프운반이 그랬다).
|
||||
# ⚠ `in_bill` 이 False 인 무대 줄은 **막힌 것이 아니다** — 품에 포함이라 안 세우는 것.
|
||||
haul_blocked = BLOCKED_UNIT_DATA_MISSING if (code is None and in_bill) else None
|
||||
haul_blocked_reason = (
|
||||
f"운반({equipment})의 품셈 공종을 아직 못 이었습니다" if haul_blocked else ""
|
||||
)
|
||||
# ⚠⚠ **내역서 수량은 자연상태다** — 유토곡선은 다짐상태로 쌓고(운반거리를 그 기준으로
|
||||
# 재야 맞는다) 내역에 오르는 수량은 되돌린 값이다(`config_system_design` 5-4-3
|
||||
# 「운반거리 산정 시 모든 수량은 다짐상태로 환산해 계산하고, **내역서에 적용하는
|
||||
@@ -242,8 +262,8 @@ def _haul_rows(
|
||||
"secondary_axes": None,
|
||||
"spec_class": None,
|
||||
"spec_class_basis": "",
|
||||
"blocked_kind": None,
|
||||
"blocked_reason": "",
|
||||
"blocked_kind": haul_blocked,
|
||||
"blocked_reason": haul_blocked_reason,
|
||||
"composite_not_ready": None,
|
||||
"in_bill": in_bill,
|
||||
"in_bill_reason": str(entry.get("reason") or ""),
|
||||
|
||||
Reference in New Issue
Block a user