refactor(b09): 옛 탭 옮기기 ④ 중기경비계산서 — 옛 BaseData 에서 UI_MachineExpense 로
- 화면 확인: 옮기기 전후 같음 — 중기 탭 표 19 · 줄 171 · 계산서 18 장(불도저 19 손료계수 1811 · 시간당 손료 35,884.965) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
/* =============================================================================
|
||||
* 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_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));
|
||||
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));
|
||||
}
|
||||
Reference in New Issue
Block a user