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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/**
* 정규업체 등록 관련 결재 서버 액션
*
* 사용자가 UI에서 호출하는 함수들
* withApproval()을 사용하여 결재 프로세스를 시작
*/
'use server';
import { ApprovalSubmissionSaga } from '@/lib/approval';
import { mapRegistrationToTemplateVariables } from './handlers';
import { debugLog, debugError, debugSuccess } from '@/lib/debug-utils';
import type { RegistrationRequestData } from '@/components/vendor-regular-registrations/registration-request-dialog';
import db from '@/db/db';
import { eq } from 'drizzle-orm';
import { vendorRegularRegistrations } from '@/db/schema/vendorRegistrations';
import { users } from '@/db/schema';
/**
* 결재를 거쳐 정규업체 등록을 처리하는 서버 액션
*
* 사용법 (클라이언트 컴포넌트에서):
* ```typescript
* const result = await registerVendorWithApproval({
* registrationId: 123,
* requestData: registrationData,
* currentUser: { id: 1, epId: 'EP001', email: 'user@example.com' },
* approvers: ['EP002', 'EP003'],
* attachments: [file1, file2] // 선택사항
* });
*
* if (result.status === 'pending_approval') {
* console.log('결재 ID:', result.approvalId);
* }
* ```
*/
export async function registerVendorWithApproval(data: {
registrationId: number;
requestData: RegistrationRequestData;
vendorId?: number; // vendors 테이블에서 정보를 가져오기 위한 vendorId
currentUser: { id: number; epId: string | null; email?: string };
approvers?: string[]; // Knox EP ID 배열 (결재선)
attachments?: File[]; // 첨부파일 (선택사항)
title?: string; // 결재 제목 (선택사항, 미지정 시 자동 생성)
}) {
debugLog('[VendorRegistrationApproval] 정규업체 등록 결재 서버 액션 시작', {
registrationId: data.registrationId,
companyName: data.requestData.companyNameKor,
businessNumber: data.requestData.businessNumber,
userId: data.currentUser.id,
hasEpId: !!data.currentUser.epId,
});
// 입력 검증
if (!data.currentUser.epId) {
debugError('[VendorRegistrationApproval] Knox EP ID 없음');
throw new Error('Knox EP ID가 필요합니다');
}
if (!data.registrationId) {
debugError('[VendorRegistrationApproval] 등록 ID 없음');
throw new Error('등록 ID가 필요합니다');
}
// 1. 유저의 nonsapUserId 조회 (Cronjob 환경을 위해)
debugLog('[VendorRegistrationApproval] nonsapUserId 조회');
const userResult = await db.query.users.findFirst({
where: eq(users.id, data.currentUser.id),
columns: { nonsapUserId: true }
});
const nonsapUserId = userResult?.nonsapUserId || null;
debugLog('[VendorRegistrationApproval] nonsapUserId 조회 완료', { nonsapUserId });
// 2. 템플릿 변수 매핑
debugLog('[VendorRegistrationApproval] 템플릿 변수 매핑 시작');
const requestedAt = new Date();
const variables = await mapRegistrationToTemplateVariables({
requestData: data.requestData,
requestedAt,
vendorId: data.vendorId,
});
debugLog('[VendorRegistrationApproval] 템플릿 변수 매핑 완료', {
variableKeys: Object.keys(variables),
});
// 3. 결재 워크플로우 시작 (Saga 패턴)
debugLog('[VendorRegistrationApproval] ApprovalSubmissionSaga 생성', {
hasAttachments: !!data.attachments,
attachmentCount: data.attachments?.length || 0,
});
const saga = new ApprovalSubmissionSaga(
// actionType: 핸들러를 찾을 때 사용할 키
'vendor_regular_registration',
// actionPayload: 결재 승인 후 핸들러에 전달될 데이터
{
registrationId: data.registrationId,
requestData: data.requestData,
currentUser: { // ⚠️ Cronjob 환경을 위한 유저 정보 포함 (headers() 대신)
id: data.currentUser.id,
email: data.currentUser.email,
nonsapUserId: nonsapUserId, // ⚠️ 미리 조회한 nonsapUserId 전달
},
},
// approvalConfig: 결재 상신 정보 (템플릿 포함)
{
title: data.title || `정규업체 등록 - ${data.requestData.companyNameKor}`,
description: `${data.requestData.companyNameKor} 정규업체 등록 요청`,
templateName: '정규업체 등록', // 한국어 템플릿명
variables, // 치환할 변수들
approvers: data.approvers,
currentUser: data.currentUser,
attachments: data.attachments, // 첨부파일 전달
}
);
debugLog('[VendorRegistrationApproval] Saga 실행 시작');
const result = await saga.execute();
// 4. 결재 상신 성공 시 상태를 pending_approval로 변경
if (result.status === 'pending_approval') {
debugLog('[VendorRegistrationApproval] 상태를 pending_approval로 변경');
await db.update(vendorRegularRegistrations)
.set({
status: 'pending_approval',
updatedAt: new Date()
})
.where(eq(vendorRegularRegistrations.id, data.registrationId));
}
debugSuccess('[VendorRegistrationApproval] 결재 워크플로우 완료', {
approvalId: result.approvalId,
status: result.status,
});
return result;
}
|