refactor(B08,B09): 폴더째 old_code 로 옮기고 빈 화면 둘만 남김 (PLAN 7-3)
B08_Quantity 86 · B09_Estimation 111 파일을 old_code/ 로 옮김(지우지 않음). 화면은 메뉴·주소·단계 막대만 남은 빈 틀 둘 — main.py 라우터 13 개는 끊음. B07 이 빌려 쓰던 비탈 길이·면적은 필요한 함수만 B07_DesignDetail_Engine_SlopeGeometry 로 옮겨 적음(면적 적분·노면 면적·측점 묶음은 안 옮김) · 시험 하나를 새로 둠. B07 구조물도 조립(Cad_StandardSheet)은 2026-09-13 에 이미 도면 목록에서 빠져 부르는 곳이 없어 old_code 로 같이 보냄 — 구조물 그림은 되살리지 않음. B06 구조물 몫 조회는 빈 값으로 두어 화면이 그대로 서게 함. B08·B09 를 부르던 시험 25 개도 old_code/resources/tester 로 옮김. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAdA5ThqmtVSsbzjusk1cJ
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""B09 원가계산 — 일위대가표 **호표 번호** (PLAN 12장 · 실무 `일위대가목록표`).
|
||||
|
||||
실무 내역서는 일위대가를 「제 N 호표」로 부르고, 목록표가 번호마다 명칭·규격·성분 금액을 보인다.
|
||||
|
||||
⚠ **번호는 저장하지 않음**(2026-09-14 브레인 판정) — 내역이 바뀌면 번호도 바뀌므로 낼 때마다 매김.
|
||||
단산 번호(`B09_Estimation_PriceBasis`)와 같은 규칙: **내역에 처음 쓰인 차례**.
|
||||
⚠ 내역 줄이 부르지 않고 **다른 일위대가 안에서만** 불리는 호표(찰쌓기 안의 모르타르 배합 따위)는
|
||||
부르는 호표 **바로 뒤**에 번호가 붙음(줄 차례대로 깊이 우선).
|
||||
⚠ 구조물도 호표(`B-AX-ST-…#키`)는 단가표 제목이 아니라 B08 일위대가 표로 섬 — 금액은 그 표 값,
|
||||
안의 하위 호표 번호는 아직 안 매김(구조물도 탭이 그 표를 보임).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
from B09_Estimation.B09_Estimation_PriceBook import Money3, PriceBook, PriceKind
|
||||
|
||||
STRUCTURE_SOURCE = "structure"
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnitPriceSheetEntry:
|
||||
number: int
|
||||
code: str
|
||||
name: str
|
||||
spec: str
|
||||
unit: str
|
||||
money: Money3
|
||||
#: 「book」 단가표 제목 · 「structure」 구조물도 일위대가 표.
|
||||
source: str = "book"
|
||||
unconfirmed: int = 0
|
||||
|
||||
@property
|
||||
def label(self) -> str:
|
||||
return f"제 {self.number} 호표"
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"number": self.number,
|
||||
"label": self.label,
|
||||
"code": self.code,
|
||||
"name": self.name,
|
||||
"spec": self.spec,
|
||||
"unit": self.unit,
|
||||
"material_krw": str(self.money.material),
|
||||
"labor_krw": str(self.money.labor),
|
||||
"expense_krw": str(self.money.expense),
|
||||
"total_krw": str(self.money.total),
|
||||
"source": self.source,
|
||||
"unconfirmed": self.unconfirmed,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnitPriceSheet:
|
||||
entries: list[UnitPriceSheetEntry] = field(default_factory=list)
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {"entries": [entry.as_dict() for entry in self.entries]}
|
||||
|
||||
|
||||
def _nested(book: PriceBook, code: str, seen: tuple[str, ...]) -> list[str]:
|
||||
"""호표 안에서 부르는 일위대가 — 줄 차례대로 깊이 우선."""
|
||||
found: list[str] = []
|
||||
for detail in book.details.get(code, []):
|
||||
ref = detail.ref_code
|
||||
title = book.titles.get(ref)
|
||||
if title is None or title.kind is not PriceKind.UNIT_PRICE or ref in seen:
|
||||
continue
|
||||
found.append(ref)
|
||||
found.extend(_nested(book, ref, (*seen, ref)))
|
||||
return found
|
||||
|
||||
|
||||
def build_unit_price_sheet(
|
||||
rows: list[Any],
|
||||
book: PriceBook,
|
||||
structure_prices: dict[str, dict[str, Any]] | None = None,
|
||||
) -> UnitPriceSheet:
|
||||
"""내역 줄(`BillRow`) 차례 → 호표 번호 한 벌. 같은 호표를 두 줄이 불러도 한 번만."""
|
||||
sheet = UnitPriceSheet()
|
||||
numbered: set[str] = set()
|
||||
|
||||
def add(code: str, **values: Any) -> None:
|
||||
numbered.add(code)
|
||||
sheet.entries.append(
|
||||
UnitPriceSheetEntry(number=len(sheet.entries) + 1, code=code, **values)
|
||||
)
|
||||
|
||||
for row in rows:
|
||||
code = row.price_code
|
||||
if not code or code in numbered:
|
||||
continue
|
||||
structure = (structure_prices or {}).get(code)
|
||||
if structure is not None:
|
||||
add(
|
||||
code,
|
||||
name=row.name,
|
||||
spec=row.spec,
|
||||
unit=row.unit,
|
||||
money=structure["money"],
|
||||
source=STRUCTURE_SOURCE,
|
||||
unconfirmed=int(structure.get("unconfirmed") or 0),
|
||||
)
|
||||
continue
|
||||
if code not in book.titles:
|
||||
continue
|
||||
for ref in (code, *_nested(book, code, (code,))):
|
||||
if ref in numbered:
|
||||
continue
|
||||
title = book.title(ref)
|
||||
add(ref, name=title.name, spec=title.spec, unit=title.unit, money=book.resolve(ref))
|
||||
return sheet
|
||||
Reference in New Issue
Block a user