Files
frontend/apps/sn/app/(map-layout)/map/components/aged-pipe-status-by-ctpv/aged-pipe-status-by-ctpv-export.ts
T

82 lines
3.0 KiB
TypeScript

/** 시도별 노후관로 현황의 연도 그룹형 엑셀 데이터를 생성한다. */
"use client";
import * as XLSX from "xlsx";
import { getRawJson } from "@/shared/api/sewerage-api";
import {
getAgedPipeStatusByCtpvValidationMessage,
normalizeAgedPipeStatusByCtpvFilters,
type AgedPipeStatusByCtpvFilters,
type AgedPipeStatusByCtpvResponse,
} from "./aged-pipe-status-by-ctpv-utils";
/** 적용조건의 시도별 노후관로현황 전체를 조회해 연도 그룹 Excel로 생성한다. */
export const downloadAgedPipeStatusByCtpvExcel = async (
filters: AgedPipeStatusByCtpvFilters,
) => {
const validationMessage = getAgedPipeStatusByCtpvValidationMessage(filters);
if (validationMessage) throw new Error(validationMessage);
const normalized = normalizeAgedPipeStatusByCtpvFilters(filters);
const params = new URLSearchParams({
startYear: String(normalized.startYear),
endYear: String(normalized.endYear),
elapsedYears: String(normalized.elapsedYears),
});
const response: any = await getRawJson(
`v1/swagePpl/agedStatusByCtpv?${params.toString()}`,
);
const payload = (response?.data ?? response) as AgedPipeStatusByCtpvResponse;
const years = Array.isArray(payload?.years)
? payload.years.map(Number).filter(Number.isFinite)
: [];
const rows = Array.isArray(payload?.rows) ? payload.rows : [];
if (rows.length === 0) throw new Error("다운로드할 데이터가 없습니다.");
const headers = ["순번", "시도"];
years.forEach((year) => headers.push(`${year}년`, "", ""));
const subHeaders = ["", ""];
years.forEach(() =>
subHeaders.push("전체관로연장(km)", "노후관로연장(km)", "노후화율(%)"),
);
const data = rows.map((row, rowIndex) => {
const statsByYear = new Map(
(row.yearStats ?? []).map((stat) => [Number(stat.year), stat]),
);
const values: Array<string | number> = [rowIndex + 1, row.ctpvNm || "-"];
years.forEach((year) => {
const stat = statsByYear.get(year);
values.push(
stat ? Number(stat.totalLengthKm ?? 0) : "-",
stat ? Number(stat.agedLengthKm ?? 0) : "-",
stat ? Number(stat.agedRate ?? 0) : "-",
);
});
return values;
});
const worksheet = XLSX.utils.aoa_to_sheet([headers, subHeaders, ...data]);
worksheet["!merges"] = [
{ s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },
{ s: { r: 0, c: 1 }, e: { r: 1, c: 1 } },
...years.map((_, index) => ({
s: { r: 0, c: 2 + index * 3 },
e: { r: 0, c: 4 + index * 3 },
})),
];
worksheet["!cols"] = [
{ wch: 8 },
{ wch: 18 },
...years.flatMap(() => [{ wch: 18 }, { wch: 18 }, { wch: 14 }]),
];
worksheet["!autofilter"] = {
ref: `A2:${XLSX.utils.encode_col(headers.length - 1)}${data.length + 2}`,
};
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "시도별 노후관로현황");
XLSX.writeFile(workbook, "시도별_노후관로현황.xlsx", {
bookType: "xlsx",
compression: true,
cellStyles: true,
});
};