- 공종 나무 = 엑셀 꼴 고정(토공사 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
64 lines
2.6 KiB
TypeScript
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;
|
|
},
|
|
};
|
|
};
|