diff options
Diffstat (limited to 'lib/vendors/approval-actions.ts')
| -rw-r--r-- | lib/vendors/approval-actions.ts | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/vendors/approval-actions.ts b/lib/vendors/approval-actions.ts new file mode 100644 index 00000000..69d09caa --- /dev/null +++ b/lib/vendors/approval-actions.ts @@ -0,0 +1,119 @@ +'use server' + +import { ApprovalSubmissionSaga } from '@/lib/approval' +import type { ApprovalConfig } from '@/lib/approval/types' +import db from '@/db/db' +import { vendors } from '@/db/schema/vendors' +import { inArray } from 'drizzle-orm' + +/** + * 벤더 가입 승인 결재 상신 + * + * @param input - 결재 요청 정보 + * @returns 결재 상신 결과 + */ +export async function approveVendorsWithApproval(input: { + vendorIds: number[] + currentUser: { + id: number + epId: string | null + email?: string + } + approvers?: string[] +}) { + console.log(`[Vendor Approval Action] 벤더 승인 결재 상신 시작:`, input.vendorIds) + + try { + // 1. 입력 검증 + if (!input.currentUser.epId) { + throw new Error('Knox EP ID가 필요합니다. 시스템 관리자에게 문의하세요.') + } + + if (input.vendorIds.length === 0) { + throw new Error('승인할 벤더를 선택해주세요.') + } + + // 2. 벤더 정보 조회 + const vendorRecords = await db + .select({ + id: vendors.id, + vendorName: vendors.vendorName, + vendorCode: vendors.vendorCode, + email: vendors.email, + status: vendors.status, + taxId: vendors.taxId, + country: vendors.country, + }) + .from(vendors) + .where(inArray(vendors.id, input.vendorIds)) + + if (vendorRecords.length === 0) { + throw new Error(`벤더를 찾을 수 없습니다: ${input.vendorIds.join(', ')}`) + } + + // 3. PENDING_REVIEW 상태가 아닌 벤더 확인 + const invalidVendors = vendorRecords.filter(v => v.status !== 'PENDING_REVIEW') + if (invalidVendors.length > 0) { + throw new Error( + `가입 신청 중(PENDING_REVIEW) 상태의 벤더만 승인할 수 있습니다. ` + + `잘못된 상태: ${invalidVendors.map(v => `${v.vendorName}(${v.status})`).join(', ')}` + ) + } + + console.log(`[Vendor Approval Action] ${vendorRecords.length}개 벤더 조회 완료`) + + // 4. 템플릿 변수 준비 (TODO: 실제 템플릿에 맞게 수정 필요) + const variables: Record<string, string> = { + // TODO: 다음 대화에서 제공될 템플릿에 맞게 변수 매핑 + '업체수': String(vendorRecords.length), + '업체목록': vendorRecords.map(v => + `${v.vendorName} (${v.vendorCode || '코드 미할당'})` + ).join('\n'), + '요청일': new Date().toLocaleDateString('ko-KR'), + '요청자': input.currentUser.email || 'Unknown', + } + + console.log(`[Vendor Approval Action] 템플릿 변수 준비 완료`) + + // 5. 결재 상신 (Saga 패턴) + const saga = new ApprovalSubmissionSaga( + 'vendor_approval', // 핸들러 타입 (handlers-registry에 등록될 키) + { + vendorIds: input.vendorIds, + userId: input.currentUser.id, // 결재 승인 후 실행 시 필요 + }, + { + title: `벤더 가입 승인 요청 - ${vendorRecords.length}개 업체`, + description: `${vendorRecords.map(v => v.vendorName).join(', ')} 의 가입을 승인합니다.`, + templateName: '벤더 가입 승인 요청', + variables, + approvers: input.approvers, + currentUser: input.currentUser, + } as ApprovalConfig + ) + + console.log(`[Vendor Approval Action] 결재 상신 실행 중...`) + + const result = await saga.execute() + + console.log(`[Vendor Approval Action] 결재 상신 완료:`, result) + + return { + success: true, + message: `${vendorRecords.length}개 벤더의 가입 승인 결재가 상신되었습니다.`, + approvalId: result.approvalId, + pendingActionId: result.pendingActionId, + status: result.status, + } + + } catch (error) { + console.error(`[Vendor Approval Action] 결재 상신 실패:`, error) + + return { + success: false, + message: error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다.', + error: error instanceof Error ? error.message : 'Unknown error', + } + } +} + |
