Files
Aislo/B09_Estimation/B09_Estimation_UI_Tabs_Labor.ts
T
eomsangdonandClaude Opus 5.5 4ebee1197a feat(ui,b09): 공용 표 줄 꼴 곁값 · 일위대가표 제목 굵게 · 하위 「ㄴ」(155-2)
- 공용 표 rowClass(줄) 곁값 — 본문 줄 class · 안 주면 글 그대로 · is-title 굵게
- 공용 표 칸 앞 빈칸 · 겹 빈칸 접지 않음(white-space-collapse: preserve-spaces)
- B09 일위대가표 = 머리 · 합계 굵게 · 품셈 인용 · 줄 = 들여쓰기 「ㄴ」(2단)
- 시험 test_ui_data_table 줄 꼴 · 새 test_155_b09_tabs

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

134 lines
4.6 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_Labor.ts
* B09 대가 탭 둘(PLAN 145-2) — 일위대가목록표 · 일위대가표(실무 엑셀 꼴 · 값 = `B09_Estimation_Calc_Labor`).
*
* 목록표 = 호표 한 줄(합계 · 노무비 · 재료비 · 경비) · 줄 누름 = 그 블록으로
* 일위대가표 = 블록(머리 · [품셈 인용] · 줄 · 합계) · 줄 누름 = 단가를 낸 탭 · 줄(대가 줄 = 그 블록)
* 줄 꼴(155-2) = 머리 · 합계 굵게(`is-title`) · 인용 · 줄 = 들여쓰기 「ㄴ」(2단 · 겹 대가는 안 펼침)
* 연결된 구조물 조합 사본이 없으면 빈 표 「연결 없음」
* ========================================================================== */
import type { DataRow } from "@ui/ui_template_data_table";
import type { Row } from "./B09_Estimation_Calc_Base";
import {
money,
qty,
text,
type Link,
type TabBuild,
type TabId,
type TabTable,
} from "./B09_Estimation_UI_Tabs";
const EMPTY =
"연결 없음 — 연결된 구조물 조합 사본(일위대가)이 없음 · B05 · B06 에서 조합을 고르고 [저장]";
/** 하위 줄 앞 — 들여쓰기 + 「ㄴ」(공용 표가 앞 빈칸을 접지 않음) */
const CHILD = " ㄴ ";
const ROUNDS = "줄 금액 ROUNDDOWN(단가 × 수량, 1) · % 줄 = 밑수 × % / 100 · 합계 ROUNDDOWN 0";
/** 블록 줄 → 단가를 낸 탭 */
const LINE_TAB: Record<string, TabId> = {
labor: "labor",
material: "material",
machine: "machine",
daega: "dg",
sangeun: "sg_list",
};
export const buildDaegaList: TabBuild = ({ sheets }): TabTable | string => {
const rows: DataRow[] = (sheets.daega || []).map((r: Row) => ({ ...r, no: `대가${r.no}` }));
if (!rows.length) return EMPTY;
return {
columns: [
text("no", "호표", 80),
text("kind", "꼴", 70),
text("name", "명칭", 240),
text("spec", "규격", 200),
text("unit", "단위", 56),
money("sum", "합계"),
money("labor", "노무비"),
money("material", "재료비"),
money("expense", "경비"),
],
rows,
frozen: 3,
hint: "호표 = 일위대가표 블록 합계 · 줄을 누르면 그 블록으로",
link: (i: number): Link | null => (rows[i] ? { tab: "dg", key: String(rows[i].key) } : null),
};
};
export const buildDaegaBlocks: TabBuild = ({ sheets }): TabTable | string => {
const blocks: Row[] = sheets.daega_blocks || [];
if (!blocks.length) return EMPTY;
const rows: DataRow[] = [];
const links: Array<Link | null> = [];
const titles = new Set<number>();
for (const b of blocks) {
titles.add(rows.length);
rows.push({
key: b.id,
name: `제 ${b.no} 호표 ${b.name}`,
spec: b.spec,
unit: b.unit,
note: b.kind,
});
links.push(null);
if (b.cite) {
rows.push({ key: `${b.id}|cite`, name: `${CHILD}${b.cite}`, note: "품셈 인용" });
links.push(null);
}
b.lines.forEach((ln: Row, n: number) => {
rows.push({
key: `${b.id}|${n}`,
name: `${CHILD}${ln.name || ""}`,
spec: ln.spec || "",
qty: ln.qty,
unit: ln.unit || "",
sum_price: ln.price,
sum: ln.amount,
labor_price: ln.prices.labor,
labor: ln.amounts.labor,
material_price: ln.prices.material,
material: ln.amounts.material,
expense_price: ln.prices.expense,
expense: ln.amounts.expense,
note: ln.ref_no || ln.why || "",
});
const tab = LINE_TAB[ln.kind];
links.push(tab && ln.key ? { tab, key: String(ln.key) } : null);
});
titles.add(rows.length);
rows.push({
key: `${b.id}|합계`,
name: " 합 계",
sum: b.sum,
labor: b.labor,
material: b.material,
expense: b.expense,
});
links.push(null);
}
const pair = (key: string, label: string) => [
money(`${key}_price`, "단가", [label], 1),
money(key, "금액", [label], 1),
];
return {
columns: [
text("name", "명칭", 240),
text("spec", "규격", 160),
qty("qty", "수량"),
text("unit", "단위", 56),
...pair("sum", "합계"),
...pair("labor", "노무비"),
...pair("material", "재료비"),
...pair("expense", "경비"),
text("note", "비고", 120),
],
rows,
frozen: 1,
hint: `단가 = B09 프로젝트 한 벌 굳힌 단가 · ${ROUNDS} · 줄 누름 = 단가를 낸 탭(대가 줄 = 그 블록)`,
link: (i: number) => links[i] ?? null,
rowClass: (i: number) => (titles.has(i) ? "is-title" : null),
};
};