Files
Aislo/B09_Estimation/B09_Estimation_UI_MachineExpense.ts
T

125 lines
4.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_MachineExpense.ts
* 각종 중기경비계산서 — 기종마다 한 장(별표2 (5)(가) 아홉째) · 중기 탭 아래에 붙음
*
* - 옛 `B09_Estimation_UI_BaseData.ts` 의 중기경비계산서를 그대로 옮김(PLAN 12장 옛 탭 옮기기).
* - ⚠ 목록표가 「얼마」라면 이 장은 **왜 그 값인가** — 계산 과정을 감추지 않음.
* ========================================================================== */
import { API_BASE_URL } from "@config/config_frontend";
import { el } from "./B09_Estimation_UI_Sheet";
import { head, infoTable, money, note } from "./B09_Estimation_UI_Table";
export interface MachineExpenseDto {
summary: string;
notes: string[];
sheets: Array<{
machine_code: string;
name: string;
spec: string;
price_thousand_krw: string | null;
economic_life_hours: number | null;
annual_standard_hours: number | null;
depreciation_coefficient: number | null;
maintenance_coefficient: number | null;
management_coefficient: number | null;
loss_coefficient: number | null;
loss_krw_per_hour: string | null;
fuel_liters_per_hour: string | null;
fuel_price_per_liter: string | null;
fuel_scope: string;
misc_material_percent: string | null;
operator_code: string;
operator_note: string;
operator_daily_wage: string | null;
operator_krw_per_hour: string | null;
material_krw: string | null;
labor_krw: string | null;
expense_krw: string | null;
total_krw: string | null;
variant: string;
attachment: boolean;
attachment_note: string;
gaps: string[];
}>;
}
export async function fetchMachineExpense(projectId: string): Promise<MachineExpenseDto> {
const response = await fetch(
`${API_BASE_URL}/projects/${encodeURIComponent(projectId)}/estimation/machine-expense`,
{ credentials: "include" },
);
if (!response.ok) throw new Error(`machine-expense ${response.status}`);
return (await response.json()) as MachineExpenseDto;
}
/** 기종 한 장 — 손료·운전경비·시간당 사용료를 차례로. */
function machineExpenseSheet(sheet: MachineExpenseDto["sheets"][number]): HTMLElement {
const box = el("div", "b09s-group");
box.append(
el(
"div",
"b09s-head",
`${sheet.machine_code} ${sheet.name} ${sheet.spec}`.trim() +
(sheet.variant ? ` — ${sheet.variant}` : ""),
),
);
const coefficient = (value: number | null) => (value === null ? "—" : String(value));
box.append(
infoTable(
["구 분", "내 용", "값"],
[
["① 손료", "취득가격(천원)", money(sheet.price_thousand_krw)],
[
"",
"내용시간 / 연간표준가동시간",
`${coefficient(sheet.economic_life_hours)} / ${coefficient(sheet.annual_standard_hours)}`,
],
[
"",
"상각비·정비비·관리비 계수 (10⁻⁷)",
`${coefficient(sheet.depreciation_coefficient)} + ${coefficient(sheet.maintenance_coefficient)} + ${coefficient(sheet.management_coefficient)} = ${coefficient(sheet.loss_coefficient)}`,
],
["", "시간당 손료(원)", money(sheet.loss_krw_per_hour)],
[
"② 운전경비",
`주연료(L/hr) × 유가(${sheet.fuel_scope})`,
`${sheet.fuel_liters_per_hour ?? "—"} × ${money(sheet.fuel_price_per_liter)}`,
],
["", "잡재료(주연료의 %)", sheet.misc_material_percent ?? "—"],
[
"",
`조종원(${sheet.operator_code || "—"}) 일당 → 시간당`,
`${money(sheet.operator_daily_wage)}${money(sheet.operator_krw_per_hour)}`,
],
[
"③ 시간당 사용료",
"재료비 / 노무비 / 경비",
`${money(sheet.material_krw)} / ${money(sheet.labor_krw)} / ${money(sheet.expense_krw)}`,
],
["", "합 계", money(sheet.total_krw)],
],
[0, 1],
),
);
if (sheet.variant) {
box.append(
note(
"같은 기종이라도 조합 사용이면 잡재료가 16% 로 줄어 재료비가 달라집니다 —" +
" 그래서 층이 따로 섭니다(건설품셈 제8장 [주]⑤).",
),
);
}
if (sheet.attachment_note) box.append(note(sheet.attachment_note));
if (sheet.operator_note) box.append(note(sheet.operator_note));
for (const gap of sheet.gaps) box.append(note(`⚠ ${gap}`));
return box;
}
export function drawMachineExpense(body: HTMLElement, data: MachineExpenseDto): void {
body.append(head(`각종 중기경비계산서 (${data.sheets.length})`));
body.append(note(data.summary));
for (const line of data.notes) body.append(note(line));
for (const sheet of data.sheets) body.append(machineExpenseSheet(sheet));
}