237 lines
7.8 KiB
TypeScript
237 lines
7.8 KiB
TypeScript
"use client";
|
|
|
|
import type { SelectDataType } from "@common/business_components";
|
|
import { formatDisplayData } from "@/components/lib/utils/formatDisplayValue";
|
|
import {
|
|
MS_SWAGE_PPL_CODES,
|
|
MS_SWAGE_PPL_USE_CODES,
|
|
} from "../common/table";
|
|
|
|
export const AGED_PIPE_LAYER_TYPE = "tb_ms_swage_ppl";
|
|
export const AGED_PIPE_DEFAULT_ELAPSED_YEARS = 30;
|
|
export const AGED_PIPE_PAGE_SIZE = 10;
|
|
export const AGED_PIPE_MIN_ZOOM = 14;
|
|
export const AGED_PIPE_INVALID_INSTALL_YMD_PREFIXES = ["19000101", "19990101"];
|
|
|
|
export type AgedPipeFilters = {
|
|
elapsedYears: number;
|
|
ctpvCd: string;
|
|
sggCd: string;
|
|
};
|
|
|
|
export type AgedPipeRow = {
|
|
fid: string;
|
|
lyrTypeNm: string;
|
|
rowNumber: number;
|
|
fcltMngNo: string;
|
|
instlYmd: string;
|
|
pdmtVl: string | number;
|
|
prlgVl: string | number;
|
|
usgCd: string;
|
|
mqltCd: string;
|
|
elapsedYears: number | string;
|
|
ctpvNm?: string;
|
|
sggNm?: string;
|
|
[key: string]: unknown;
|
|
};
|
|
|
|
type PipeSource = Record<string, unknown>;
|
|
|
|
const useMap = new Map(MS_SWAGE_PPL_USE_CODES.map((item) => [item.val.trim(), item.text]));
|
|
const materialMap = new Map(MS_SWAGE_PPL_CODES.map((item) => [item.val.trim(), item.text]));
|
|
|
|
export const AGED_PIPE_DEFAULT_FILTERS: AgedPipeFilters = {
|
|
elapsedYears: AGED_PIPE_DEFAULT_ELAPSED_YEARS,
|
|
ctpvCd: "0",
|
|
sggCd: "0",
|
|
};
|
|
|
|
export const AGED_PIPE_LIST_HEADLIST = [
|
|
{ id: "rowNumber", title: "NO", widthPercent: 6 },
|
|
{ id: "fcltMngNo", title: "시설관리번호", widthPercent: 18 },
|
|
{ id: "instlYmd", title: "설치일자", widthPercent: 12 },
|
|
{ id: "pdmtVl", title: "관경(mm)", widthPercent: 10 },
|
|
{ id: "prlgVl", title: "연장(m)", widthPercent: 10 },
|
|
{ id: "usgCd", title: "용도", widthPercent: 14 },
|
|
{ id: "mqltCd", title: "재질", widthPercent: 18 },
|
|
{ id: "elapsedYears", title: "경과년도", widthPercent: 12, align: "right" },
|
|
];
|
|
|
|
export const AGED_PIPE_EXCEL_HEADER = {
|
|
rowNumber: "NO",
|
|
fcltMngNo: "시설관리번호",
|
|
instlYmd: "설치일자",
|
|
pdmtVl: "관경(mm)",
|
|
prlgVl: "연장(m)",
|
|
usgCd: "용도",
|
|
mqltCd: "재질",
|
|
elapsedYears: "경과년도",
|
|
ctpvNm: "시도",
|
|
sggNm: "시군구",
|
|
};
|
|
|
|
const pad2 = (value: number) => String(value).padStart(2, "0");
|
|
|
|
const normalizeYmd = (value: unknown) =>
|
|
String(value ?? "").replace(/[^0-9]/g, "").slice(0, 8);
|
|
|
|
const getToday = () => new Date();
|
|
|
|
export const normalizeAgedPipeFilters = (filters: AgedPipeFilters): AgedPipeFilters => {
|
|
const elapsedYears = Math.trunc(Number(filters.elapsedYears));
|
|
|
|
return {
|
|
...filters,
|
|
elapsedYears:
|
|
Number.isFinite(elapsedYears) && elapsedYears >= 1 && elapsedYears <= 100
|
|
? elapsedYears
|
|
: AGED_PIPE_DEFAULT_ELAPSED_YEARS,
|
|
};
|
|
};
|
|
|
|
export const validateElapsedYears = (value: number) =>
|
|
Number.isInteger(value) && value >= 1 && value <= 100;
|
|
|
|
export const getCutoffYmd = (elapsedYears: number) => {
|
|
const today = getToday();
|
|
const cutoff = new Date(today.getFullYear() - elapsedYears, today.getMonth(), today.getDate());
|
|
return `${cutoff.getFullYear()}${pad2(cutoff.getMonth() + 1)}${pad2(cutoff.getDate())}`;
|
|
};
|
|
|
|
export const getElapsedYears = (value: unknown) => {
|
|
const normalized = normalizeYmd(value);
|
|
if (normalized.length < 4 || isInvalidInstallYmd(value)) return null;
|
|
|
|
const year = Number(normalized.slice(0, 4));
|
|
const month = Number(normalized.slice(4, 6) || "1");
|
|
const day = Number(normalized.slice(6, 8) || "1");
|
|
if (!year) return null;
|
|
|
|
const today = getToday();
|
|
let elapsed = today.getFullYear() - year;
|
|
if (
|
|
today.getMonth() + 1 < month ||
|
|
(today.getMonth() + 1 === month && today.getDate() < day)
|
|
) {
|
|
elapsed -= 1;
|
|
}
|
|
|
|
return Math.max(elapsed, 0);
|
|
};
|
|
|
|
export const isInvalidInstallYmd = (value: unknown) => {
|
|
const normalized = normalizeYmd(value);
|
|
return (
|
|
normalized.length < 8 ||
|
|
AGED_PIPE_INVALID_INSTALL_YMD_PREFIXES.some((prefix) => normalized.startsWith(prefix))
|
|
);
|
|
};
|
|
|
|
export const getElapsedYearsDisplayText = (value: unknown) => {
|
|
const elapsedYears = getElapsedYears(value);
|
|
return elapsedYears == null ? "확인불가" : `${elapsedYears}년`;
|
|
};
|
|
|
|
export const buildAgedPipeCqlFilters = (filters: AgedPipeFilters) => {
|
|
const normalized = normalizeAgedPipeFilters(filters);
|
|
const cqlFilters = [
|
|
"instl_ymd IS NOT NULL",
|
|
...AGED_PIPE_INVALID_INSTALL_YMD_PREFIXES.map((prefix) => `instl_ymd NOT LIKE '${prefix}%'`),
|
|
`instl_ymd <= '${getCutoffYmd(normalized.elapsedYears)}'`,
|
|
];
|
|
|
|
if (normalized.sggCd !== "0") {
|
|
cqlFilters.push(`pbadms_emd_cd LIKE '${normalized.sggCd}%'`);
|
|
} else if (normalized.ctpvCd !== "0") {
|
|
cqlFilters.push(`pbadms_emd_cd LIKE '${normalized.ctpvCd}%'`);
|
|
}
|
|
|
|
return cqlFilters;
|
|
};
|
|
|
|
const getRegionCode = (source: PipeSource) =>
|
|
String(source.pbadmsEmdCd ?? source.pbadms_emd_cd ?? "").trim();
|
|
|
|
export const matchesAgedPipeFilters = (source: PipeSource, filters: AgedPipeFilters) => {
|
|
const normalized = normalizeAgedPipeFilters(filters);
|
|
const instlYmd = normalizeYmd(source.instl_ymd ?? source.instlYmd);
|
|
if (!instlYmd || isInvalidInstallYmd(instlYmd) || instlYmd > getCutoffYmd(normalized.elapsedYears)) return false;
|
|
|
|
const regionCode = getRegionCode(source);
|
|
if (normalized.sggCd !== "0") return regionCode.startsWith(normalized.sggCd);
|
|
if (normalized.ctpvCd !== "0") return regionCode.startsWith(normalized.ctpvCd);
|
|
return true;
|
|
};
|
|
|
|
const resolveRegionName = (
|
|
code: string,
|
|
directName: unknown,
|
|
options: SelectDataType[],
|
|
prefixLength: number,
|
|
) => {
|
|
const direct = String(directName ?? "").trim();
|
|
if (direct) return direct;
|
|
|
|
const prefix = code.slice(0, prefixLength);
|
|
return options.find((item) => String(item.val).trim() === prefix)?.text ?? "";
|
|
};
|
|
|
|
export const toDisplayPipeRow = (
|
|
source: PipeSource,
|
|
index: number,
|
|
page: number,
|
|
ctpvOptions: SelectDataType[],
|
|
sggOptions: SelectDataType[],
|
|
): AgedPipeRow => {
|
|
const formatted = formatDisplayData(source) as PipeSource;
|
|
const codePrefix = getRegionCode(source);
|
|
const instlYmd = formatted.instlYmd ?? source.instlYmd ?? formatted.instl_ymd ?? source.instl_ymd;
|
|
const invalidInstallYmd = isInvalidInstallYmd(source.instlYmd ?? source.instl_ymd ?? instlYmd);
|
|
const trimmedUse = String(source.usgCd ?? source.usg_cd ?? "").trim();
|
|
const trimmedMaterial = String(source.mqltCd ?? source.mqlt_cd ?? "").trim();
|
|
const pdmtVl = formatted.pdmtVl ?? source.pdmtVl ?? source.pdmt_vl ?? "-";
|
|
const prlgVl = formatted.prlgVl ?? source.prlgVl ?? source.prlg_vl ?? "-";
|
|
const fcltMngNo = String(formatted.fcltMngNo ?? source.fcltMngNo ?? source.fclt_mng_no ?? "-");
|
|
|
|
return {
|
|
...source,
|
|
...formatted,
|
|
fid: String(source.fid ?? ""),
|
|
lyrTypeNm: String(source.lyrTypeNm ?? AGED_PIPE_LAYER_TYPE),
|
|
rowNumber: (page - 1) * AGED_PIPE_PAGE_SIZE + index + 1,
|
|
fcltMngNo,
|
|
swtrmtFcltCd: source.swtrmtFcltCd ?? fcltMngNo,
|
|
instlYmd: invalidInstallYmd ? "확인불가" : String(instlYmd ?? "-"),
|
|
pdmtVl: typeof pdmtVl === "number" ? pdmtVl : String(pdmtVl),
|
|
prlgVl: typeof prlgVl === "number" ? prlgVl : String(prlgVl),
|
|
usgCd: useMap.get(trimmedUse) ?? String(formatted.usgCd ?? source.usgCd ?? source.usg_cd ?? "-"),
|
|
mqltCd:
|
|
materialMap.get(trimmedMaterial) ??
|
|
String(formatted.mqltCd ?? source.mqltCd ?? source.mqlt_cd ?? "-"),
|
|
elapsedYears: getElapsedYears(source.instlYmd ?? source.instl_ymd) ?? "확인불가",
|
|
ctpvNm: resolveRegionName(
|
|
codePrefix,
|
|
formatted.ctpvNm ?? source.ctpvNm ?? source.ctpv_nm,
|
|
ctpvOptions,
|
|
2,
|
|
),
|
|
sggNm: resolveRegionName(
|
|
codePrefix,
|
|
formatted.sggNm ?? source.sggNm ?? source.sgg_nm,
|
|
sggOptions,
|
|
5,
|
|
),
|
|
};
|
|
};
|
|
|
|
export const isAgedPipeLayerNode = (node: any) => {
|
|
const data = node?.data ?? node;
|
|
const layerName = String(data?.lyrNm ?? node?.text ?? "");
|
|
const layerTypeName = String(data?.lyrTyNm ?? "");
|
|
|
|
return (
|
|
layerTypeName === "tb_old_pipe" ||
|
|
layerName.includes("노후관로")
|
|
);
|
|
};
|