82 lines
3.0 KiB
TypeScript
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,
|
|
});
|
|
};
|