Files
frontend/apps/sn/src/features/dredging/model/registration-request.ts
T

85 lines
3.1 KiB
TypeScript

import type { DredgingSaveGroup } from "./types";
import { createDredgingClientUuid } from "../lib/uuid";
/** 공통 첨부 업로드가 완료된 사진의 서버 식별자다. */
export type AttachmentReference = { atflCd: string; atflId: string };
/** 화면 draft에서 기존 등록 DTO에 해당하는 필드만 명시적으로 추출한다. */
const buildRegistrationBody = (
groups: DredgingSaveGroup[],
attachments: Map<string, AttachmentReference>,
requireAttachments: boolean,
) => ({
dredgingDate: groups[0]?.dredgingDate,
groups: groups.map((group, groupIndex) => ({
groupSn: groupIndex + 1,
registrationMode: group.registrationMode,
location: {
source: group.locationSource,
longitude: group.location.longitude,
latitude: group.location.latitude,
},
expectedPipe: group.pipe ? {
fid: group.pipe.fid,
mngInstCd: group.pipe.mngInstCd,
fcltMngNo: group.pipe.fcltMngNo,
} : null,
photos: group.photos.map((photo) => {
const attachment = attachments.get(photo.key);
if (!attachment && requireAttachments) {
throw new Error(`${photo.file.name}의 첨부 식별자가 없습니다.`);
}
return {
atflCd: attachment?.atflCd,
atflId: attachment?.atflId,
originalFileName: photo.file.name,
clientCapturedAt: photo.metadata.capturedAt,
clientLongitude: photo.metadata.location?.longitude ?? null,
clientLatitude: photo.metadata.location?.latitude ?? null,
};
}),
})),
});
/** 기존 POST /v1/dredging/registrations의 요청 body를 그대로 표현한다. */
export type DredgingRegistrationRequest = ReturnType<
typeof buildRegistrationBody
> & {
clientRequestId: string;
};
/**
* 모달을 연 한 번의 등록 세션이 전송 payload별 중복방지 ID를 소유한다.
* 응답 유실 후 같은 입력 재시도와 수정 후 원래 입력 복원은 같은 ID를 쓴다.
* 날짜·관로·위치·사진 등 실제 전송값이 바뀌면 새 ID를 발급한다.
* 화면 그룹 ID, 관경 표시값, 선택 탭 등 비전송 상태는 등록 의도를 바꾸지 않는다.
*/
export const createDredgingRegistrationSession = (
createId: () => string = createDredgingClientUuid,
) => {
// 세션 밖으로 공유하지 않으며 모달을 다시 열 때 새 Map으로 교체한다.
const requestIds = new Map<string, string>();
return {
/** 첨부 식별자까지 확정된 동일 payload에 항상 같은 요청 ID를 부여한다. */
prepare: (
groups: DredgingSaveGroup[],
attachments: Map<string, AttachmentReference>,
// FE 선행 모의 모드만 첨부 업로드 없이 payload 구성 검증을 허용한다.
requireAttachments = true,
): DredgingRegistrationRequest => {
const body = buildRegistrationBody(
groups,
attachments,
requireAttachments,
);
const signature = JSON.stringify(body);
let clientRequestId = requestIds.get(signature);
if (!clientRequestId) {
clientRequestId = createId();
requestIds.set(signature, clientRequestId);
}
return { clientRequestId, ...body };
},
};
};