fix(B09): 서고 사본 산근 = 산근 목록에 듦 · 대가 단가 채움(PLAN 702-3)

단가연결로 들여온 서고 사본(구조물조합 · 사전조합)의 단가산출 줄이 산근 목록에
안 들어 대가 블록 단가가 빈칸 — 산근 모음이 구조물 사본만 훑던 것 · 차례 =
대가 입력과 같게(구조물 → 서고 사본 → 수기 줄).
시험 test_702_3 서고 사본 산근 2 줄 · 대가 합 채움.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 13:33:49 +09:00
co-authored by Claude Opus 5.5
parent 5cb947d46c
commit 1599014504
2 changed files with 52 additions and 1 deletions
+7 -1
View File
@@ -570,11 +570,17 @@ def collect(
def build( def build(
project_root: str | Path, sheets: dict[str, Any], user: dict[str, Any] | None = None project_root: str | Path, sheets: dict[str, Any], user: dict[str, Any] | None = None
) -> dict[str, Any]: ) -> dict[str, Any]:
"""연결된 사본 전부(구조물 id 차례)의 산근 + 설계내역서 손 줄 로직(166-2 · 뒤 번호).""" """연결된 사본 전부(구조물 id 차례 → 설계내역서 서고 사본 · 702-3)의 산근 +
설계내역서 손 줄 로직(166-2 · 뒤 번호) — 차례 = `Labor_Source.daega_inputs`."""
from B09_Estimation.B09_Estimation_Bill_Library import copies
base = structures_dir(project_root) base = structures_dir(project_root)
entries = [ entries = [
(owner, base / linked["폴더"]) (owner, base / linked["폴더"])
for owner, linked in sorted(linked_snapshots(project_root).items()) for owner, linked in sorted(linked_snapshots(project_root).items())
if "일위대가" in linked.get("부분", []) if "일위대가" in linked.get("부분", [])
] ]
entries += [
(f"서고 {(m.get('원본') or {}).get('name') or f.name}", f) for f, m in copies(project_root)
]
return collect(entries, sheets, hand_sources(user)) return collect(entries, sheets, hand_sources(user))
@@ -0,0 +1,45 @@
"""702-3 B09 단가연결 즉시 금액 · [저장] 단추 · 서고 사본 산근.
- 서고 사본(단가연결로 들여온 사전조합)의 단가산출 줄 = 산근 목록에 듦 · 대가 블록 단가 채움
(옛 흠 — 산근이 구조물 사본만 훑어 서고 사본 산근 0 · 대가 빈칸)
- 셈 미리보기 길(`POST …/estimation/calc`) = 화면 캐시로 서버 셈 · 저장 안 함 · 로직 연결 줄 금액
- 화면 — 연결 즉시 뒤에서 셈(차례 번호 · 옛 요청 끊기) · [저장] 단추 · 옮길 때 물음
임시 층(견본 마스터 · 임시 storage) · 실제 마스터 · 프로젝트는 안 씀.
"""
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from B09_Estimation import B09_Estimation_Prices as prices # noqa: E402
from B09_Estimation import B09_Estimation_Sangeun as sangeun # noqa: E402
from B09_Estimation.B09_Estimation_Calc_Base import compute_base # noqa: E402
from B09_Estimation.B09_Estimation_Calc_Labor import compute_labor # noqa: E402
from resources.tester.test_204_2_b09_bill_library import ( # noqa: E402, F401
daega_inputs,
library,
linked_resource_keys,
world,
)
B09 = ROOT / "B09_Estimation"
def test_서고_사본_산근_목록에_듦_대가_단가_채움(world):
root = world["root"]
folder = library.import_copy(root, "precombo", "system", None, world["key"])["폴더"]
daega = daega_inputs(root)
block = next(b for b in daega["blocks"] if b["id"] == daega["libs"][folder])
wanted = [ln["key"] for ln in block["lines"] if ln["kind"] == "sangeun"]
base = compute_base(prices.build_inputs(None, linked_resource_keys(root)), {})
sg = sangeun.build(root, base)
assert [r["key"] for r in sg["sg_list"]] == wanted # 둘 다 산근 · 블록 줄 키 그대로
assert all(r["sum"] for r in sg["sg_list"])
assert sg["sg_list"][0]["uses"] == ["서고 서고 조합"]
by_key = {r["key"]: r for r in sg["sg_list"]}
labor = compute_labor(daega, {**base, "gaps": []}, by_key)
row = next(r for r in labor["daega"] if r["key"] == block["id"])
assert row["sum"] and not row.get("blank")