조사사업 등록·결과 업로드 및 관로·맨홀 종합집계 화면 구현
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
import {
|
||||
getBlobData,
|
||||
getData,
|
||||
postMutiPart,
|
||||
postRawJson,
|
||||
putData,
|
||||
} from "@/components/lib/api";
|
||||
import type {
|
||||
ExmnAttachmentKey,
|
||||
ExmnBusiness,
|
||||
ExmnBusinessDetail,
|
||||
ExmnBusinessSaveRequest,
|
||||
ExmnBusinessSearchParams,
|
||||
ExmnFileType,
|
||||
ExmnImportCommitResult,
|
||||
ExmnImportValidationResult,
|
||||
ExmnJobType,
|
||||
ExmnPage,
|
||||
ExmnSectionSummaryRow,
|
||||
ExmnTemplateResult,
|
||||
PplFacility,
|
||||
PplFacilitySearchParams,
|
||||
PplSummaryRow,
|
||||
} from "../model/exmn-business-types";
|
||||
|
||||
/** 조사사업 API의 공통 기준 경로다. */
|
||||
const EXMN_BUSINESS_API_PATH = "v1/exmnBusinesses";
|
||||
|
||||
/** 공통 응답 원문 또는 data 래퍼 양쪽에서 실제 payload를 해석한다. */
|
||||
const unwrapData = <T>(response: T | { data?: T }): T =>
|
||||
typeof response === "object" && response !== null && "data" in response
|
||||
? (response as { data: T }).data
|
||||
: (response as T);
|
||||
|
||||
/** Spring Page 응답이 비어 있거나 아직 미구현이어도 안전한 빈 Page로 정규화한다. */
|
||||
const toPage = <T>(value: Partial<ExmnPage<T>> | null | undefined): ExmnPage<T> => ({
|
||||
content: Array.isArray(value?.content) ? value.content : [],
|
||||
totalElements: Number(value?.totalElements ?? 0),
|
||||
number: Number(value?.number ?? 0),
|
||||
size: Number(value?.size ?? 20),
|
||||
totalPages: Number(value?.totalPages ?? 0),
|
||||
});
|
||||
|
||||
/** 조사사업 목록을 조회조건·0-base 페이지·서버 정렬 계약으로 요청한다. */
|
||||
export const getExmnBusinesses = async (
|
||||
params: ExmnBusinessSearchParams,
|
||||
): Promise<ExmnPage<ExmnBusiness>> => {
|
||||
const query = new URLSearchParams({
|
||||
page: String(params.page),
|
||||
size: String(params.size),
|
||||
});
|
||||
if (params.bizCycl?.trim()) query.set("bizCycl", params.bizCycl.trim());
|
||||
if (params.bizYr?.trim()) query.set("bizYr", params.bizYr.trim());
|
||||
if (params.ctpvNm?.trim()) query.set("ctpvNm", params.ctpvNm.trim());
|
||||
if (params.sggNm?.trim()) query.set("sggNm", params.sggNm.trim());
|
||||
if (params.bizNm?.trim()) query.set("bizNm", params.bizNm.trim());
|
||||
if (params.sort) query.set("sort", params.sort);
|
||||
|
||||
return toPage<ExmnBusiness>(await getData(`${EXMN_BUSINESS_API_PATH}?${query}`));
|
||||
};
|
||||
|
||||
/** 선택 사업의 처리분구별 관로·맨홀 조사 상세현황을 조회한다. */
|
||||
export const getExmnSectionSummaries = async (
|
||||
exmnBizId: string,
|
||||
jobType: ExmnJobType,
|
||||
): Promise<ExmnSectionSummaryRow[]> => {
|
||||
type SectionSummaryPayload = ExmnSectionSummaryRow[] | Partial<ExmnPage<ExmnSectionSummaryRow>>;
|
||||
const response = await getData(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/sections?jobType=${jobType}`,
|
||||
) as SectionSummaryPayload | { data?: SectionSummaryPayload };
|
||||
const payload = unwrapData<SectionSummaryPayload>(response);
|
||||
if (Array.isArray(payload)) return payload;
|
||||
return Array.isArray(payload?.content) ? payload.content : [];
|
||||
};
|
||||
|
||||
/** 선택한 조사사업의 처리분구·첨부를 포함한 상세정보를 조회한다. */
|
||||
export const getExmnBusiness = async (exmnBizId: string): Promise<ExmnBusinessDetail> =>
|
||||
getData(`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}`) as Promise<ExmnBusinessDetail>;
|
||||
|
||||
/** 조사사업과 선택 처리분구별 기본 요약행을 신규 저장한다. */
|
||||
export const createExmnBusiness = async (
|
||||
request: ExmnBusinessSaveRequest,
|
||||
): Promise<ExmnBusinessDetail> =>
|
||||
unwrapData<ExmnBusinessDetail>(await postRawJson(EXMN_BUSINESS_API_PATH, request));
|
||||
|
||||
/** 기존 조사사업 기본정보와 연결 처리분구를 같은 저장 계약으로 갱신한다. */
|
||||
export const updateExmnBusiness = async (
|
||||
exmnBizId: string,
|
||||
request: ExmnBusinessSaveRequest,
|
||||
): Promise<ExmnBusinessDetail> =>
|
||||
putData(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}`,
|
||||
request,
|
||||
) as Promise<ExmnBusinessDetail>;
|
||||
|
||||
/** 저장된 사업의 처리분구별 PPL/MNHL 엑셀 시트명을 생성한다. */
|
||||
export const createExmnTemplates = async (
|
||||
exmnBizId: string,
|
||||
trtdstIds: string[],
|
||||
): Promise<ExmnTemplateResult> =>
|
||||
unwrapData<ExmnTemplateResult>(await postRawJson(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/templates`,
|
||||
{ trtdstIds },
|
||||
));
|
||||
|
||||
/** 생성된 조사사업 입력 양식 파일을 내려받는다. */
|
||||
export const downloadExmnTemplates = async (exmnBizId: string): Promise<Blob> =>
|
||||
getBlobData(`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/templates/download`);
|
||||
|
||||
/** 사업 파일별 첨부서비스 키 쌍을 조사사업에 연결한다. */
|
||||
export const updateExmnAttachments = async (
|
||||
exmnBizId: string,
|
||||
attachments: Partial<Record<ExmnFileType, ExmnAttachmentKey>>,
|
||||
): Promise<Partial<Record<ExmnFileType, ExmnAttachmentKey>>> =>
|
||||
putData(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/attachments`,
|
||||
{ attachments },
|
||||
) as Promise<Partial<Record<ExmnFileType, ExmnAttachmentKey>>>;
|
||||
|
||||
/** 원본 PPL/MNHL 파일의 업무·JSON 정합성을 서버에서 검토한다. */
|
||||
export const validateExmnImport = async (
|
||||
exmnBizId: string,
|
||||
formData: FormData,
|
||||
): Promise<ExmnImportValidationResult> =>
|
||||
postMutiPart(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/imports/validate`,
|
||||
formData,
|
||||
) as Promise<ExmnImportValidationResult>;
|
||||
|
||||
/** 검토했던 동일 파일과 첨부키를 다시 보내 시설 저장·요약 집계를 확정한다. */
|
||||
export const commitExmnImport = async (
|
||||
exmnBizId: string,
|
||||
formData: FormData,
|
||||
): Promise<ExmnImportCommitResult> =>
|
||||
postMutiPart(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/imports/commit`,
|
||||
formData,
|
||||
) as Promise<ExmnImportCommitResult>;
|
||||
|
||||
/** 선택 사업의 처리분구별 PPL 집계를 조회한다. */
|
||||
export const getPplSummaries = async (
|
||||
exmnBizId: string,
|
||||
params: { trtdstId?: string; page: number; size: number; sort?: string },
|
||||
): Promise<ExmnPage<PplSummaryRow>> => {
|
||||
const query = new URLSearchParams({ page: String(params.page), size: String(params.size) });
|
||||
if (params.trtdstId) query.set("trtdstId", params.trtdstId);
|
||||
if (params.sort) query.set("sort", params.sort);
|
||||
return toPage<PplSummaryRow>(await getData(
|
||||
`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/summaries/ppl?${query}`,
|
||||
));
|
||||
};
|
||||
|
||||
/** 선택 사업의 PPL 시설을 처리분구·구간·GIS번호·등급으로 조회한다. */
|
||||
export const getPplFacilities = async (
|
||||
params: PplFacilitySearchParams,
|
||||
): Promise<ExmnPage<PplFacility>> => {
|
||||
const query = new URLSearchParams({
|
||||
exmnBizId: params.exmnBizId,
|
||||
jobType: "PPL",
|
||||
page: String(params.page),
|
||||
size: String(params.size),
|
||||
});
|
||||
if (params.trtdstId) query.set("trtdstId", params.trtdstId);
|
||||
if (params.sectionType) query.set("sectionType", params.sectionType);
|
||||
if (params.gisManagementNo?.trim()) query.set("gisManagementNo", params.gisManagementNo.trim());
|
||||
if (params.structuralGrade) query.set("structuralGrade", params.structuralGrade);
|
||||
if (params.operationalGrade) query.set("operationalGrade", params.operationalGrade);
|
||||
if (params.defectType && params.defectType !== "ALL") query.set("defectType", params.defectType);
|
||||
if (params.sort) query.set("sort", params.sort);
|
||||
return toPage<PplFacility>(await getData(`v1/exmnFacilities?${query}`));
|
||||
};
|
||||
|
||||
/** 현재 PPL 조회조건을 서버 엑셀로 내려받는다. */
|
||||
export const downloadPplExport = async (
|
||||
exmnBizId: string,
|
||||
trtdstId?: string,
|
||||
): Promise<Blob> => {
|
||||
const query = new URLSearchParams();
|
||||
if (trtdstId) query.set("trtdstId", trtdstId);
|
||||
const queryString = query.toString();
|
||||
const suffix = queryString ? `?${queryString}` : "";
|
||||
return getBlobData(`${EXMN_BUSINESS_API_PATH}/${encodeURIComponent(exmnBizId)}/exports/ppl${suffix}`);
|
||||
};
|
||||
Reference in New Issue
Block a user