[as elapr] 공공하수도 재원협의 복합사업(SF+SP) Fork-Join 전자결재 프론트엔드 병합자(ATRZ04) 결재 버튼 연동 및 순차결재 분리 개선
This commit is contained in:
@@ -17,7 +17,7 @@ export type AtrzSeComCd =
|
||||
| "ATRZ02" // 검토 (실무 기술검토)
|
||||
| "ATRZ03" // 승인 (부서 승인 / 병합에 회신)
|
||||
| "ATRZ04" // 병합 (정책총괄 AI 병합의견 종합 심의 - 10-12 신설)
|
||||
| "ATRZ99"; // 최종승인(회신) (환경청에 최종 회신)
|
||||
| "ATRZ99"; // 최종승인(회신) (환경청에 회신)
|
||||
|
||||
/** 브랜치 구분코드 */
|
||||
export type BranchSeCd = "MAIN" | "PIPE" | "FACILITY" | "TOTAL_AGG";
|
||||
|
||||
@@ -123,7 +123,7 @@ function ElaprApprovalDialog({
|
||||
|
||||
const approveButtonLabel = useMemo(() => {
|
||||
if (!isForkJoin) return "결재";
|
||||
if (branchSeCd === "TOTAL_AGG" && isLastInBranch) return "결재 (환경청에 최종회신)";
|
||||
if (branchSeCd === "TOTAL_AGG" && isLastInBranch) return "결재 (환경청에 회신)";
|
||||
if (branchSeCd === "TOTAL_AGG") return "결재 (병합)";
|
||||
if ((branchSeCd === "PIPE" || branchSeCd === "FACILITY") && isLastInBranch)
|
||||
return "결재 (병합에 회신)";
|
||||
|
||||
@@ -200,7 +200,7 @@ export function ElaprDocPrgrsForkJoinStep({ steps }: ElaprDocPrgrsForkJoinStepPr
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stage 3: 정책총괄부 종합취합 및 환경청 최종회신 트랙 */}
|
||||
{/* Stage 3: 정책총괄부 종합취합 및 환경청 회신 트랙 */}
|
||||
<div className="flex flex-1 flex-col gap-4 rounded-xl border border-purple-100 bg-purple-50/40 p-4">
|
||||
<div className="flex items-center gap-2 border-b border-purple-200/60 pb-2">
|
||||
<CheckCircle2 className="size-5 text-purple-600" />
|
||||
|
||||
@@ -58,7 +58,7 @@ const TRACK_CONFIGS: TrackConfig[] = [
|
||||
key: "TOTAL_AGG",
|
||||
label: "정책부 종합병합",
|
||||
defaultDeptNm: "정책총괄부",
|
||||
guideText: "ℹ️ 두 부서(관로+시설) Join 완료 후 정책취합 및 환경청 최종회신 단계로 진행됩니다.",
|
||||
guideText: "ℹ️ 두 부서(관로+시설) Join 완료 후 정책취합 및 환경청 회신 단계로 진행됩니다.",
|
||||
minCount: 2,
|
||||
maxCount: 5,
|
||||
},
|
||||
@@ -107,7 +107,7 @@ export function ElaprForkJoinPickerGrid({
|
||||
],
|
||||
TOTAL_AGG: [
|
||||
createDefaultRow("TOTAL_AGG", "정책총괄부", 1, "ATRZ04"), // 병합 (10-12 신설)
|
||||
createDefaultRow("TOTAL_AGG", "정책총괄부", 2, "ATRZ99"), // 최종승인/전결 (환경청 최종회신)
|
||||
createDefaultRow("TOTAL_AGG", "정책총괄부", 2, "ATRZ99"), // 최종승인/전결 (환경청 회신)
|
||||
],
|
||||
}));
|
||||
|
||||
|
||||
@@ -188,16 +188,149 @@ const ROLE_USER01_ATRZ_STATUS_ACTIONS: Record<
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Fork-Join (병렬 결재 6인 체제: 관로2 + 시설2 + 정책병합2) 전용 상태별 버튼 액션 매핑
|
||||
* - Stage 2: 관로/시설 실무검토자(ATRZ02), 부서승인자(ATRZ03)
|
||||
* - Stage 3: 정책총괄 종합병합자(ATRZ04), 최종회신자(ATRZ99)
|
||||
* - 일반 순차 결재 라인과 분리하여 독립적으로 관리
|
||||
*/
|
||||
const ROLE_USER01_FORK_JOIN_ATRZ_STATUS_ACTIONS: Record<
|
||||
string,
|
||||
Record<string, FnrsCnsltnViewButtonAction[]>
|
||||
> = {
|
||||
ER: {
|
||||
ATRZ01: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileSplmnt,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.fileVrfc,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr,
|
||||
],
|
||||
},
|
||||
SL: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
TE: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocCrt,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwStrg,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwCmptn,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dmndSplmnt,
|
||||
],
|
||||
ATRZ03: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzRply,
|
||||
],
|
||||
ATRZ04: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv,
|
||||
],
|
||||
ATRZ99: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzRply,
|
||||
],
|
||||
},
|
||||
TP: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
RB: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
RA: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
AV: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
EV: {
|
||||
ATRZ01: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dsgntRvwr,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.costVrfc,
|
||||
],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
RK: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwCmptn,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.dmndSplmnt,
|
||||
],
|
||||
ATRZ03: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzRply,
|
||||
],
|
||||
ATRZ04: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzAprv,
|
||||
],
|
||||
ATRZ99: [
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng,
|
||||
FNRS_CNSLTN_VIEW_BUTTON_ACTION.atrzRply,
|
||||
],
|
||||
},
|
||||
RR: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
EP: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
TA: {
|
||||
ATRZ01: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ02: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ03: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ04: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
ATRZ99: [FNRS_CNSLTN_VIEW_BUTTON_ACTION.pwrkCnsltnDocMng],
|
||||
},
|
||||
};
|
||||
|
||||
function resolveButtonConfigs(actions: FnrsCnsltnViewButtonAction[]): FnrsCnsltnViewButtonAction[] {
|
||||
return actions.map((action) => FNRS_CNSLTN_VIEW_BUTTON_ACTION[action]);
|
||||
}
|
||||
|
||||
interface GetButtonConfigsOptions {
|
||||
export interface GetButtonConfigsOptions {
|
||||
hasPendingApprovalRequest?: boolean;
|
||||
hasCompletedDraft?: boolean;
|
||||
canRetryFileVrfc?: boolean;
|
||||
canRetryDraftGen?: boolean;
|
||||
canRetryCostVrfc?: boolean;
|
||||
isForkJoin?: boolean;
|
||||
}
|
||||
|
||||
const PENDING_APPROVAL_ACTIONS = new Set<FnrsCnsltnViewButtonAction>([
|
||||
@@ -214,7 +347,9 @@ function resolveRoleUser01AtrzButtonActions(
|
||||
atrzSeComCdList: string[],
|
||||
options?: GetButtonConfigsOptions,
|
||||
): FnrsCnsltnViewButtonAction[] {
|
||||
const atrzStatusMap = ROLE_USER01_ATRZ_STATUS_ACTIONS[prgrsSttsComCd];
|
||||
const atrzStatusMap = options?.isForkJoin
|
||||
? ROLE_USER01_FORK_JOIN_ATRZ_STATUS_ACTIONS[prgrsSttsComCd]
|
||||
: ROLE_USER01_ATRZ_STATUS_ACTIONS[prgrsSttsComCd];
|
||||
if (!atrzStatusMap || atrzSeComCdList.length === 0) return [];
|
||||
|
||||
const seen = new Set<FnrsCnsltnViewButtonAction>();
|
||||
|
||||
@@ -194,6 +194,15 @@ function FloatingActionButtons({
|
||||
const normalizedTaskSeComCd = normalizeTaskSeComCdForElapr(data.detDto?.taskSeComCd);
|
||||
const isForkJoin = isForkJoinTask(data.detDto?.taskSeComCd);
|
||||
|
||||
const effectiveAtrzSeComCdList = useMemo(() => {
|
||||
if (isForkJoin && userPendingAtrzSeComCd) {
|
||||
if (!atrzSeComCdList.includes(userPendingAtrzSeComCd)) {
|
||||
return [...atrzSeComCdList, userPendingAtrzSeComCd];
|
||||
}
|
||||
}
|
||||
return atrzSeComCdList;
|
||||
}, [atrzSeComCdList, isForkJoin, userPendingAtrzSeComCd]);
|
||||
|
||||
const viewOnlyPwrkCnsltnDoc =
|
||||
prgrsSttsComCd === "SL" ||
|
||||
(prgrsSttsComCd === "RB" && dtlInstCd !== "ROLE_USER05") ||
|
||||
@@ -204,23 +213,25 @@ function FloatingActionButtons({
|
||||
if (needsElaprPrgrsCheck && isElaprDocPrgrsLoading) return [];
|
||||
if (needsPwrkDraftCheck && isPwrkCnsltnLoading) return [];
|
||||
if (needsAiAutoLatest && isAiAutoLatestLoading) return [];
|
||||
return getButtonConfigs(dtlInstCd, prgrsSttsComCd, atrzSeComCdList, {
|
||||
return getButtonConfigs(dtlInstCd, prgrsSttsComCd, effectiveAtrzSeComCdList, {
|
||||
hasPendingApprovalRequest: needsElaprPrgrsCheck ? hasPendingApprovalRequest : undefined,
|
||||
hasCompletedDraft: needsPwrkDraftCheck ? hasCompletedDraft : undefined,
|
||||
canRetryFileVrfc: needsAiAutoLatest ? canRetryFileVrfc : undefined,
|
||||
canRetryDraftGen: needsAiAutoLatest ? canRetryDraftGen : undefined,
|
||||
canRetryCostVrfc: needsAiAutoLatest ? canRetryCostVrfc : undefined,
|
||||
isForkJoin,
|
||||
});
|
||||
}, [
|
||||
atrzSeComCdList,
|
||||
canRetryCostVrfc,
|
||||
canRetryDraftGen,
|
||||
canRetryFileVrfc,
|
||||
dtlInstCd,
|
||||
effectiveAtrzSeComCdList,
|
||||
hasCompletedDraft,
|
||||
hasPendingApprovalRequest,
|
||||
isAiAutoLatestLoading,
|
||||
isElaprDocPrgrsLoading,
|
||||
isForkJoin,
|
||||
isPwrkCnsltnLoading,
|
||||
isRvwLoginUserLoading,
|
||||
needsAiAutoLatest,
|
||||
@@ -234,7 +245,7 @@ function FloatingActionButtons({
|
||||
isRegister && actionButtons.some((button) => button === FNRS_CNSLTN_VIEW_BUTTON_ACTION.strg);
|
||||
const canDmndSplmntInPwrkCnsltnDoc =
|
||||
prgrsSttsComCd === "RK" &&
|
||||
atrzSeComCdList.includes("ATRZ02") &&
|
||||
effectiveAtrzSeComCdList.includes("ATRZ02") &&
|
||||
actionButtons.some((button) => button === FNRS_CNSLTN_VIEW_BUTTON_ACTION.dmndSplmnt);
|
||||
|
||||
function handleGoToList() {
|
||||
@@ -817,7 +828,7 @@ function FloatingActionButtons({
|
||||
>
|
||||
{isForkJoin
|
||||
? userPendingBranchSeCd === "TOTAL_AGG"
|
||||
? "결재 (환경청에 최종회신)"
|
||||
? "결재 (환경청에 회신)"
|
||||
: "결재 (병합에 회신)"
|
||||
: "결재(회신)"}
|
||||
</Button>
|
||||
@@ -877,7 +888,7 @@ function FloatingActionButtons({
|
||||
<PwrkCnsltnDocMngDialog
|
||||
open={activeDialog === "pwrkCnsltnDocMng"}
|
||||
fnrsCnsltnDocNo={docNo}
|
||||
atrzSeComCdList={atrzSeComCdList}
|
||||
atrzSeComCdList={effectiveAtrzSeComCdList}
|
||||
prgrsSttsComCd={prgrsSttsComCd}
|
||||
canSave={
|
||||
(needsElaprPrgrsCheck && !hasPendingApprovalRequest) || viewOnlyPwrkCnsltnDoc
|
||||
|
||||
Reference in New Issue
Block a user