'use server'; import { revalidatePath } from 'next/cache'; import { ApprovalExecutionSaga } from '@/lib/approval/approval-saga'; import { getApprovalLogDetail } from './service'; import db from '@/db/db'; import { pendingActions } from '@/db/schema/knox/pending-actions'; import { eq } from 'drizzle-orm'; /** * 결재 후처리 강제 실행 * * 외부 시스템(Knox) 장애 시 결재가 승인되었지만 * 후속 작업이 실행되지 않은 경우 강제로 실행 * * @param apInfId 결재 ID * @returns 성공 여부 및 결과 메시지 */ export async function forcePostProcessApproval(apInfId: string) { try { console.log(`[ForcePostProcess] Starting forced post-process for ${apInfId}`); // 1. 결재 로그 및 Pending Action 조회 const detail = await getApprovalLogDetail(apInfId); if (!detail) { return { success: false, error: '결재 로그를 찾을 수 없습니다.', }; } const { pendingAction } = detail; // 2. Pending Action이 없는 경우 if (!pendingAction) { return { success: false, error: '실행할 후처리 작업이 없습니다. 이 결재는 후처리 작업이 연결되지 않은 결재입니다.', }; } // 3. 이미 실행된 경우 if (pendingAction.status === 'executed') { return { success: false, error: '이미 후처리가 완료된 결재입니다.', }; } // 4. Pending Action 상태를 'pending'으로 재설정 (강제 실행을 위해) console.log(`[ForcePostProcess] Resetting pending action status to 'pending'`); await db.update(pendingActions) .set({ status: 'pending', errorMessage: null, executionResult: null, }) .where(eq(pendingActions.apInfId, apInfId)); // 5. ApprovalExecutionSaga를 통해 강제 실행 console.log(`[ForcePostProcess] Executing ApprovalExecutionSaga`); const saga = new ApprovalExecutionSaga(apInfId); const result = await saga.execute(); // 6. 캐시 무효화 revalidatePath(`/[lng]/evcp/approval/log`, 'page'); revalidatePath(`/[lng]/evcp/approval/log/${apInfId}`, 'page'); console.log(`[ForcePostProcess] ✅ Post-process completed successfully`); return { success: true, message: '후처리가 성공적으로 실행되었습니다.', result, }; } catch (error) { console.error('[ForcePostProcess] ❌ Post-process failed:', error); return { success: false, error: error instanceof Error ? `후처리 실행 중 오류가 발생했습니다: ${error.message}` : '후처리 실행 중 알 수 없는 오류가 발생했습니다.', }; } }