[as] feat: 결재선 저장 api 수정

This commit is contained in:
2026-07-08 19:22:40 +09:00
parent 843519c3b5
commit 35b6f4ae54
5 changed files with 161 additions and 11 deletions
@@ -26,8 +26,10 @@ async function findById(elaprPrgrsId: string): Promise<ElaprPrgrsSttsResponseDto
return response.data;
}
async function save(body: ElaprPrgrsSttsSaveRequestDto): Promise<ElaprPrgrsSttsResponseDto> {
const response = await client.post<ElaprPrgrsSttsResponseDto>(BASE, body);
async function save(
requestDtos: ElaprPrgrsSttsSaveRequestDto[],
): Promise<ElaprPrgrsSttsResponseDto[]> {
const response = await client.post<ElaprPrgrsSttsResponseDto[]>(BASE, requestDtos);
return response.data;
}
+2 -1
View File
@@ -272,7 +272,8 @@ export function useSaveElaprPrgrsStts() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (body: ElaprPrgrsSttsSaveRequestDto) => elaprPrgrsSttsService.save(body),
mutationFn: (requestDtos: ElaprPrgrsSttsSaveRequestDto[]) =>
elaprPrgrsSttsService.save(requestDtos),
onSuccess: () => {
invalidateElaprPrgrsSttsQueries(queryClient);
},
+12 -4
View File
@@ -43,14 +43,20 @@ export {
validateAtrzOrder,
validateUniqueSeqNo,
} from "./lib/apln-validators";
export {
buildElaprPrgrsSttsListFromApln,
buildElaprPrgrsSttsListFromAplnRows,
} from "./lib/dmnd-save-utils";
export {
findCurrentUserPendingApprovalRequest,
hasCurrentUserPendingApprovalRequest,
} from "./lib/approval-request-utils";
export {
buildElaprPrgrsSttsListFromApln,
buildElaprPrgrsSttsListFromAplnRows,
} from "./lib/dmnd-save-utils";
export type { ElaprPrgrsSttsRow } from "./lib/prgrs-stts-save-utils";
export {
assignPrgrsSttsAtrzSeqNumbers,
buildPrgrsSttsSavePayload,
hasUnsavedPrgrsSttsChanges,
} from "./lib/prgrs-stts-save-utils";
export { createDraftRowKey, useAplnRows } from "./lib/use-apln-rows";
export { useDndSensors } from "./lib/use-dnd-sensors";
export {
@@ -77,11 +83,13 @@ export type {
ElaprApproverInsertRequestDto,
ElaprPrgrsSttsMyDocSearchParams,
ElaprPrgrsSttsResponseDto,
ElaprPrgrsSttsSaveMode,
ElaprPrgrsSttsSaveRequestDto,
ElaprPrgrsSttsSearchDto,
ElaprPrgrsSttsService,
ElaprProcessRequestDto,
} from "./model/elapr-prgrs-stts-interface";
export { ELAPR_PRGRS_STTS_SAVE_MODE } from "./model/elapr-prgrs-stts-interface";
export type {
ElaprTmplt,
ElaprTmpltSaveRequest,
@@ -0,0 +1,127 @@
import {
ELAPR_PRGRS_STTS_SAVE_MODE,
type ElaprPrgrsSttsResponseDto,
type ElaprPrgrsSttsSaveRequestDto,
} from "../model/elapr-prgrs-stts-interface";
/** 결재선 그리드 로컬 행 — 진행상태 API 응답 + UI 보조 필드 */
export interface ElaprPrgrsSttsRow {
rowKey: string;
elaprPrgrsId?: string;
elaprDmndId?: string;
aprvrUuid?: string;
atrzSeComCd?: string;
atrzSeqNo?: number;
atrzPrgrsSttsComCd?: string;
isNew?: boolean;
isDirty?: boolean;
/** 소프트 삭제 — 최종 저장 시 mode:D */
isDeleted?: boolean;
/** 수정 취소용 스냅샷 */
snapshot?: ElaprPrgrsSttsRow;
}
function getVisibleRows(rows: ElaprPrgrsSttsRow[]): ElaprPrgrsSttsRow[] {
return rows.filter((row) => !row.isDeleted);
}
/** 그리드 행 순서(1-based)로 결재순서번호 일괄 채번 */
export function assignPrgrsSttsAtrzSeqNumbers(rows: ElaprPrgrsSttsRow[]): ElaprPrgrsSttsRow[] {
return rows.map((row, index) => ({ ...row, atrzSeqNo: index + 1 }));
}
function rowDiffersFromServer(
row: ElaprPrgrsSttsRow,
serverRow: ElaprPrgrsSttsResponseDto,
): boolean {
return (
row.aprvrUuid !== serverRow.aprvrUuid ||
row.atrzSeComCd !== serverRow.atrzSeComCd ||
row.atrzSeqNo !== serverRow.atrzSeqNo
);
}
function shouldIncludeUpdate(
row: ElaprPrgrsSttsRow,
serverRows: ElaprPrgrsSttsResponseDto[],
): boolean {
if (row.isDirty) return true;
if (!row.elaprPrgrsId) return false;
const serverRow = serverRows.find((s) => s.elaprPrgrsId === row.elaprPrgrsId);
if (!serverRow) return false;
return rowDiffersFromServer(row, serverRow);
}
export function hasUnsavedPrgrsSttsChanges(
rows: ElaprPrgrsSttsRow[],
serverRows: ElaprPrgrsSttsResponseDto[],
): boolean {
if (rows.some((row) => row.isDeleted && row.elaprPrgrsId)) return true;
if (rows.some((row) => row.isNew && !row.isDeleted)) return true;
const visibleWithSeq = assignPrgrsSttsAtrzSeqNumbers(getVisibleRows(rows));
for (const row of visibleWithSeq) {
if (row.isNew) continue;
if (!row.elaprPrgrsId) continue;
if (row.isDirty) return true;
const serverRow = serverRows.find((s) => s.elaprPrgrsId === row.elaprPrgrsId);
if (!serverRow) continue;
if (rowDiffersFromServer(row, serverRow)) return true;
}
return false;
}
export function buildPrgrsSttsSavePayload(
rows: ElaprPrgrsSttsRow[],
elaprDmndId: string,
serverRows: ElaprPrgrsSttsResponseDto[],
): ElaprPrgrsSttsSaveRequestDto[] {
const payload: ElaprPrgrsSttsSaveRequestDto[] = [];
for (const row of rows) {
if (row.isDeleted && row.elaprPrgrsId) {
payload.push({
mode: ELAPR_PRGRS_STTS_SAVE_MODE.DELETE,
elaprPrgrsId: row.elaprPrgrsId,
elaprDmndId,
});
}
}
const visibleWithSeq = assignPrgrsSttsAtrzSeqNumbers(getVisibleRows(rows));
for (const row of visibleWithSeq) {
if (row.isNew) {
payload.push({
mode: ELAPR_PRGRS_STTS_SAVE_MODE.CREATE,
elaprDmndId,
aprvrUuid: row.aprvrUuid,
atrzSeComCd: row.atrzSeComCd,
atrzSeqNo: row.atrzSeqNo,
atrzPrgrsSttsComCd: row.atrzPrgrsSttsComCd,
});
continue;
}
if (!row.elaprPrgrsId) continue;
if (shouldIncludeUpdate(row, serverRows)) {
payload.push({
mode: ELAPR_PRGRS_STTS_SAVE_MODE.UPDATE,
elaprPrgrsId: row.elaprPrgrsId,
elaprDmndId,
aprvrUuid: row.aprvrUuid,
atrzSeComCd: row.atrzSeComCd,
atrzSeqNo: row.atrzSeqNo,
atrzPrgrsSttsComCd: row.atrzPrgrsSttsComCd,
});
}
}
return payload;
}
@@ -1,5 +1,15 @@
import type { PageableParams, PageResponse } from "@/shared/model";
export const ELAPR_PRGRS_STTS_SAVE_MODE = {
CREATE: "C",
READ: "R",
UPDATE: "U",
DELETE: "D",
} as const;
export type ElaprPrgrsSttsSaveMode =
(typeof ELAPR_PRGRS_STTS_SAVE_MODE)[keyof typeof ELAPR_PRGRS_STTS_SAVE_MODE];
/** 백엔드 ElaprPrgrsSttsResponseDto */
export interface ElaprPrgrsSttsResponseDto {
elaprPrgrsId: string;
@@ -16,10 +26,12 @@ export interface ElaprPrgrsSttsResponseDto {
/** 백엔드 ElaprPrgrsSttsSaveRequestDto */
export interface ElaprPrgrsSttsSaveRequestDto {
mode?: ElaprPrgrsSttsSaveMode;
elaprPrgrsId?: string;
elaprDmndId?: string;
aprvrUuid: string;
atrzSeComCd: string;
atrzSeqNo: number;
aprvrUuid?: string;
atrzSeComCd?: string;
atrzSeqNo?: number;
atrzPrgrsSttsComCd?: string;
}
@@ -56,7 +68,7 @@ export interface ElaprApproverInsertRequestDto {
export interface ElaprPrgrsSttsService {
findAllByDmndId(elaprDmndId?: string): Promise<ElaprPrgrsSttsResponseDto[]>;
findById(elaprPrgrsId: string): Promise<ElaprPrgrsSttsResponseDto>;
save(body: ElaprPrgrsSttsSaveRequestDto): Promise<ElaprPrgrsSttsResponseDto>;
save(requestDtos: ElaprPrgrsSttsSaveRequestDto[]): Promise<ElaprPrgrsSttsResponseDto[]>;
process(elaprPrgrsId: string, body: ElaprProcessRequestDto): Promise<ElaprPrgrsSttsResponseDto>;
processByDocNoAndAprvrUuid(
elaprDocNo: string,