summaryrefslogtreecommitdiff
path: root/lib/general-contracts/handlers.ts
blob: 029fb9cdd2d0a97a5080f8e28a4d9b26768b1587 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
 * 일반계약 관련 결재 액션 핸들러
 * 
 * 실제 비즈니스 로직만 포함 (결재 로직은 approval-workflow에서 처리)
 */

'use server';

import { sendContractApprovalRequest } from './service';
import { debugLog, debugError, debugSuccess } from '@/lib/debug-utils';
import db from '@/db/db';
import { eq } from 'drizzle-orm';
import { generalContracts } from '@/db/schema/generalContract';

interface ContractSummary {
  basicInfo: Record<string, unknown>;
  items: Record<string, unknown>[];
  subcontractChecklist: Record<string, unknown> | null;
  storageInfo?: Record<string, unknown>[];
}

/**
 * 일반계약 승인 핸들러 (결재 승인 후 계약승인요청 전송 실행)
 *
 * 결재 승인 후 자동으로 계약승인요청을 전송함
 * 이 함수는 직접 호출하지 않고, 결재 워크플로우에서 자동으로 호출됨
 *
 * @param payload - withApproval()에서 전달한 actionPayload
 */
export async function approveContractInternal(payload: {
  contractId: number;
  contractSummary: ContractSummary;
  currentUser?: {
    id: string | number;
    name?: string | null;
    email?: string | null;
    nonsapUserId?: string | null;
  };
}) {
  debugLog('[ContractApprovalHandler] 일반계약 승인 핸들러 시작', {
    contractId: payload.contractId,
    contractNumber: payload.contractSummary.basicInfo?.contractNumber,
    contractName: payload.contractSummary.basicInfo?.name,
    hasCurrentUser: !!payload.currentUser,
  });

  try {
    // 1. 계약 정보 확인
    const [contract] = await db
      .select()
      .from(generalContracts)
      .where(eq(generalContracts.id, payload.contractId))
      .limit(1);

    if (!contract) {
      throw new Error('계약을 찾을 수 없습니다.');
    }

    // 2. 계약승인요청 전송
    debugLog('[ContractApprovalHandler] sendContractApprovalRequest 호출');
    
    // PDF 경로에서 PDF 버퍼 읽기
    const pdfPath = (payload.contractSummary as any).pdfPath;
    if (!pdfPath) {
      throw new Error('PDF 경로가 없습니다.');
    }

    // PDF 파일 읽기
    const fs = await import('fs/promises');
    const path = await import('path');
    
    const nasPath = process.env.NAS_PATH || "/evcp_nas";
    const isProduction = process.env.NODE_ENV === "production";
    const baseDir = isProduction ? nasPath : path.join(process.cwd(), "public");
    
    // publicPath에서 실제 파일 경로로 변환
    const actualPath = pdfPath.startsWith('/') 
      ? path.join(baseDir, pdfPath)
      : path.join(baseDir, 'generalContracts', pdfPath);

    let pdfBuffer: Uint8Array;
    try {
      const fileBuffer = await fs.readFile(actualPath);
      pdfBuffer = new Uint8Array(fileBuffer);
    } catch (error) {
      debugError('[ContractApprovalHandler] PDF 파일 읽기 실패', error);
      throw new Error('PDF 파일을 읽을 수 없습니다.');
    }

    // 기본계약서는 클라이언트에서 이미 생성되었을 것으로 가정
    const generatedBasicContracts: Array<{ key: string; buffer: number[]; fileName: string }> = 
      (payload.contractSummary as any).basicContractPdfs || [];

    const userId = payload.currentUser?.id 
      ? String(payload.currentUser.id) 
      : String(contract.registeredById);

    const result = await sendContractApprovalRequest(
      payload.contractSummary,
      pdfBuffer,
      'contractDocument',
      userId,
      generatedBasicContracts
    );

    if (!result.success) {
      debugError('[ContractApprovalHandler] 계약승인요청 전송 실패', result.error);
      
      // 전송 실패 시 상태를 원래대로 되돌림
      await db.update(generalContracts)
        .set({ 
          status: 'Draft',
          lastUpdatedAt: new Date()
        })
        .where(eq(generalContracts.id, payload.contractId));
      
      throw new Error(result.error || '계약승인요청 전송에 실패했습니다.');
    }

    // 3. 전송 성공 시 상태를 'Contract Accept Request'로 변경
    debugLog('[ContractApprovalHandler] 계약승인요청 전송 성공, 상태를 Contract Accept Request로 변경');
    await db.update(generalContracts)
      .set({ 
        status: 'Contract Accept Request',
        lastUpdatedAt: new Date()
      })
      .where(eq(generalContracts.id, payload.contractId));

    debugSuccess('[ContractApprovalHandler] 일반계약 승인 완료', {
      contractId: payload.contractId,
      result: result
    });

    return {
      success: true,
      message: '계약승인요청이 전송되었습니다.',
      result: result
    };
  } catch (error) {
    debugError('[ContractApprovalHandler] 일반계약 승인 중 에러', error);
    
    // 에러 발생 시 상태를 원래대로 되돌림
    try {
      await db.update(generalContracts)
        .set({ 
          status: 'Draft',
          lastUpdatedAt: new Date()
        })
        .where(eq(generalContracts.id, payload.contractId));
    } catch (updateError) {
      debugError('[ContractApprovalHandler] 상태 업데이트 실패', updateError);
    }
    
    throw error;
  }
}