[as]병렬결재에서 병합자 - 웹기안기 MAIN만 수정가능하게 하고 최종승인자의 경우에는 MAIN 탭만 보이도록 수정함
This commit is contained in:
@@ -228,7 +228,6 @@ const ROLE_USER01_FORK_JOIN_ATRZ_STATUS_ACTIONS: Record<
|
||||
],
|
||||
ATRZ04: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv,
|
||||
],
|
||||
ATRZ99: [
|
||||
|
||||
@@ -911,11 +911,15 @@ function FloatingActionButtons({
|
||||
조치 완료
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq) && (
|
||||
<Button color="sky" onClick={() => setActiveDialog("rvwRsltInq")} disabled={isBusy}>
|
||||
검토 결과 조회
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq) &&
|
||||
!(
|
||||
isForkJoin &&
|
||||
(userPendingBranchSeCd === "TOTAL_AGG" || userPendingAtrzSeComCd === "ATRZ04")
|
||||
) && (
|
||||
<Button color="sky" onClick={() => setActiveDialog("rvwRsltInq")} disabled={isBusy}>
|
||||
검토 결과 조회
|
||||
</Button>
|
||||
)}
|
||||
{shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwStrg) && (
|
||||
<Button onClick={handleRvwStrgClick} disabled={isBusy}>
|
||||
저장
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useContext, useEffect, useMemo, useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { PanelRightClose, PanelRightOpen } from "lucide-react";
|
||||
import { useStore } from "zustand";
|
||||
|
||||
import { getDefaultFileKey, useAlertStore, useTus } from "@/shared/lib";
|
||||
import { StoreContext } from "@/shared/providers";
|
||||
import { AttachmentFileField } from "@/shared/ui";
|
||||
import {
|
||||
attachService,
|
||||
@@ -18,7 +20,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 { useElaprBranchesByDocNo, useElaprDocPrgrsByDocNo } from "@/entities/elapr";
|
||||
import {
|
||||
findCompletedPwrkDraft,
|
||||
pwrkCnsltnMngKeys,
|
||||
@@ -85,6 +87,7 @@ function resolveDefaultBranchSeCd({
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
isFinalApproverAfterMerger,
|
||||
}: {
|
||||
branchSeCd?: string;
|
||||
isForkJoin?: boolean;
|
||||
@@ -92,7 +95,13 @@ function resolveDefaultBranchSeCd({
|
||||
prgrsSttsComCd?: string;
|
||||
supplementDmndBranch?: string;
|
||||
supplementBranches?: Set<string>;
|
||||
isFinalApproverAfterMerger?: boolean;
|
||||
}): string {
|
||||
// 0. 병합자 후의 최종 승인자는 무조건 MAIN 탭으로 고정
|
||||
if (isForkJoin && isFinalApproverAfterMerger) {
|
||||
return "MAIN";
|
||||
}
|
||||
|
||||
// 1. 공단 사용자 등 본인 부서(branchSeCd)가 있는 경우 본인 부서 탭을 1순위로 지정
|
||||
if (branchSeCd === "TOTAL_AGG") {
|
||||
return "MAIN";
|
||||
@@ -134,6 +143,8 @@ function PwrkCnsltnDocMngDialog({
|
||||
}: PwrkCnsltnDocMngDialogProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const storeContext = useContext(StoreContext);
|
||||
const userInfo = storeContext ? useStore(storeContext.userStore, (state) => state.userInfo) : null;
|
||||
const [atchFileGroupId, setAtchFileGroupId] = useState("");
|
||||
const [uploadedFiles, setUploadedFiles] = useState<UploadedAtchFile[]>([]);
|
||||
const [isPjtcoAjmtTableOpen, setIsPjtcoAjmtTableOpen] = useState(false);
|
||||
@@ -145,6 +156,97 @@ function PwrkCnsltnDocMngDialog({
|
||||
open && Boolean(isForkJoin),
|
||||
);
|
||||
|
||||
// 전자결재 결재선 목록 직접 조회 (병합자 / 최종승인자 식별용)
|
||||
const { data: elaprDocPrgrsList = [] } = useElaprDocPrgrsByDocNo(
|
||||
open && Boolean(isForkJoin) ? fnrsCnsltnDocNo : null,
|
||||
);
|
||||
|
||||
const elaprPrgrsForCycl = useMemo(() => {
|
||||
if (!elaprDocPrgrsList.length) return [];
|
||||
if (prgrsSttsComCd === "RK") {
|
||||
const cycl2 = elaprDocPrgrsList.filter((row) => Number(row.elaprCycl) === 2);
|
||||
return cycl2.length > 0 ? cycl2 : elaprDocPrgrsList;
|
||||
}
|
||||
return elaprDocPrgrsList;
|
||||
}, [elaprDocPrgrsList, prgrsSttsComCd]);
|
||||
|
||||
const currentUserPrgrs = useMemo(() => {
|
||||
if (!userInfo?.userUnqId || !elaprPrgrsForCycl.length) return undefined;
|
||||
return (
|
||||
elaprPrgrsForCycl.find(
|
||||
(row) => row.aprvrUuid === userInfo.userUnqId && row.atrzPrgrsSttsComCd === "ATRZ_PRGRS_002",
|
||||
) ?? elaprPrgrsForCycl.find((row) => row.aprvrUuid === userInfo.userUnqId)
|
||||
);
|
||||
}, [userInfo?.userUnqId, elaprPrgrsForCycl]);
|
||||
|
||||
const effectiveBranchSeCd = branchSeCd ?? currentUserPrgrs?.branchSeCd;
|
||||
const effectiveAtrzSeList = useMemo(() => {
|
||||
if (atrzSeComCdList && atrzSeComCdList.length > 0) return atrzSeComCdList;
|
||||
if (currentUserPrgrs?.atrzSeComCd) return [currentUserPrgrs.atrzSeComCd];
|
||||
return [];
|
||||
}, [atrzSeComCdList, currentUserPrgrs?.atrzSeComCd]);
|
||||
|
||||
const isTeOrRk = prgrsSttsComCd === "TE" || prgrsSttsComCd === "RK";
|
||||
|
||||
// 1. 병합자 여부 (TE/RK 상태에서 TOTAL_AGG 브랜치이거나 ATRZ04 권한을 가진 병합자)
|
||||
const isMerger = useMemo(() => {
|
||||
if (!isForkJoin || !isTeOrRk) return false;
|
||||
if (effectiveAtrzSeList.includes("ATRZ04")) return true;
|
||||
if (effectiveBranchSeCd === "TOTAL_AGG" && !effectiveAtrzSeList.some((cd) => APPROVER_ATRZ_SE_COM_CDS.has(cd))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, [isForkJoin, isTeOrRk, effectiveAtrzSeList, effectiveBranchSeCd]);
|
||||
|
||||
// 2. 병합자 후의 최종 승인자 여부 (TE/RK 상태에서 TOTAL_AGG 브랜치이면서 ATRZ04가 아니고 ATRZ03 또는 ATRZ99 등 후속 결재/승인자)
|
||||
const isFinalApproverAfterMerger = useMemo(() => {
|
||||
if (!isForkJoin || !isTeOrRk) return false;
|
||||
if (effectiveBranchSeCd === "TOTAL_AGG") {
|
||||
if (effectiveAtrzSeList.includes("ATRZ04")) return false;
|
||||
if (effectiveAtrzSeList.some((cd) => APPROVER_ATRZ_SE_COM_CDS.has(cd))) return true;
|
||||
if (currentUserPrgrs?.atrzSeq && Number(currentUserPrgrs.atrzSeq) > 1) return true;
|
||||
if (effectiveAtrzSeList.length > 0 && !effectiveAtrzSeList.includes("ATRZ04")) return true;
|
||||
}
|
||||
return false;
|
||||
}, [isForkJoin, isTeOrRk, effectiveBranchSeCd, effectiveAtrzSeList, currentUserPrgrs?.atrzSeq]);
|
||||
|
||||
// 3. 병합 완료(결재 후) 여부
|
||||
// 병합자가 이미 결재(승인)를 진행한 경우 (ATRZ_PRGRS_003 등) MAIN 탭 저장 불가
|
||||
const isMergerApproved = useMemo(() => {
|
||||
if (!isForkJoin || !isMerger) return false;
|
||||
|
||||
// 1순위: 현재 로그인 사용자의 결재선 행 확인
|
||||
if (userInfo?.userUnqId) {
|
||||
const userRows = elaprPrgrsForCycl.filter((row) => row.aprvrUuid === userInfo.userUnqId);
|
||||
const mergerRow = userRows.find(
|
||||
(row) =>
|
||||
row.atrzSeComCd === "ATRZ04" ||
|
||||
(row.branchSeCd === "TOTAL_AGG" && Number(row.atrzSeq) === 1),
|
||||
);
|
||||
if (mergerRow) {
|
||||
return (
|
||||
mergerRow.atrzPrgrsSttsComCd === "ATRZ_PRGRS_003" ||
|
||||
mergerRow.atrzPrgrsSttsComCd === "ATRZ_PRGRS_999"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 2순위: 결재선 상에서 TOTAL_AGG 브랜치 1순번(병합자)의 결재 완료 여부 확인
|
||||
const aggMergerRow = elaprPrgrsForCycl.find(
|
||||
(row) =>
|
||||
row.branchSeCd === "TOTAL_AGG" &&
|
||||
(row.atrzSeComCd === "ATRZ04" || Number(row.atrzSeq) === 1),
|
||||
);
|
||||
if (aggMergerRow) {
|
||||
return (
|
||||
aggMergerRow.atrzPrgrsSttsComCd === "ATRZ_PRGRS_003" ||
|
||||
aggMergerRow.atrzPrgrsSttsComCd === "ATRZ_PRGRS_999"
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}, [isForkJoin, isMerger, userInfo?.userUnqId, elaprPrgrsForCycl]);
|
||||
|
||||
// 전자결재 브랜치 테이블(tb_as_elapr_branch)에서 branchSttsCd === 'SUPPLEMENT'인 부서들을 모두 수집 (SP, SF)
|
||||
const supplementBranches = useMemo<Set<string>>(() => {
|
||||
const branches = new Set<string>();
|
||||
@@ -167,12 +269,13 @@ function PwrkCnsltnDocMngDialog({
|
||||
|
||||
const [currentBranchSeCd, setCurrentBranchSeCd] = useState<string>(() =>
|
||||
resolveDefaultBranchSeCd({
|
||||
branchSeCd,
|
||||
branchSeCd: effectiveBranchSeCd,
|
||||
isForkJoin,
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
isFinalApproverAfterMerger,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -180,16 +283,26 @@ function PwrkCnsltnDocMngDialog({
|
||||
if (open) {
|
||||
setCurrentBranchSeCd(
|
||||
resolveDefaultBranchSeCd({
|
||||
branchSeCd,
|
||||
branchSeCd: effectiveBranchSeCd,
|
||||
isForkJoin,
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementDmndBranch,
|
||||
supplementBranches,
|
||||
isFinalApproverAfterMerger,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [open, branchSeCd, isForkJoin, userRole, prgrsSttsComCd, supplementBranches, supplementDmndBranch]);
|
||||
}, [
|
||||
open,
|
||||
effectiveBranchSeCd,
|
||||
isForkJoin,
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
supplementBranches,
|
||||
supplementDmndBranch,
|
||||
isFinalApproverAfterMerger,
|
||||
]);
|
||||
|
||||
const { mutate: downloadByAtflId } = useDownloadAttachmentByAtflId();
|
||||
|
||||
@@ -420,24 +533,44 @@ function PwrkCnsltnDocMngDialog({
|
||||
if (!baseCanSave) return false;
|
||||
|
||||
if (isForkJoin) {
|
||||
// 종합병합자: MAIN 탭만 저장 가능
|
||||
if (branchSeCd === "TOTAL_AGG") {
|
||||
// 2-1. 병합자 후의 최종 승인자 또는 병합 완료(결재 후)된 병합자: 저장 불가 (읽기 전용)
|
||||
if (isFinalApproverAfterMerger || isMergerApproved) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2-2. 종합병합자 (ATRZ04 또는 TOTAL_AGG):
|
||||
// 웹기안기의 한글문서 저장 버튼은 MAIN 탭의 것만 저장 버튼이 보이고 SP, SF 탭의 저장 버튼은 보이지 않음!
|
||||
if (isMerger || effectiveBranchSeCd === "TOTAL_AGG") {
|
||||
return currentBranchSeCd === "MAIN";
|
||||
}
|
||||
// 관로 검토자: 관로(SP) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (branchSeCd === "SP") {
|
||||
|
||||
// 2-3. 관로 검토자: 관로(SP) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (effectiveBranchSeCd === "SP") {
|
||||
return currentBranchSeCd === "SP";
|
||||
}
|
||||
// 시설 검토자: 시설(SF) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (branchSeCd === "SF") {
|
||||
|
||||
// 2-4. 시설 검토자: 시설(SF) 탭만 저장 가능 (타 부서 보완요청 여부와 무관하게 본인 부서 작성/수정 가능)
|
||||
if (effectiveBranchSeCd === "SF") {
|
||||
return currentBranchSeCd === "SF";
|
||||
}
|
||||
|
||||
// 특정 부서가 지정되지 않은 일반 관리자/사용자
|
||||
return baseCanSave;
|
||||
}
|
||||
|
||||
return baseCanSave;
|
||||
}, [baseCanSave, userRole, prgrsSttsComCd, isForkJoin, branchSeCd, currentBranchSeCd, supplementBranches]);
|
||||
}, [
|
||||
baseCanSave,
|
||||
userRole,
|
||||
prgrsSttsComCd,
|
||||
isForkJoin,
|
||||
isFinalApproverAfterMerger,
|
||||
isMerger,
|
||||
isMergerApproved,
|
||||
effectiveBranchSeCd,
|
||||
currentBranchSeCd,
|
||||
supplementBranches,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -454,22 +587,26 @@ function PwrkCnsltnDocMngDialog({
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 rounded-md border border-border bg-muted/40 px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-semibold text-muted-foreground">부서별 문서 탭:</span>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color={currentBranchSeCd === "SP" ? "primary" : "white"}
|
||||
onClick={() => setCurrentBranchSeCd("SP")}
|
||||
>
|
||||
관로 초안 (SP)
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color={currentBranchSeCd === "SF" ? "primary" : "white"}
|
||||
onClick={() => setCurrentBranchSeCd("SF")}
|
||||
>
|
||||
시설 초안 (SF)
|
||||
</Button>
|
||||
{!isFinalApproverAfterMerger && (
|
||||
<>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color={currentBranchSeCd === "SP" ? "primary" : "white"}
|
||||
onClick={() => setCurrentBranchSeCd("SP")}
|
||||
>
|
||||
관로 초안 (SP)
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color={currentBranchSeCd === "SF" ? "primary" : "white"}
|
||||
onClick={() => setCurrentBranchSeCd("SF")}
|
||||
>
|
||||
시설 초안 (SF)
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
@@ -490,21 +627,25 @@ function PwrkCnsltnDocMngDialog({
|
||||
: 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(", ")} 부서 보완요청 진행 중`
|
||||
: "문서 열람 모드"}
|
||||
: isFinalApproverAfterMerger
|
||||
? "최종 승인자: MAIN 종합 실무협의서 열람 모드"
|
||||
: isMerger || effectiveBranchSeCd === "TOTAL_AGG"
|
||||
? isMergerApproved
|
||||
? "종합병합자: 병합 결재 완료 (읽기 전용 모드)"
|
||||
: currentBranchSeCd === "MAIN"
|
||||
? "종합병합자: SP/SF를 참조하여 MAIN 종합본을 수동 병합 저장합니다."
|
||||
: "종합병합자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: effectiveBranchSeCd === "SP"
|
||||
? currentBranchSeCd === "SP"
|
||||
? "관로 검토자: 관로 초안(SP) 편집 모드 (저장 가능)"
|
||||
: "관로 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: effectiveBranchSeCd === "SF"
|
||||
? currentBranchSeCd === "SF"
|
||||
? "시설 검토자: 시설 초안(SF) 편집 모드 (저장 가능)"
|
||||
: "시설 검토자: 타 문서 열람 모드 (읽기 전용)"
|
||||
: isForkJoin && supplementBranches.size > 0
|
||||
? `[보완 진행 중] ${Array.from(supplementBranches).join(", ")} 부서 보완요청 진행 중`
|
||||
: "문서 열람 모드"}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user