1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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',
}
}
}
|