Files
Aislo/B09_Estimation/draft/B09_Draft_Print_Cost.ts
T

97 lines
4.3 KiB
TypeScript

/* =============================================================================
* B09_Draft_Print_Cost.ts
* 인쇄 미리보기(PLAN 302-4 · 초안) 「원가계산」 영역 — B09 18장을 실무 내역서 차례로 모음.
* 차례 · 이름 · 방향 = 기번3 내역서 xlsx 시트(목차 · 안내 빼고 · page_setup.orientation)
* 값 = GET …/estimation + 화면 캐시(`b09-estimation`) → `computeSheets` = B09 화면과 같은 값
* 표 = 화면 표 짜기(`…_UI_Builders`) 그대로 · 링크 · 강조 · 고칠 칸 표시 · 단가연결 칸만 뺌
* 공기 초안 탭(공기집계 · 공기산출) = 내역서 차례 밖 → 안 넣음
* ========================================================================== */
import { API_BASE_URL } from "@config/config_frontend";
import type { DataTableOptions } from "@ui/ui_template_data_table";
import { readState } from "../../A00_Common/b_page_state";
import type { Row } from "../B09_Estimation_Calc_Base";
import { tableOptionsOf, tabTableOf } from "../B09_Estimation_UI_Builders";
import { computeSheets } from "../B09_Estimation_UI_Shell";
import type { TabContext, TabId } from "../B09_Estimation_UI_Tabs";
import type { CollectSheets, PrintSheet } from "./B09_Draft_Print_Types";
type Orientation = NonNullable<PrintSheet["orientation"]>;
/** 기번3 내역서 시트 차례 — [탭, 시트 이름, 인쇄 방향] */
export const COST_SHEETS: Array<[TabId, string, Orientation]> = [
["cost", "공사원가계산서", "landscape"],
["total", "총괄설계내역서", "landscape"],
["bill", "설계내역서", "landscape"],
["dg_list", "일위대가목록표", "landscape"],
["dg", "일위대가표", "landscape"],
["sg_list", "단가산출근거목록표", "landscape"],
["sg", "단가산출근거", "landscape"],
["basis", "환율및기초자료", "landscape"],
["machine", "중기목록표", "landscape"],
["machine_blocks", "중기사용료", "landscape"],
["material", "재료비목록표", "landscape"],
["labor", "노무비목록표", "landscape"],
["expense", "경비목록표", "landscape"],
["compare", "자재단가대비표", "landscape"],
["sum_material", "재료비수량금액집계표", "landscape"],
["sum_labor", "노무비수량금액집계표", "landscape"],
["sum_expense", "경비수량금액집계표", "landscape"],
["sum_machine", "중기시간금액집계표", "landscape"],
];
/** 화면 조작 전용 칸(설계내역서 「단가연결 ▾」) */
const UI_COLUMNS = new Set(["connect"]);
/** 인쇄에 남길 줄 꼴(제목 줄 굵게) — 손 줄 · 고른 줄 표시는 뺌 */
const KEEP_ROW = new Set(["is-title"]);
/** 화면 표 옵션 → 인쇄 표(값 · 머리 · 레벨 · 합계 · 병합 그대로 · 누름 · 고침 · 강조 뺌) */
export function printTable(options: DataTableOptions, caption: string): DataTableOptions {
const { columns, rows, total, frozen, empty, level, mergeSame, rowClass } = options;
return {
columns: columns.filter((c) => !UI_COLUMNS.has(c.key)),
rows,
total,
frozen,
empty,
caption,
mergeSame,
level: level && { ...level, tree: false },
rowClass:
rowClass &&
((i) =>
rowClass(i)
?.split(" ")
.filter((c) => KEEP_ROW.has(c))
.join(" ") || null),
};
}
/** 받은 자료 + 사용자 값 → 18장(차례 그대로 · 표가 없는 탭 = 빈 표) */
export function costSheetsOf(payload: Row, user: Row): PrintSheet[] {
const ctx: TabContext = {
sheets: computeSheets(payload, user),
payload,
user,
setUser: () => {},
};
return COST_SHEETS.map(([id, name, orientation]) => {
const spec = tabTableOf(id, ctx);
const table =
!spec || typeof spec === "string"
? { columns: [], rows: [], caption: name }
: printTable(tableOptionsOf(spec, id), name);
return { id, name, orientation, table };
});
}
export const collectCostSheets: CollectSheets = async (projectId) => {
const response = await fetch(`${API_BASE_URL}/projects/${projectId}/estimation`, {
credentials: "include",
});
if (!response.ok) throw new Error(`원가 자료를 불러오지 못했습니다 — HTTP ${response.status}`);
const payload = (await response.json()) as Row;
const user = readState<Row>("b09-estimation", projectId) ?? payload.user ?? {};
return costSheetsOf(payload, user);
};