summaryrefslogtreecommitdiff
path: root/lib/general-contracts/approval-actions.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/general-contracts/approval-actions.ts')
-rw-r--r--lib/general-contracts/approval-actions.ts136
1 files changed, 136 insertions, 0 deletions
diff --git a/lib/general-contracts/approval-actions.ts b/lib/general-contracts/approval-actions.ts
new file mode 100644
index 00000000..e75d6cd6
--- /dev/null
+++ b/lib/general-contracts/approval-actions.ts
@@ -0,0 +1,136 @@
+/**
+ * 일반계약 관련 결재 서버 액션
+ *
+ * 사용자가 UI에서 호출하는 함수들
+ * ApprovalSubmissionSaga를 사용하여 결재 프로세스를 시작
+ */
+
+'use server';
+
+import { ApprovalSubmissionSaga } from '@/lib/approval';
+import { mapContractToApprovalTemplateVariables } from './approval-template-variables';
+import { debugLog, debugError, debugSuccess } from '@/lib/debug-utils';
+import db from '@/db/db';
+import { eq } from 'drizzle-orm';
+import { generalContracts } from '@/db/schema/generalContract';
+import { users } from '@/db/schema';
+
+interface ContractSummary {
+ basicInfo: Record<string, unknown>;
+ items: Record<string, unknown>[];
+ subcontractChecklist: Record<string, unknown> | null;
+ storageInfo?: Record<string, unknown>[];
+ pdfPath?: string;
+ basicContractPdfs?: Array<{ key: string; buffer: number[]; fileName: string }>;
+}
+
+/**
+ * 결재를 거쳐 일반계약 승인 요청을 처리하는 서버 액션
+ *
+ * 사용법 (클라이언트 컴포넌트에서):
+ * ```typescript
+ * const result = await requestContractApprovalWithApproval({
+ * contractId: 123,
+ * contractSummary: summaryData,
+ * currentUser: { id: 1, epId: 'EP001', email: 'user@example.com' },
+ * approvers: ['EP002', 'EP003'],
+ * title: '계약 체결 진행 품의 요청서'
+ * });
+ *
+ * if (result.status === 'pending_approval') {
+ * console.log('결재 ID:', result.approvalId);
+ * }
+ * ```
+ */
+export async function requestContractApprovalWithApproval(data: {
+ contractId: number;
+ contractSummary: ContractSummary;
+ currentUser: { id: number; epId: string | null; email?: string };
+ approvers?: string[]; // Knox EP ID 배열 (결재선)
+ title?: string; // 결재 제목 (선택사항, 미지정 시 자동 생성)
+}) {
+ debugLog('[ContractApproval] 일반계약 승인 요청 결재 서버 액션 시작', {
+ contractId: data.contractId,
+ contractNumber: data.contractSummary.basicInfo?.contractNumber,
+ contractName: data.contractSummary.basicInfo?.name,
+ userId: data.currentUser.id,
+ hasEpId: !!data.currentUser.epId,
+ });
+
+ // 입력 검증
+ if (!data.currentUser.epId) {
+ debugError('[ContractApproval] Knox EP ID 없음');
+ throw new Error('Knox EP ID가 필요합니다');
+ }
+
+ if (!data.contractId) {
+ debugError('[ContractApproval] 계약 ID 없음');
+ throw new Error('계약 ID가 필요합니다');
+ }
+
+ // 1. 유저의 nonsapUserId 조회 (Cronjob 환경을 위해)
+ debugLog('[ContractApproval] nonsapUserId 조회');
+ const userResult = await db.query.users.findFirst({
+ where: eq(users.id, data.currentUser.id),
+ columns: { nonsapUserId: true }
+ });
+ const nonsapUserId = userResult?.nonsapUserId || null;
+ debugLog('[ContractApproval] nonsapUserId 조회 완료', { nonsapUserId });
+
+ // 2. 템플릿 변수 매핑
+ debugLog('[ContractApproval] 템플릿 변수 매핑 시작');
+ const variables = await mapContractToApprovalTemplateVariables(data.contractSummary);
+ debugLog('[ContractApproval] 템플릿 변수 매핑 완료', {
+ variableKeys: Object.keys(variables),
+ });
+
+ // 3. 결재 워크플로우 시작 (Saga 패턴)
+ debugLog('[ContractApproval] ApprovalSubmissionSaga 생성');
+ const saga = new ApprovalSubmissionSaga(
+ // actionType: 핸들러를 찾을 때 사용할 키
+ 'general_contract_approval',
+
+ // actionPayload: 결재 승인 후 핸들러에 전달될 데이터
+ {
+ contractId: data.contractId,
+ contractSummary: data.contractSummary,
+ currentUser: {
+ id: data.currentUser.id,
+ email: data.currentUser.email,
+ nonsapUserId: nonsapUserId,
+ },
+ },
+
+ // approvalConfig: 결재 상신 정보 (템플릿 포함)
+ {
+ title: data.title || `계약 체결 진행 품의 요청서 - ${data.contractSummary.basicInfo?.contractNumber || data.contractId}`,
+ description: `${data.contractSummary.basicInfo?.name || '일반계약'} 계약 체결 진행 품의 요청`,
+ templateName: '일반계약 결재', // 한국어 템플릿명
+ variables, // 치환할 변수들
+ approvers: data.approvers,
+ currentUser: data.currentUser,
+ }
+ );
+
+ debugLog('[ContractApproval] Saga 실행 시작');
+ const result = await saga.execute();
+
+ // 4. 결재 상신 성공 시 상태를 'approval_in_progress'로 변경
+ if (result.status === 'pending_approval') {
+ debugLog('[ContractApproval] 상태를 approval_in_progress로 변경');
+ await db.update(generalContracts)
+ .set({
+ status: 'approval_in_progress',
+ lastUpdatedAt: new Date()
+ })
+ .where(eq(generalContracts.id, data.contractId));
+ }
+
+ debugSuccess('[ContractApproval] 결재 워크플로우 완료', {
+ approvalId: result.approvalId,
+ status: result.status,
+ });
+
+ return result;
+}
+