summaryrefslogtreecommitdiff
path: root/lib/rfq-last/approval-actions.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-06 20:01:16 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-06 20:01:16 +0900
commit4c07f977c951cd99dd50d3bdaad0437e3dd55e6d (patch)
tree77c0db24854ed1ecde821d4a79543e82fa75eaed /lib/rfq-last/approval-actions.ts
parent1b843e0a7ea55c64992f55033b30037239ff67f5 (diff)
(김준회) ITB/RFQ/일반견적: 발송시 첨부파일 있는 경우 '암호화해제 결재' 프로세스 타도록 변경
Diffstat (limited to 'lib/rfq-last/approval-actions.ts')
-rw-r--r--lib/rfq-last/approval-actions.ts155
1 files changed, 155 insertions, 0 deletions
diff --git a/lib/rfq-last/approval-actions.ts b/lib/rfq-last/approval-actions.ts
new file mode 100644
index 00000000..be435931
--- /dev/null
+++ b/lib/rfq-last/approval-actions.ts
@@ -0,0 +1,155 @@
+/**
+ * RFQ 발송 결재 서버 액션
+ *
+ * 첨부파일이 있는 RFQ를 발송할 때 결재를 거치는 서버 액션
+ */
+
+'use server';
+
+import { ApprovalSubmissionSaga } from '@/lib/approval';
+import { mapRfqSendToTemplateVariables } from './approval-handlers';
+
+interface RfqSendApprovalData {
+ // RFQ 기본 정보
+ rfqId: number;
+ rfqCode?: string;
+
+ // 발송 데이터
+ vendors: Array<{
+ vendorId: number;
+ vendorName: string;
+ vendorCode?: string | null;
+ vendorCountry?: string | null;
+ selectedMainEmail: string;
+ additionalEmails: string[];
+ customEmails?: Array<{ email: string; name?: string }>;
+ currency?: string | null;
+ contractRequirements?: {
+ ndaYn: boolean;
+ generalGtcYn: boolean;
+ projectGtcYn: boolean;
+ agreementYn: boolean;
+ projectCode?: string;
+ };
+ isResend: boolean;
+ sendVersion?: number;
+ }>;
+ attachmentIds: number[];
+
+ // 첨부파일 정보 (파일명, 크기 등)
+ attachments: Array<{
+ fileName?: string | null;
+ fileSize?: number | null;
+ }>;
+
+ message?: string;
+ generatedPdfs?: Array<{
+ key: string;
+ buffer: number[];
+ fileName: string;
+ }>;
+ hasToSendEmail?: boolean;
+
+ // 신청 사유
+ applicationReason: string;
+
+ // 결재 정보
+ currentUser: {
+ id: number;
+ epId: string | null;
+ name?: string;
+ email?: string;
+ };
+ approvers?: string[]; // Knox EP ID 배열
+}
+
+/**
+ * RFQ 발송 결재 상신
+ *
+ * 첨부파일이 있는 경우 결재를 거쳐 RFQ를 발송합니다.
+ */
+export async function requestRfqSendWithApproval(data: RfqSendApprovalData) {
+ // 1. 입력 검증
+ if (!data.currentUser.epId) {
+ throw new Error('Knox EP ID가 필요합니다. 시스템 관리자에게 문의하세요.');
+ }
+
+ if (!data.vendors || data.vendors.length === 0) {
+ throw new Error('발송할 벤더를 선택해주세요.');
+ }
+
+ if (!data.attachmentIds || data.attachmentIds.length === 0) {
+ throw new Error('첨부파일이 없습니다. 결재가 필요하지 않습니다.');
+ }
+
+ console.log('[RFQ Approval] Starting approval process for RFQ send');
+ console.log('[RFQ Approval] RFQ ID:', data.rfqId);
+ console.log('[RFQ Approval] Vendors:', data.vendors.length);
+ console.log('[RFQ Approval] Attachments:', data.attachmentIds.length);
+
+ try {
+ // 2. 템플릿 변수 매핑
+ const variables = await mapRfqSendToTemplateVariables({
+ attachments: data.attachments,
+ vendorNames: data.vendors.map(v => v.vendorName),
+ applicationReason: data.applicationReason,
+ });
+
+ // 3. 결재 상신용 payload 구성
+ // ⚠️ cronjob 환경에서 실행되므로 currentUser 정보를 포함해야 함
+ const approvalPayload = {
+ rfqId: data.rfqId,
+ rfqCode: data.rfqCode,
+ vendors: data.vendors,
+ attachmentIds: data.attachmentIds,
+ message: data.message,
+ generatedPdfs: data.generatedPdfs,
+ hasToSendEmail: data.hasToSendEmail,
+ currentUser: {
+ id: data.currentUser.id,
+ name: data.currentUser.name,
+ email: data.currentUser.email,
+ epId: data.currentUser.epId,
+ },
+ };
+
+ // 4. Saga로 결재 상신
+ const saga = new ApprovalSubmissionSaga(
+ 'rfq_send_with_attachments', // 핸들러 키
+ approvalPayload, // 결재 승인 후 실행될 데이터
+ {
+ title: `암호화해제 신청 - ${data.rfqCode || 'RFQ'}`,
+ description: `${data.vendors.length}개 업체에 첨부파일 ${data.attachmentIds.length}개를 포함한 암호화해제 신청`,
+ templateName: '암호화해제 신청', // DB에 있어야 함
+ variables,
+ approvers: data.approvers,
+ currentUser: {
+ id: data.currentUser.id,
+ epId: data.currentUser.epId,
+ email: data.currentUser.email,
+ },
+ }
+ );
+
+ const result = await saga.execute();
+
+ console.log('[RFQ Approval] ✅ Approval submitted successfully');
+ console.log('[RFQ Approval] Approval ID:', result.approvalId);
+ console.log('[RFQ Approval] Pending Action ID:', result.pendingActionId);
+
+ return {
+ success: true,
+ ...result,
+ message: `결재가 상신되었습니다. (결재 ID: ${result.approvalId})`,
+ };
+
+ } catch (error) {
+ console.error('[RFQ Approval] ❌ Failed to submit approval:', error);
+ throw new Error(
+ error instanceof Error
+ ? error.message
+ : 'RFQ 발송 결재 상신에 실패했습니다.'
+ );
+ }
+}
+