Files
Aislo/B09_Estimation/B09_Estimation_UI_Tabs_Bill.ts
T
eomsangdonandClaude Opus 5.5 489a682794 feat(B09): 설계내역서 — 공종 나무 엑셀 꼴 · B08 수량 · 호표 단가 · 관급 · 원가계산서 이음(145-3)
- 공종 나무 = 엑셀 꼴 고정(토공사 1.1~1.6 · 구조물공 2.1~2.3 · 운반공 · 자재대 · 관급자재대 제외금액) · 공구 안 나눔
- 항목 짜기(서버) = B08 토공집계표 짝 · 구조물 집계표 열(구조물군 → 공종 짝 · 커플링 뺌) · 운반공 수량 = B08 총괄자재
- 조합 밖 토공 · 운반 산근 · 준비공 = 빈칸 「연결 없음」 · 구조물 단가 = 대가 호표 자리(145-2 hopyo)
- 4 자재대 = 대비표 「별도」 · 관급자재대 = 「관급」 표시 + 조달수수료(율 사용자 입력 · ROUNDDOWN 0)
- 셈 = 파이썬 · TS 짝 + 거울 · 금액 ROUNDDOWN(단가 × 수량, 0) 비목마다 · 제목 = 아는 금액 합 + 빈 줄 수
- 원가계산서 이음 = sheets.bill.sums {material · labor · expense · supply_net} · 빈 줄 있으면 null
- 시험 = test_145_3_b09_bill(엑셀 G9 361,494 · G14 11,003,825 · 관급 69,474,220 + 375,160 = 69,849,380)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
2026-10-09 15:13:05 +09:00

64 lines
2.6 KiB
TypeScript

/* =============================================================================
* 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;
},
};
};