diff options
| author | joonhoekim <26rote@gmail.com> | 2025-10-21 12:17:30 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-10-21 12:17:30 +0900 |
| commit | df8c7db59b463aea2b464552e207e4ae63ea4077 (patch) | |
| tree | c15cfb7f44a433996c8a46f4511d43550bd4c50d | |
| parent | 52b0f03803a94689ccc08578b5538405c88be1f2 (diff) | |
(김준회) 결재 조회 구조 변경, 권한없을 떄 권한 변경시 실패사유 안내하도록 error.message 토스트에 추가
| -rw-r--r-- | components/knox/approval/ApprovalList.tsx | 8 | ||||
| -rw-r--r-- | components/permissions/menu-permission-generator.tsx | 2 | ||||
| -rw-r--r-- | lib/knox-api/approval/approval.ts | 53 |
3 files changed, 53 insertions, 10 deletions
diff --git a/components/knox/approval/ApprovalList.tsx b/components/knox/approval/ApprovalList.tsx index ed26a375..ec47bf04 100644 --- a/components/knox/approval/ApprovalList.tsx +++ b/components/knox/approval/ApprovalList.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; @@ -62,7 +62,7 @@ export default function ApprovalList({ const [error, setError] = useState<string | null>(null); const [isSyncing, setIsSyncing] = useState(false); - const fetchData = async () => { + const fetchData = useCallback(async () => { setIsLoading(true); setError(null); @@ -106,7 +106,7 @@ export default function ApprovalList({ } finally { setIsLoading(false); } - }; + }, [type, userParams]); const getStatusBadgeVariant = (status: string) => { switch (status) { @@ -189,7 +189,7 @@ export default function ApprovalList({ // 컴포넌트 마운트 시 데이터 로드 useEffect(() => { fetchData(); - }, [type]); + }, [fetchData]); return ( <Card className="w-full max-w-5xl"> diff --git a/components/permissions/menu-permission-generator.tsx b/components/permissions/menu-permission-generator.tsx index 4c8d60d0..0aa05d5a 100644 --- a/components/permissions/menu-permission-generator.tsx +++ b/components/permissions/menu-permission-generator.tsx @@ -168,7 +168,7 @@ export function MenuBasedPermissionGenerator() { toast.success(`${result.created}개의 권한이 생성되었습니다.`); loadAnalysis(); } catch (error) { - toast.error("권한 생성에 실패했습니다."); + toast.error(`권한 생성에 실패했습니다. ${error instanceof Error ? error.message : ''}`); } finally { setGenerating(false); } diff --git a/lib/knox-api/approval/approval.ts b/lib/knox-api/approval/approval.ts index fba7ef04..c7803653 100644 --- a/lib/knox-api/approval/approval.ts +++ b/lib/knox-api/approval/approval.ts @@ -1004,13 +1004,13 @@ export async function getApprovalLogsAction(): Promise<{ }>; }> { "use server"; - + try { const db = (await import('@/db/db')).default; const { approvalLogs } = await import('@/db/schema/knox/approvals'); const { eq, desc } = await import('drizzle-orm'); - - // 데이터베이스에서 결재 로그 조회 (삭제되지 않은 것만) + + // 1. 데이터베이스에서 결재 로그 조회 (삭제되지 않은 것만) const logs = await db .select({ apInfId: approvalLogs.apInfId, @@ -1036,7 +1036,50 @@ export async function getApprovalLogsAction(): Promise<{ .where(eq(approvalLogs.isDeleted, false)) .orderBy(desc(approvalLogs.createdAt)); - // ApprovalList 컴포넌트에서 기대하는 형식으로 데이터 변환 + // 2. 상태가 변동될 수 있는 항목들 필터링 (암호화중(-2), 보류(0), 진행중(1)) + const pendingApprovals = logs.filter(log => + ['-2', '0', '1'].includes(log.status) + ); + + // 3. 상태 동기화가 필요한 경우 Knox API 호출 + let statusSyncMessage = ''; + if (pendingApprovals.length > 0) { + try { + const apinfids = pendingApprovals.map(approval => ({ + apinfid: approval.apInfId + })); + + const statusResponse = await getApprovalStatus({ + apinfids + }); + + if (statusResponse.result === 'success' && statusResponse.data) { + let updatedCount = 0; + + // 4. 상태 변경된 항목들 업데이트 + for (const statusData of statusResponse.data) { + const currentLog = logs.find(log => log.apInfId === statusData.apInfId); + if (currentLog && currentLog.status !== statusData.status) { + try { + await upsertApprovalStatus(statusData.apInfId, statusData.status); + // 메모리상의 데이터도 업데이트 + currentLog.status = statusData.status; + updatedCount++; + } catch (updateError) { + console.error(`결재상태 업데이트 실패 (${statusData.apInfId}):`, updateError); + } + } + } + + statusSyncMessage = updatedCount > 0 ? ` (${updatedCount}건 상태 동기화)` : ''; + } + } catch (syncError) { + console.error('결재 상태 동기화 중 오류:', syncError); + // 상태 동기화 실패는 전체 조회 실패로 처리하지 않음 + } + } + + // 5. ApprovalList 컴포넌트에서 기대하는 형식으로 데이터 변환 const formattedData = logs.map(log => ({ apInfId: log.apInfId, subject: log.subject, @@ -1058,7 +1101,7 @@ export async function getApprovalLogsAction(): Promise<{ return { success: true, - message: `${formattedData.length}건의 결재 로그를 조회했습니다.`, + message: `${formattedData.length}건의 결재 로그를 조회했습니다.${statusSyncMessage}`, data: formattedData, }; |
