summaryrefslogtreecommitdiff
path: root/lib/vendors/approval-actions.ts
blob: 69d09caa4b8cadb1398a977f0e48112358197855 (plain)
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',
    }
  }
}