Files
Aislo/B09_Estimation/B09_Estimation_UI_Tabs_Summary.ts
T

93 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* B09_Estimation_UI_Tabs_Summary.ts
* B09 집계표 넷(PLAN 145-5) — 재료비 · 노무비 · 경비 수량금액집계표 · 중기시간금액집계표(실무 엑셀 꼴).
*
* 값 = 서버 단독 역전개(`B09_Estimation_Summary` · GET 응답 `summary`) — 조작 중엔 안 바뀜 · [저장] 뒤 정본
* 끝수 = 총수량 ROUND 2 · 금액 ROUND(수량 × 단가, 0) · 줄 누름 = 단가를 낸 목록표 줄
* 경비 집계표 빈 까닭(166-5) = 산근 · 대가 어느 길도 경비 자원 줄을 안 냄(기계 → 중기 · 구역화물 → 자재)
* ========================================================================== */
import type { DataRow } from "@ui/ui_template_data_table";
import type { Row } from "./B09_Estimation_Calc_Base";
import {
money,
qty,
text,
type TabBuild,
type TabId,
type TabTable,
} from "./B09_Estimation_UI_Tabs";
const HINT =
"총수량 = 설계내역서 수량 × 호표(산근 · 대가) 구성 역전개(서버 · [저장] 뒤 다시 셈) · ROUND 2 · 금액 = ROUND(수량 × 단가, 0) · 줄 누름 = 목록표";
/** 안내 + 「연결 없음 n」(전개 안 한 내역 항목 — 조합 밖 토공 · 운반 산근 등) */
const hint = (payload: Row, extra = ""): string => {
const n = (payload.summary || {}).unlinked || 0;
return `${HINT}${extra}${n ? ` · 연결 없음 ${n} — 전개 안 함(연결 점검 탭)` : ""}`;
};
/** 줄이 없을 때 표 위 맨 앞 안내 */
const EXPENSE_NONE = "경비 갈래 자원 없음 — 중기 · 자재로 셈 · 경비 로직이 들어오면 채워짐";
function resourceTab(id: string, list: TabId, unitPrice: string, none = ""): TabBuild {
return ({ payload }): TabTable => {
const rows: DataRow[] = ((payload.summary || {})[id] || []).map((r: Row) => ({ ...r }));
const sum = rows.reduce((acc, r) => acc + (typeof r.amount === "number" ? r.amount : 0), 0);
return {
columns: [
qty("no", "호표", 0),
text("name", "명칭", 200),
text("spec", "규격", 140),
qty("qty", "수량", 2),
text("unit", "단위", 56),
money("price", unitPrice),
money("amount", "금액"),
text("note", "비고", 120),
],
rows,
total: rows.length ? { name: "계", amount: sum } : null,
frozen: 2,
hint: !rows.length && none ? `${none} · ${hint(payload)}` : hint(payload),
link: (i) => (rows[i] ? { tab: list, key: String(rows[i].key) } : null),
};
};
}
export const buildSumMaterial = resourceTab("sum_material", "material", "단가");
export const buildSumLabor = resourceTab("sum_labor", "labor", "단가");
export const buildSumExpense = resourceTab("sum_expense", "expense", "단가", EXPENSE_NONE);
export const buildSumMachine: TabBuild = ({ payload }): TabTable => {
const rows: DataRow[] = ((payload.summary || {}).sum_machine || []).map((r: Row) => ({ ...r }));
const add = (key: string) =>
rows.reduce((acc, r) => acc + (typeof r[key] === "number" ? (r[key] as number) : 0), 0);
return {
columns: [
qty("no", "호표", 0),
text("name", "명칭", 200),
text("spec", "규격", 120),
qty("qty", "수량", 2),
text("unit", "단위", 56),
money("sum", "합계"),
money("labor", "노무비"),
money("material", "재료비"),
money("expense", "경비"),
text("note", "비고", 120),
],
rows,
total: rows.length
? {
name: "계",
sum: add("sum"),
labor: add("labor"),
material: add("material"),
expense: add("expense"),
}
: null,
frozen: 2,
hint: hint(payload, " · 비목마다 ROUND(시간 × 시간당, 0)"),
link: (i) => (rows[i] ? { tab: "machine", key: String(rows[i].key) } : null),
};
};