/** * 결재 시스템 API 클라이언트 * 엔드포인트: /api/approval/* */ import apiClient from "@/lib/api/client"; // ============================================================ // 공통 타입 정의 // ============================================================ export interface ApiResponse { success: boolean; data?: T; message?: string; error?: string; total?: number; page?: number; limit?: number; } export interface ApprovalDefinition { definition_id: number; definition_name: string; definition_name_eng?: string; description?: string; default_template_id?: number; max_steps: number; allow_self_approval: boolean; allow_cancel: boolean; is_active: string; company_code: string; created_by?: string; created_at: string; updated_by?: string; updated_at: string; } export interface ApprovalLineTemplate { template_id: number; template_name: string; description?: string; definition_id?: number; definition_name?: string; is_active: string; company_code: string; created_by?: string; created_at: string; updated_by?: string; updated_at: string; steps?: ApprovalLineTemplateStep[]; } export interface ApprovalLineTemplateStep { step_id: number; template_id: number; step_order: number; step_type?: "approval" | "consensus" | "notification"; approver_type: "user" | "position" | "dept"; approver_user_id?: string; approver_position?: string; approver_dept_code?: string; approver_label?: string; company_code: string; } export interface ApprovalProxySetting { id: number; original_user_id: string; original_user_name?: string; original_dept_name?: string; proxy_user_id: string; proxy_user_name?: string; proxy_dept_name?: string; start_date: string; end_date: string; reason?: string; is_active: string; company_code: string; created_at: string; updated_at: string; } export interface ApprovalRequest { request_id: number; title: string; description?: string; definition_id?: number; definition_name?: string; target_table: string; target_record_id: string; target_record_data?: Record; status: "requested" | "in_progress" | "approved" | "rejected" | "cancelled"; current_step: number; total_steps: number; requester_id: string; requester_name?: string; requester_dept?: string; completed_at?: string; final_approver_id?: string; final_comment?: string; screen_id?: number; button_component_id?: string; company_code: string; created_at: string; updated_at: string; lines?: ApprovalLine[]; } export interface ApprovalLine { line_id: number; request_id: number; step_order: number; approver_id: string; approver_name?: string; approver_position?: string; approver_dept?: string; approver_label?: string; status: "waiting" | "pending" | "approved" | "rejected" | "skipped"; comment?: string; processed_at?: string; company_code: string; created_at: string; // 요청 정보 (my-pending 조회 시 포함) title?: string; target_table?: string; target_record_id?: string; requester_name?: string; requester_dept?: string; request_created_at?: string; } export interface CreateApprovalRequestInput { title: string; description?: string; definition_id?: number; target_table: string; target_record_id?: string; target_record_data?: Record; screen_id?: number; button_component_id?: string; approval_mode?: "sequential" | "parallel"; approval_type?: "self" | "escalation" | "consensus" | "post"; approvers: { approver_id: string; approver_name?: string; approver_position?: string; approver_dept?: string; approver_label?: string; step_type?: "approval" | "consensus" | "notification"; step_order?: number; }[]; } // ============================================================ // 결재 유형 (Definitions) API // ============================================================ export async function getApprovalDefinitions(params?: { is_active?: string; search?: string; }): Promise> { try { const response = await apiClient.get("/approval/definitions", { params }); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function getApprovalDefinition(id: number): Promise> { try { const response = await apiClient.get(`/approval/definitions/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function createApprovalDefinition(data: { definition_name: string; definition_name_eng?: string; description?: string; default_template_id?: number; max_steps?: number; allow_self_approval?: boolean; allow_cancel?: boolean; is_active?: string; }): Promise> { try { const response = await apiClient.post("/approval/definitions", data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function updateApprovalDefinition( id: number, data: Partial ): Promise> { try { const response = await apiClient.put(`/approval/definitions/${id}`, data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function deleteApprovalDefinition(id: number): Promise> { try { const response = await apiClient.delete(`/approval/definitions/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 결재선 템플릿 (Templates) API // ============================================================ export async function getApprovalTemplates(params?: { definition_id?: number; is_active?: string; }): Promise> { try { const response = await apiClient.get("/approval/templates", { params }); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function getApprovalTemplate(id: number): Promise> { try { const response = await apiClient.get(`/approval/templates/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function createApprovalTemplate(data: { template_name: string; description?: string; definition_id?: number; is_active?: string; steps?: Omit[]; }): Promise> { try { const response = await apiClient.post("/approval/templates", data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function updateApprovalTemplate( id: number, data: { template_name?: string; description?: string; definition_id?: number; is_active?: string; steps?: Omit[]; } ): Promise> { try { const response = await apiClient.put(`/approval/templates/${id}`, data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function deleteApprovalTemplate(id: number): Promise> { try { const response = await apiClient.delete(`/approval/templates/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 결재 요청 (Requests) API // ============================================================ export async function getApprovalRequests(params?: { status?: string; target_table?: string; target_record_id?: string; requester_id?: string; my_approvals?: boolean; page?: number; limit?: number; }): Promise> { try { const response = await apiClient.get("/approval/requests", { params }); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function getApprovalRequest(id: number): Promise> { try { const response = await apiClient.get(`/approval/requests/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function createApprovalRequest( data: CreateApprovalRequestInput ): Promise> { try { const response = await apiClient.post("/approval/requests", data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function cancelApprovalRequest(id: number): Promise> { try { const response = await apiClient.post(`/approval/requests/${id}/cancel`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 결재 라인 처리 (Lines) API // ============================================================ export async function getMyPendingApprovals(): Promise> { try { const response = await apiClient.get("/approval/my-pending"); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function processApprovalLine( lineId: number, data: { action: "approved" | "rejected"; comment?: string } ): Promise> { try { const response = await apiClient.post(`/approval/lines/${lineId}/process`, data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 대결 위임 설정 (Proxy Settings) API // ============================================================ export async function getProxySettings(): Promise> { try { const response = await apiClient.get("/approval/proxy-settings"); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function createProxySetting(data: { original_user_id: string; proxy_user_id: string; start_date: string; end_date: string; reason?: string; }): Promise> { try { const response = await apiClient.post("/approval/proxy-settings", data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function updateProxySetting( id: number, data: { proxy_user_id?: string; start_date?: string; end_date?: string; reason?: string; is_active?: string; } ): Promise> { try { const response = await apiClient.put(`/approval/proxy-settings/${id}`, data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function deleteProxySetting(id: number): Promise> { try { const response = await apiClient.delete(`/approval/proxy-settings/${id}`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function checkActiveProxy( userId: string ): Promise> { try { const response = await apiClient.get( `/approval/proxy-settings/check/${encodeURIComponent(userId)}` ); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 후결 승인 API // ============================================================ export async function postApproveRequest(requestId: number): Promise> { try { const response = await apiClient.post(`/approval/requests/${requestId}/post-approve`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } // ============================================================ // 결재선 템플릿 단계 (Template Steps) API // ============================================================ export async function getTemplateSteps( templateId: number ): Promise> { try { const response = await apiClient.get(`/approval/templates/${templateId}/steps`); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function createTemplateStep( templateId: number, data: Omit ): Promise> { try { const response = await apiClient.post(`/approval/templates/${templateId}/steps`, data); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function updateTemplateStep( templateId: number, stepId: number, data: Partial> ): Promise> { try { const response = await apiClient.put( `/approval/templates/${templateId}/steps/${stepId}`, data ); return response.data; } catch (error: any) { return { success: false, error: error.message }; } } export async function deleteTemplateStep( templateId: number, stepId: number ): Promise> { try { const response = await apiClient.delete( `/approval/templates/${templateId}/steps/${stepId}` ); return response.data; } catch (error: any) { return { success: false, error: error.message }; } }