[as] 재원협의 병렬및 순차 결재시 버튼및 웹기안기 권한 제어 완료
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import type { ElaprBranchDto } from "../model/elapr-forkjoin-types";
|
||||
|
||||
const BASE = ENDPOINT.AS_ELAPR_SERVICE.ELAPR_BRANCH;
|
||||
|
||||
async function getBranchesByDocNo(elaprDocNo: string): Promise<ElaprBranchDto[]> {
|
||||
const response = await client.get<ElaprBranchDto[]>(`${BASE}/doc/${elaprDocNo}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const elaprBranchService = {
|
||||
getBranchesByDocNo,
|
||||
};
|
||||
@@ -23,6 +23,7 @@ import type {
|
||||
} from "../model/elapr-tmplt-interface";
|
||||
|
||||
import { elaprAplnService } from "./elapr-apln-service";
|
||||
import { elaprBranchService } from "./elapr-branch-service";
|
||||
import { elaprDmndService } from "./elapr-dmnd-service";
|
||||
import { elaprPrgrsSttsService } from "./elapr-prgrs-stts-service";
|
||||
import { elaprTmpltService } from "./elapr-tmplt-service";
|
||||
@@ -31,6 +32,7 @@ const elaprTmpltBaseKey = [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_TMPLT] as const;
|
||||
const elaprAplnBaseKey = [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_APLN] as const;
|
||||
const elaprDmndBaseKey = [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_DMND] as const;
|
||||
const elaprPrgrsSttsBaseKey = [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_PRGRS_STTS] as const;
|
||||
const elaprBranchBaseKey = [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_BRANCH] as const;
|
||||
|
||||
function invalidateElaprPrgrsSttsQueries(queryClient: ReturnType<typeof useQueryClient>) {
|
||||
queryClient.invalidateQueries({ queryKey: elaprPrgrsSttsBaseKey });
|
||||
@@ -360,3 +362,16 @@ export function useInsertElaprPrgrsSttsApprover() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useElaprBranchesByDocNo(
|
||||
elaprDocNo: string | null | undefined,
|
||||
options?: { enabled?: boolean; structuralSharing?: boolean },
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: [...elaprBranchBaseKey, "getBranchesByDocNo", elaprDocNo],
|
||||
queryFn: () => elaprBranchService.getBranchesByDocNo(elaprDocNo!),
|
||||
enabled: Boolean(elaprDocNo) && (options?.enabled ?? true),
|
||||
structuralSharing: options?.structuralSharing ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export { elaprAplnService } from "./api/elapr-apln-service";
|
||||
export { elaprBranchService } from "./api/elapr-branch-service";
|
||||
export { elaprDmndService } from "./api/elapr-dmnd-service";
|
||||
export { elaprPrgrsSttsService } from "./api/elapr-prgrs-stts-service";
|
||||
export { elaprTmpltService } from "./api/elapr-tmplt-service";
|
||||
@@ -9,6 +10,7 @@ export {
|
||||
useDeleteElaprTmplt,
|
||||
useElaprApln,
|
||||
useElaprAplnPage,
|
||||
useElaprBranchesByDocNo,
|
||||
useElaprDmnd,
|
||||
useElaprDmndPage,
|
||||
useElaprDocPrgrsByDocNo,
|
||||
|
||||
@@ -27,6 +27,7 @@ export type BranchSttsCd =
|
||||
| "WAITING"
|
||||
| "IN_PROGRESS"
|
||||
| "COMPLETED"
|
||||
| "SUPPLEMENT"
|
||||
| "REJECTED"
|
||||
| "CANCELLED";
|
||||
|
||||
|
||||
@@ -329,6 +329,8 @@ export interface GetButtonConfigsOptions {
|
||||
canRetryDraftGen?: boolean;
|
||||
canRetryCostVrfc?: boolean;
|
||||
isForkJoin?: boolean;
|
||||
branchSeCd?: "SP" | "SF" | "TOTAL_AGG" | "MAIN" | string;
|
||||
branchSttsCd?: "WAITING" | "IN_PROGRESS" | "COMPLETED" | "SUPPLEMENT" | "REJECTED" | string;
|
||||
}
|
||||
|
||||
const PENDING_APPROVAL_ACTIONS = new Set<FnrsCnsltnViewButtonAction>([
|
||||
@@ -345,9 +347,30 @@ function resolveRoleUser01AtrzButtonActions(
|
||||
atrzSeComCdList: string[],
|
||||
options?: GetButtonConfigsOptions,
|
||||
): FnrsCnsltnViewButtonAction[] {
|
||||
let effectiveStatus = prgrsSttsComCd;
|
||||
|
||||
if (options?.isForkJoin && options?.branchSttsCd) {
|
||||
switch (options.branchSttsCd) {
|
||||
case "SUPPLEMENT":
|
||||
// 본인 브랜치가 보완요청 중이면 'SL' 맵핑 적용 (검토/승인 버튼 숨김, 실무협의서관리만 노출)
|
||||
effectiveStatus = "SL";
|
||||
break;
|
||||
case "IN_PROGRESS":
|
||||
// 본인 브랜치가 정상 진행 중이면 원천 상태('TE' 또는 'RK') 정상 적용!
|
||||
effectiveStatus = prgrsSttsComCd === "RK" ? "RK" : "TE";
|
||||
break;
|
||||
case "COMPLETED":
|
||||
// 본인 브랜치 승인 완료 후 타 브랜치 대기 중이면 조회 전용 맵 적용
|
||||
effectiveStatus = prgrsSttsComCd === "RK" ? "RR" : "TP";
|
||||
break;
|
||||
case "WAITING":
|
||||
return [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng];
|
||||
}
|
||||
}
|
||||
|
||||
const atrzStatusMap = options?.isForkJoin
|
||||
? ROLE_USER01_FORK_JOIN_ATRZ_STATUS_ACTIONS[prgrsSttsComCd]
|
||||
: ROLE_USER01_ATRZ_STATUS_ACTIONS[prgrsSttsComCd];
|
||||
? ROLE_USER01_FORK_JOIN_ATRZ_STATUS_ACTIONS[effectiveStatus]
|
||||
: ROLE_USER01_ATRZ_STATUS_ACTIONS[effectiveStatus];
|
||||
if (!atrzStatusMap || atrzSeComCdList.length === 0) return [];
|
||||
|
||||
const seen = new Set<FnrsCnsltnViewButtonAction>();
|
||||
@@ -382,12 +405,12 @@ function resolveRoleUser01AtrzButtonActions(
|
||||
}
|
||||
|
||||
if (options?.hasCompletedDraft != null) {
|
||||
if (prgrsSttsComCd === "SL" || prgrsSttsComCd === "TE" || prgrsSttsComCd === "RK") {
|
||||
if (effectiveStatus === "SL" || effectiveStatus === "TE" || effectiveStatus === "RK") {
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng) {
|
||||
return options.hasCompletedDraft;
|
||||
}
|
||||
}
|
||||
if (prgrsSttsComCd === "TE") {
|
||||
if (effectiveStatus === "TE") {
|
||||
if (action === FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq) {
|
||||
return options.hasCompletedDraft;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
type ElaprTmpltPickerConfirmPayload,
|
||||
ElaprTmpltPickerDialog,
|
||||
hasCurrentUserPendingApprovalRequest,
|
||||
useElaprBranchesByDocNo,
|
||||
useElaprDocPrgrsByDocNo,
|
||||
} from "@/entities/elapr";
|
||||
import {
|
||||
@@ -139,8 +140,13 @@ function FloatingActionButtons({
|
||||
const docNo = data.detDto?.fnrsCnsltnDocNo ?? fnrsCnsltnDocNo;
|
||||
const isRegister = data.detDto?.rgtr === userInfo?.userUnqId;
|
||||
|
||||
const isForkJoin = isForkJoinTask(data.detDto?.taskSeComCd);
|
||||
const normalizedTaskSeComCd = normalizeTaskSeComCdForElapr(data.detDto?.taskSeComCd);
|
||||
|
||||
const needsAtrzResolve = needsRoleUser01AtrzResolve(dtlInstCd, prgrsSttsComCd);
|
||||
const needsElaprPrgrsCheck = needsAtrzResolve && ["TE", "RK"].includes(prgrsSttsComCd);
|
||||
const needsElaprPrgrsCheck =
|
||||
needsAtrzResolve &&
|
||||
(["TE", "RK"].includes(prgrsSttsComCd) || (isForkJoin && prgrsSttsComCd === "SL"));
|
||||
const needsPwrkDraftCheck =
|
||||
dtlInstCd === "ROLE_USER01" && ["SL", "TE", "RK"].includes(prgrsSttsComCd);
|
||||
const needsPwrkForRb = dtlInstCd === "ROLE_USER05" && prgrsSttsComCd === "RB";
|
||||
@@ -151,6 +157,10 @@ function FloatingActionButtons({
|
||||
const { data: elaprDocPrgrsList = [], isLoading: isElaprDocPrgrsLoading } =
|
||||
useElaprDocPrgrsByDocNo(needsElaprPrgrsCheck ? docNo : null);
|
||||
|
||||
const { data: elaprBranchList = [], isLoading: isElaprBranchLoading } = useElaprBranchesByDocNo(
|
||||
isForkJoin && (needsElaprPrgrsCheck || prgrsSttsComCd === "SL") ? docNo : null,
|
||||
);
|
||||
|
||||
const { data: pwrkCnsltnData, isLoading: isPwrkCnsltnLoading } = usePwrkCnsltnMngByUpDocNo(
|
||||
docNo,
|
||||
needsPwrkLookup,
|
||||
@@ -190,32 +200,101 @@ function FloatingActionButtons({
|
||||
elaprPrgrsForPending,
|
||||
userInfo?.userUnqId,
|
||||
);
|
||||
const currentUserPrgrsRow = elaprPrgrsForPending.find(
|
||||
(row) => row.aprvrUuid === userInfo?.userUnqId,
|
||||
);
|
||||
const userPendingPrgrs = elaprPrgrsForPending.find(
|
||||
(row) =>
|
||||
row.aprvrUuid === userInfo?.userUnqId &&
|
||||
row.atrzPrgrsSttsComCd === "ATRZ_PRGRS_002",
|
||||
);
|
||||
const userPendingBranchSeCd = (userPendingPrgrs as { branchSeCd?: string } | undefined)?.branchSeCd;
|
||||
const userBranchSeCd = (userPendingPrgrs?.branchSeCd ?? currentUserPrgrsRow?.branchSeCd) as
|
||||
| "SP"
|
||||
| "SF"
|
||||
| "TOTAL_AGG"
|
||||
| "MAIN"
|
||||
| undefined;
|
||||
const userPendingBranchSeCd = userPendingPrgrs?.branchSeCd ?? userBranchSeCd;
|
||||
const userPendingAtrzSeComCd = userPendingPrgrs?.atrzSeComCd;
|
||||
|
||||
const normalizedTaskSeComCd = normalizeTaskSeComCdForElapr(data.detDto?.taskSeComCd);
|
||||
const isForkJoin = isForkJoinTask(data.detDto?.taskSeComCd);
|
||||
|
||||
const effectiveAtrzSeComCdList = useMemo(() => {
|
||||
if (isForkJoin && userPendingAtrzSeComCd) {
|
||||
return [userPendingAtrzSeComCd];
|
||||
}
|
||||
if (isForkJoin && currentUserPrgrsRow?.atrzSeComCd) {
|
||||
return [currentUserPrgrsRow.atrzSeComCd];
|
||||
}
|
||||
return atrzSeComCdList;
|
||||
}, [atrzSeComCdList, isForkJoin, userPendingAtrzSeComCd]);
|
||||
}, [atrzSeComCdList, currentUserPrgrsRow?.atrzSeComCd, isForkJoin, userPendingAtrzSeComCd]);
|
||||
|
||||
const supplementDmndBranch = useMemo(() => {
|
||||
if (!isForkJoin) return undefined;
|
||||
|
||||
// 1순위: 전자결재 브랜치(tb_as_elapr_branch) 테이블에서 상태가 SUPPLEMENT인 부서 직접 확인
|
||||
const splmntBranch = elaprBranchList.find((b) => b.branchSttsCd === "SUPPLEMENT");
|
||||
if (splmntBranch?.branchSeCd && ["SP", "SF"].includes(splmntBranch.branchSeCd)) {
|
||||
return splmntBranch.branchSeCd as "SP" | "SF";
|
||||
}
|
||||
|
||||
// 2순위: 미완료 보완요청 항목의 등록자 UUID 매칭
|
||||
const uncompletedItems = data?.splmntDmndList?.filter((item) => item.cmptnYn !== "Y") ?? [];
|
||||
if (uncompletedItems.length > 0) {
|
||||
for (const splmnt of uncompletedItems) {
|
||||
const matchedPrgrs = elaprDocPrgrsList.find(
|
||||
(p) => p.aprvrUuid?.toLowerCase() === splmnt.rgtr?.toLowerCase(),
|
||||
);
|
||||
if (matchedPrgrs?.branchSeCd && ["SP", "SF"].includes(matchedPrgrs.branchSeCd)) {
|
||||
return matchedPrgrs.branchSeCd as "SP" | "SF";
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}, [data?.splmntDmndList, elaprBranchList, elaprDocPrgrsList, isForkJoin]);
|
||||
|
||||
const userBranchSttsCd = useMemo<string | undefined>(() => {
|
||||
if (!isForkJoin || !userBranchSeCd) return undefined;
|
||||
|
||||
// 1. elaprBranchList API 응답에서 사용자 브랜치 상태 확인
|
||||
const matchedBranch = elaprBranchList.find((b) => b.branchSeCd === userBranchSeCd);
|
||||
if (matchedBranch?.branchSttsCd) {
|
||||
return matchedBranch.branchSttsCd;
|
||||
}
|
||||
|
||||
// 2. Fallback: 문서 상태가 SL일 때 보완요청 발생 부서(supplementDmndBranch)와 비교
|
||||
if (prgrsSttsComCd === "SL") {
|
||||
if (supplementDmndBranch && userBranchSeCd === supplementDmndBranch) {
|
||||
return "SUPPLEMENT";
|
||||
}
|
||||
const branchRows = elaprPrgrsForPending.filter((row) => row.branchSeCd === userBranchSeCd);
|
||||
const hasUnfinished = branchRows.some(
|
||||
(row) =>
|
||||
row.atrzPrgrsSttsComCd !== "ATRZ_PRGRS_003" && row.atrzPrgrsSttsComCd !== "ATRZ_PRGRS_999",
|
||||
);
|
||||
return hasUnfinished ? "IN_PROGRESS" : "COMPLETED";
|
||||
}
|
||||
|
||||
if (["TE", "RK"].includes(prgrsSttsComCd)) {
|
||||
return "IN_PROGRESS";
|
||||
}
|
||||
if (["TP", "RR"].includes(prgrsSttsComCd)) {
|
||||
return "COMPLETED";
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [elaprBranchList, elaprPrgrsForPending, isForkJoin, prgrsSttsComCd, supplementDmndBranch, userBranchSeCd]);
|
||||
|
||||
const isBranchInProgress =
|
||||
isForkJoin && userBranchSttsCd === "IN_PROGRESS" && dtlInstCd === "ROLE_USER01";
|
||||
|
||||
const viewOnlyPwrkCnsltnDoc =
|
||||
prgrsSttsComCd === "SL" ||
|
||||
(prgrsSttsComCd === "SL" && dtlInstCd !== "ROLE_USER05" && !isBranchInProgress) ||
|
||||
(prgrsSttsComCd === "RB" && dtlInstCd !== "ROLE_USER05") ||
|
||||
(prgrsSttsComCd === "RK" && dtlInstCd === "ROLE_USER03");
|
||||
|
||||
const actionButtons = useMemo(() => {
|
||||
if (needsAtrzResolve && isRvwLoginUserLoading) return [];
|
||||
if (needsElaprPrgrsCheck && isElaprDocPrgrsLoading) return [];
|
||||
if (isForkJoin && isElaprBranchLoading) return [];
|
||||
if (needsPwrkDraftCheck && isPwrkCnsltnLoading) return [];
|
||||
if (needsAiAutoLatest && isAiAutoLatestLoading) return [];
|
||||
return getButtonConfigs(dtlInstCd, prgrsSttsComCd, effectiveAtrzSeComCdList, {
|
||||
@@ -225,6 +304,8 @@ function FloatingActionButtons({
|
||||
canRetryDraftGen: needsAiAutoLatest ? canRetryDraftGen : undefined,
|
||||
canRetryCostVrfc: needsAiAutoLatest ? canRetryCostVrfc : undefined,
|
||||
isForkJoin,
|
||||
branchSeCd: userBranchSeCd,
|
||||
branchSttsCd: userBranchSttsCd,
|
||||
});
|
||||
}, [
|
||||
canRetryCostVrfc,
|
||||
@@ -235,6 +316,7 @@ function FloatingActionButtons({
|
||||
hasCompletedDraft,
|
||||
hasPendingApprovalRequest,
|
||||
isAiAutoLatestLoading,
|
||||
isElaprBranchLoading,
|
||||
isElaprDocPrgrsLoading,
|
||||
isForkJoin,
|
||||
isPwrkCnsltnLoading,
|
||||
@@ -244,6 +326,8 @@ function FloatingActionButtons({
|
||||
needsElaprPrgrsCheck,
|
||||
needsPwrkDraftCheck,
|
||||
prgrsSttsComCd,
|
||||
userBranchSeCd,
|
||||
userBranchSttsCd,
|
||||
]);
|
||||
|
||||
const canEdit =
|
||||
@@ -287,6 +371,9 @@ function FloatingActionButtons({
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: fnrsCnsltnKeys.detail(fnrsCnsltnDocNo),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_BRANCH],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
let errorMessage = "";
|
||||
@@ -526,7 +613,7 @@ function FloatingActionButtons({
|
||||
data,
|
||||
checklistFormState,
|
||||
"KECO",
|
||||
"TE",
|
||||
prgrsSttsComCd === "SL" ? "SL" : prgrsSttsComCd === "RK" ? "RK" : "TE",
|
||||
"SV",
|
||||
getReviewOpinionFormData(),
|
||||
opnrNm,
|
||||
@@ -541,8 +628,9 @@ function FloatingActionButtons({
|
||||
}
|
||||
|
||||
function handleApprovalOpen() {
|
||||
if (prgrsSttsComCd === "TE" && userPendingBranchSeCd) {
|
||||
const branchCd = (userPendingBranchSeCd as BranchSeCd) || (isForkJoin ? "SP" : "MAIN");
|
||||
const isTeStep = prgrsSttsComCd === "TE" || (isForkJoin && prgrsSttsComCd === "SL");
|
||||
if (isTeStep && (userBranchSeCd || userPendingBranchSeCd)) {
|
||||
const branchCd = (userBranchSeCd as BranchSeCd) || (userPendingBranchSeCd as BranchSeCd) || (isForkJoin ? "SP" : "MAIN");
|
||||
const validation = validateChecklistFormStateByBranch({
|
||||
rows: data.cklstResultList ?? [],
|
||||
formState: checklistFormState,
|
||||
@@ -560,8 +648,9 @@ function FloatingActionButtons({
|
||||
}
|
||||
|
||||
async function handleRvwCmptnClick() {
|
||||
if (prgrsSttsComCd === "TE") {
|
||||
const branchCd = (userPendingBranchSeCd as BranchSeCd) || (isForkJoin ? "SP" : "MAIN");
|
||||
const isTeStep = prgrsSttsComCd === "TE" || (isForkJoin && prgrsSttsComCd === "SL");
|
||||
if (isTeStep) {
|
||||
const branchCd = (userBranchSeCd as BranchSeCd) || (userPendingBranchSeCd as BranchSeCd) || (isForkJoin ? "SP" : "MAIN");
|
||||
const validation = validateChecklistFormStateByBranch({
|
||||
rows: data.cklstResultList ?? [],
|
||||
formState: checklistFormState,
|
||||
@@ -924,6 +1013,9 @@ function FloatingActionButtons({
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: fnrsCnsltnKeys.detail(fnrsCnsltnDocNo),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.AS_ELAPR_SERVICE.ELAPR_BRANCH],
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -932,11 +1024,13 @@ function FloatingActionButtons({
|
||||
fnrsCnsltnDocNo={docNo}
|
||||
atrzSeComCdList={effectiveAtrzSeComCdList}
|
||||
prgrsSttsComCd={prgrsSttsComCd}
|
||||
branchSeCd={userPendingBranchSeCd}
|
||||
branchSeCd={userBranchSeCd ?? userPendingBranchSeCd}
|
||||
isForkJoin={isForkJoin}
|
||||
userRole={dtlInstCd}
|
||||
supplementDmndBranch={supplementDmndBranch}
|
||||
canSave={
|
||||
(needsElaprPrgrsCheck && !hasPendingApprovalRequest) || viewOnlyPwrkCnsltnDoc
|
||||
(needsElaprPrgrsCheck && !hasPendingApprovalRequest && !isBranchInProgress) ||
|
||||
viewOnlyPwrkCnsltnDoc
|
||||
? false
|
||||
: null
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
pwrkCnsltnDocCrtRsltService,
|
||||
} from "@/entities/pwrk-cnsltn-doc-crt-rslt";
|
||||
import { usePwrkCnsltnDocPjtcoAjmtMngPage } from "@/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng";
|
||||
import { useElaprBranchesByDocNo } from "@/entities/elapr";
|
||||
import {
|
||||
findCompletedPwrkDraft,
|
||||
pwrkCnsltnMngKeys,
|
||||
@@ -83,22 +84,38 @@ function resolveDefaultBranchSeCd({
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
}: {
|
||||
branchSeCd?: string;
|
||||
isForkJoin?: boolean;
|
||||
userRole?: string;
|
||||
prgrsSttsComCd?: string;
|
||||
supplementDmndBranch?: string;
|
||||
supplementBranches?: Set<string>;
|
||||
}): string {
|
||||
if (userRole === "ROLE_USER05" && prgrsSttsComCd === "SL") {
|
||||
return supplementDmndBranch || branchSeCd || "SP";
|
||||
}
|
||||
// 1. 공단 사용자 등 본인 부서(branchSeCd)가 있는 경우 본인 부서 탭을 1순위로 지정
|
||||
if (branchSeCd === "TOTAL_AGG") {
|
||||
return "MAIN";
|
||||
}
|
||||
if (branchSeCd && ["SP", "SF", "MAIN"].includes(branchSeCd)) {
|
||||
return branchSeCd;
|
||||
}
|
||||
|
||||
// 2. 지자체 사용자(ROLE_USER05) 또는 본인 부서가 없는 경우: 보완요청 부서 우선 선택
|
||||
if (isForkJoin && supplementBranches && supplementBranches.size > 0) {
|
||||
if (supplementBranches.size > 1) {
|
||||
return "SP";
|
||||
}
|
||||
if (supplementBranches.has("SP")) return "SP";
|
||||
if (supplementBranches.has("SF")) return "SF";
|
||||
}
|
||||
if (isForkJoin && supplementDmndBranch && ["SP", "SF"].includes(supplementDmndBranch)) {
|
||||
return supplementDmndBranch;
|
||||
}
|
||||
if (userRole === "ROLE_USER05" && (prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB")) {
|
||||
return supplementDmndBranch || "SP";
|
||||
}
|
||||
|
||||
return isForkJoin ? "SP" : "MAIN";
|
||||
}
|
||||
|
||||
@@ -121,6 +138,33 @@ function PwrkCnsltnDocMngDialog({
|
||||
const [uploadedFiles, setUploadedFiles] = useState<UploadedAtchFile[]>([]);
|
||||
const [isPjtcoAjmtTableOpen, setIsPjtcoAjmtTableOpen] = useState(false);
|
||||
const [isEvlDialogOpen, setIsEvlDialogOpen] = useState(false);
|
||||
|
||||
// 전자결재 브랜치 목록 직접 조회 (Single Source of Truth)
|
||||
const { data: elaprBranchList = [] } = useElaprBranchesByDocNo(
|
||||
fnrsCnsltnDocNo,
|
||||
open && Boolean(isForkJoin),
|
||||
);
|
||||
|
||||
// 전자결재 브랜치 테이블(tb_as_elapr_branch)에서 branchSttsCd === 'SUPPLEMENT'인 부서들을 모두 수집 (SP, SF)
|
||||
const supplementBranches = useMemo<Set<string>>(() => {
|
||||
const branches = new Set<string>();
|
||||
if (!isForkJoin) return branches;
|
||||
|
||||
// 1순위: elaprBranchList에서 SUPPLEMENT 상태인 브랜치들을 모두 수집
|
||||
for (const b of elaprBranchList) {
|
||||
if (b.branchSttsCd === "SUPPLEMENT" && b.branchSeCd && ["SP", "SF"].includes(b.branchSeCd)) {
|
||||
branches.add(b.branchSeCd);
|
||||
}
|
||||
}
|
||||
|
||||
// 2순위: props로 전달된 supplementDmndBranch 추가
|
||||
if (supplementDmndBranch && ["SP", "SF"].includes(supplementDmndBranch)) {
|
||||
branches.add(supplementDmndBranch);
|
||||
}
|
||||
|
||||
return branches;
|
||||
}, [elaprBranchList, isForkJoin, supplementDmndBranch]);
|
||||
|
||||
const [currentBranchSeCd, setCurrentBranchSeCd] = useState<string>(() =>
|
||||
resolveDefaultBranchSeCd({
|
||||
branchSeCd,
|
||||
@@ -128,6 +172,7 @@ function PwrkCnsltnDocMngDialog({
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -140,10 +185,11 @@ function PwrkCnsltnDocMngDialog({
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [open, branchSeCd, isForkJoin, userRole, prgrsSttsComCd, supplementDmndBranch]);
|
||||
}, [open, branchSeCd, isForkJoin, userRole, prgrsSttsComCd, supplementBranches, supplementDmndBranch]);
|
||||
|
||||
const { mutate: downloadByAtflId } = useDownloadAttachmentByAtflId();
|
||||
|
||||
@@ -355,21 +401,43 @@ function PwrkCnsltnDocMngDialog({
|
||||
const baseCanSave = !viewOnly && (canSaveProp ?? canSaveByAtrz);
|
||||
|
||||
const canSaveCurrentBranch = useMemo(() => {
|
||||
// 1. 지자체 사용자 (ROLE_USER05): 보완요청(SL) 및 지자체회신/조치결과작성(RB) 상태에서 보완 부서만 저장 허용
|
||||
if (userRole === "ROLE_USER05") {
|
||||
if (prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB") {
|
||||
if (isForkJoin) {
|
||||
// 보완요청 부서(supplementBranches)가 존재하는 경우 해당 부서만 저장 허용
|
||||
if (supplementBranches.size > 0) {
|
||||
return supplementBranches.has(currentBranchSeCd);
|
||||
}
|
||||
return currentBranchSeCd === "SP" || currentBranchSeCd === "SF";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 공단 사용자 등 일반 사용자 (검토자, 결재자 등)
|
||||
if (!baseCanSave) return false;
|
||||
if (userRole === "ROLE_USER05") return false;
|
||||
|
||||
if (isForkJoin) {
|
||||
// 종합병합자: MAIN 탭만 저장 가능
|
||||
if (branchSeCd === "TOTAL_AGG") {
|
||||
return currentBranchSeCd === "MAIN";
|
||||
}
|
||||
// 관로 검토자: 관로(SP) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (branchSeCd === "SP") {
|
||||
return currentBranchSeCd === "SP";
|
||||
}
|
||||
// 시설 검토자: 시설(SF) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (branchSeCd === "SF") {
|
||||
return currentBranchSeCd === "SF";
|
||||
}
|
||||
// 특정 부서가 지정되지 않은 일반 관리자/사용자
|
||||
return baseCanSave;
|
||||
}
|
||||
|
||||
return baseCanSave;
|
||||
}, [baseCanSave, userRole, isForkJoin, branchSeCd, currentBranchSeCd]);
|
||||
}, [baseCanSave, userRole, prgrsSttsComCd, isForkJoin, branchSeCd, currentBranchSeCd, supplementBranches]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -412,19 +480,31 @@ function PwrkCnsltnDocMngDialog({
|
||||
</Button>
|
||||
</div>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{branchSeCd === "TOTAL_AGG"
|
||||
? "종합병합자: SP/SF를 참조하여 MAIN 종합본을 수동 병합 저장합니다."
|
||||
: branchSeCd === "SP"
|
||||
? currentBranchSeCd === "SP"
|
||||
? "관로 검토자: 관로 초안(SP) 편집 모드"
|
||||
: "관로 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: branchSeCd === "SF"
|
||||
? currentBranchSeCd === "SF"
|
||||
? "시설 검토자: 시설 초안(SF) 편집 모드"
|
||||
: "시설 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: userRole === "ROLE_USER05"
|
||||
? "지자체 사용자: 보완요청 부서 문서 열람 전용"
|
||||
: "문서 열람 모드"}
|
||||
{userRole === "ROLE_USER05"
|
||||
? isForkJoin && supplementBranches.size > 0
|
||||
? supplementBranches.has(currentBranchSeCd)
|
||||
? supplementBranches.size > 1
|
||||
? `[보완 수정 모드] 관로·시설 부서 모두 보완요청 상태이며, ${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안을 수정 및 저장할 수 있습니다.`
|
||||
: `[보완 수정 모드] ${supplementBranches.has("SP") ? "관로" : "시설"} 초안만 수정 및 저장 가능합니다.`
|
||||
: `[읽기 전용 모드] ${currentBranchSeCd === "MAIN" ? "종합본" : currentBranchSeCd === "SP" ? "관로 초안" : "시설 초안"}은 보완 비대상으로 저장 불가합니다.`
|
||||
: prgrsSttsComCd === "SL" || prgrsSttsComCd === "RB"
|
||||
? `지자체 담당자: ${currentBranchSeCd === "MAIN" ? "종합본 열람 전용" : `${currentBranchSeCd === "SP" ? "관로" : "시설"} 초안 보완 수정 모드 (저장 가능)`}`
|
||||
: "지자체 사용자: 문서 열람 모드"
|
||||
: branchSeCd === "TOTAL_AGG"
|
||||
? currentBranchSeCd === "MAIN"
|
||||
? "종합병합자: SP/SF를 참조하여 MAIN 종합본을 수동 병합 저장합니다."
|
||||
: "종합병합자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: branchSeCd === "SP"
|
||||
? currentBranchSeCd === "SP"
|
||||
? "관로 검토자: 관로 초안(SP) 편집 모드 (저장 가능)"
|
||||
: "관로 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: branchSeCd === "SF"
|
||||
? currentBranchSeCd === "SF"
|
||||
? "시설 검토자: 시설 초안(SF) 편집 모드 (저장 가능)"
|
||||
: "시설 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: isForkJoin && supplementBranches.size > 0
|
||||
? `[보완 진행 중] ${Array.from(supplementBranches).join(", ")} 부서 보완요청 진행 중`
|
||||
: "문서 열람 모드"}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -352,8 +352,8 @@ function FnrsFormPage({ mode, initialData, createDefaults }: FnrsFormPageProps)
|
||||
fnrsCnsltnDocNo={fnrsCnsltnDocNo}
|
||||
isForkJoin={isForkJoinTask(initialData?.detDto?.taskSeComCd)}
|
||||
userRole={userInfo?.dtlInstCd}
|
||||
prgrsSttsComCd={initialData?.detDto?.prgrsSttsComCd}
|
||||
canSave={!isSplmntPrgrsStts}
|
||||
prgrsSttsComCd={initialData?.detDto?.prgrsSttsComCd ?? undefined}
|
||||
canSave={isSplmntPrgrsStts && userInfo?.dtlInstCd === "ROLE_USER05" ? null : !isSplmntPrgrsStts}
|
||||
onClose={() => setIsPwrkCnsltnDocMngOpen(false)}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@@ -42,6 +42,7 @@ export const ENDPOINT = {
|
||||
ELAPR_APLN: "/as-elapr-service/api/v1/elapr-apln",
|
||||
ELAPR_DMND: "/as-elapr-service/api/v1/elapr-dmnd",
|
||||
ELAPR_PRGRS_STTS: "/as-elapr-service/api/v1/elapr-prgrs-stts",
|
||||
ELAPR_BRANCH: "/as-elapr-service/api/v1/elapr-branch",
|
||||
},
|
||||
CMS_SERVICE: {
|
||||
CODE: "/cms-service/api/v1/code/cache",
|
||||
|
||||
Reference in New Issue
Block a user