/* ============================================================================= * B09_Estimation_UI_Tabs_Bill.ts * B09 설계내역서 탭(PLAN 145-3) — 실무 엑셀 꼴(공종 · 명칭 · 규격 · 수량 · 단위 · 합계 · 노무 · 재료 · 경비 · 비고). * * 값 = `B09_Estimation_Calc_Bill`(조작 중 브라우저 · [저장] 때 서버 정본) * 고칠 칸 = 관급자재대 조달수수료 율(%) · 빈칸 = 「연결 없음」(수량 · 단가 원천 없음) * 줄 누름 = 단가를 낸 탭 줄(자재 → 재료비목록표 · 구조물 → 일위대가목록표) * ========================================================================== */ import type { DataRow } from "@ui/ui_template_data_table"; import type { Row } from "./B09_Estimation_Calc_Base"; import { money, parseNumber, qty, text, type TabBuild, type TabId, type TabTable, } from "./B09_Estimation_UI_Tabs"; export const buildBill: TabBuild = ({ sheets, user, setUser }): TabTable => { const bill: Row = sheets.bill || { rows: [], totals: null }; const rows: DataRow[] = bill.rows.map((r: Row) => ({ ...r, name: r.kind === "title" ? r.name : ` ${r.name}`, })); const direct: Row = bill.totals?.direct || {}; const pair = (key: string, label: string) => [ money(`price_${key}`, "단가", [label]), money(key, "금액", [label]), ]; return { columns: [ text("name", "공종 · 명칭", 220), text("spec", "규격", 160), qty("qty", "수량", 3), text("unit", "단위", 56), ...pair("sum", "합계"), ...pair("labor", "노무비"), ...pair("material", "재료비"), ...pair("expense", "경비"), text("note", "비고", 200), ], rows, total: { name: "순공사비 계(관급 제외)", ...direct }, frozen: 1, hint: "공종 나무 = 엑셀 꼴 고정 · 금액 = ROUNDDOWN(단가 × 수량, 0) 비목마다 · 4 자재대 = 대비표 「별도」 · 관급자재대 = 「관급」 표시 자재 · 조달수수료 율(%)은 수량 칸에 넣음 · " + `빈 줄 ${direct.blank ?? 0} — 계는 아는 금액만 · 원가계산서는 빈 줄이 없을 때만 받음`, editable: (i, key) => key === "qty" && rows[i]?.key === "fee", onEdit: (i, key, value) => { if (key !== "qty" || rows[i]?.key !== "fee") return; const v = parseNumber(value); if (v === undefined) return; setUser({ ...user, estimate: { ...(user.estimate || {}), procurement_fee_pct: v } }); }, link: (i) => { const ref = rows[i]?.ref as Row | null | undefined; return ref?.key ? { tab: ref.tab as TabId, key: String(ref.key) } : null; }, }; };