/** * 리비전 관리 훅 * - 리비전 세션 생성, 관리, 완료 * - 자재 비교 및 변경사항 처리 * - 리비전 히스토리 조회 */ import { useState, useCallback } from 'react'; import api from '../api'; export const useRevisionManagement = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [currentSession, setCurrentSession] = useState(null); const [sessionStatus, setSessionStatus] = useState(null); const [revisionHistory, setRevisionHistory] = useState([]); // 에러 처리 헬퍼 const handleError = useCallback((error, defaultMessage) => { console.error(defaultMessage, error); const errorMessage = error.response?.data?.detail || error.message || defaultMessage; setError(errorMessage); return { success: false, error: errorMessage }; }, []); // 리비전 세션 생성 const createRevisionSession = useCallback(async (jobNo, currentFileId, previousFileId) => { setLoading(true); setError(null); try { const response = await api.post('/revision-management/sessions', { job_no: jobNo, current_file_id: currentFileId, previous_file_id: previousFileId }); if (response.data.success) { setCurrentSession(response.data.data); console.log('✅ 리비전 세션 생성 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 세션 생성 실패'); } } catch (error) { return handleError(error, '리비전 세션 생성 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 세션 상태 조회 const getSessionStatus = useCallback(async (sessionId) => { setLoading(true); setError(null); try { const response = await api.get(`/revision-management/sessions/${sessionId}`); if (response.data.success) { setSessionStatus(response.data.data); console.log('✅ 세션 상태 조회 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '세션 상태 조회 실패'); } } catch (error) { return handleError(error, '세션 상태 조회 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 카테고리별 자재 비교 const compareCategory = useCallback(async (sessionId, category) => { setLoading(true); setError(null); try { const response = await api.post(`/revision-management/sessions/${sessionId}/compare/${category}`); if (response.data.success) { console.log(`✅ 카테고리 ${category} 비교 완료:`, response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), `카테고리 ${category} 비교 실패`); } } catch (error) { return handleError(error, `카테고리 ${category} 비교 중 오류 발생`); } finally { setLoading(false); } }, [handleError]); // 세션 변경사항 조회 const getSessionChanges = useCallback(async (sessionId, category = null) => { setLoading(true); setError(null); try { const params = category ? { category } : {}; const response = await api.get(`/revision-management/sessions/${sessionId}/changes`, { params }); if (response.data.success) { console.log('✅ 세션 변경사항 조회 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '세션 변경사항 조회 실패'); } } catch (error) { return handleError(error, '세션 변경사항 조회 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 리비전 액션 처리 const processRevisionAction = useCallback(async (changeId, action, notes = null) => { setLoading(true); setError(null); try { const response = await api.post(`/revision-management/changes/${changeId}/process`, { action, notes }); if (response.data.success) { console.log('✅ 리비전 액션 처리 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 액션 처리 실패'); } } catch (error) { return handleError(error, '리비전 액션 처리 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 세션 완료 const completeSession = useCallback(async (sessionId) => { setLoading(true); setError(null); try { const response = await api.post(`/revision-management/sessions/${sessionId}/complete`); if (response.data.success) { setCurrentSession(null); setSessionStatus(null); console.log('✅ 리비전 세션 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 세션 완료 실패'); } } catch (error) { return handleError(error, '리비전 세션 완료 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 세션 취소 const cancelSession = useCallback(async (sessionId, reason = null) => { setLoading(true); setError(null); try { const params = reason ? { reason } : {}; const response = await api.post(`/revision-management/sessions/${sessionId}/cancel`, null, { params }); if (response.data.success) { setCurrentSession(null); setSessionStatus(null); console.log('✅ 리비전 세션 취소:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 세션 취소 실패'); } } catch (error) { return handleError(error, '리비전 세션 취소 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 리비전 히스토리 조회 const getRevisionHistory = useCallback(async (jobNo) => { setLoading(true); setError(null); try { const response = await api.get(`/revision-management/history/${jobNo}`); if (response.data.success) { setRevisionHistory(response.data.data.history); console.log('✅ 리비전 히스토리 조회 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 히스토리 조회 실패'); } } catch (error) { return handleError(error, '리비전 히스토리 조회 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 리비전 요약 조회 const getRevisionSummary = useCallback(async (sessionId) => { setLoading(true); setError(null); try { const response = await api.get(`/revision-management/sessions/${sessionId}/summary`); if (response.data.success) { console.log('✅ 리비전 요약 조회 완료:', response.data.data); return { success: true, data: response.data.data }; } else { return handleError(new Error(response.data.message), '리비전 요약 조회 실패'); } } catch (error) { return handleError(error, '리비전 요약 조회 중 오류 발생'); } finally { setLoading(false); } }, [handleError]); // 지원 카테고리 조회 const getSupportedCategories = useCallback(async () => { try { const response = await api.get('/revision-management/categories'); if (response.data.success) { return { success: true, data: response.data.data.categories }; } } catch (error) { console.warn('지원 카테고리 조회 실패:', error); } // 기본 카테고리 반환 return { success: true, data: [ { key: "PIPE", name: "배관", description: "파이프 및 배관 자재" }, { key: "FITTING", name: "피팅", description: "배관 연결 부품" }, { key: "FLANGE", name: "플랜지", description: "플랜지 및 연결 부품" }, { key: "VALVE", name: "밸브", description: "각종 밸브류" }, { key: "GASKET", name: "가스켓", description: "씰링 부품" }, { key: "BOLT", name: "볼트", description: "체결 부품" }, { key: "SUPPORT", name: "서포트", description: "지지대 및 구조물" }, { key: "SPECIAL", name: "특수자재", description: "특수 목적 자재" }, { key: "UNCLASSIFIED", name: "미분류", description: "분류되지 않은 자재" } ] }; }, []); // 리비전 액션 목록 조회 const getRevisionActions = useCallback(async () => { try { const response = await api.get('/revision-management/actions'); if (response.data.success) { return { success: true, data: response.data.data.actions }; } } catch (error) { console.warn('리비전 액션 조회 실패:', error); } // 기본 액션 반환 return { success: true, data: [ { key: "new_material", name: "신규 자재", description: "새로 추가된 자재" }, { key: "additional_purchase", name: "추가 구매", description: "구매된 자재의 수량 증가" }, { key: "inventory_transfer", name: "재고 이관", description: "구매된 자재의 수량 감소 또는 제거" }, { key: "purchase_cancel", name: "구매 취소", description: "미구매 자재의 제거" }, { key: "quantity_update", name: "수량 업데이트", description: "미구매 자재의 수량 변경" }, { key: "maintain", name: "유지", description: "변경사항 없음" } ] }; }, []); // 상태 초기화 const resetState = useCallback(() => { setCurrentSession(null); setSessionStatus(null); setRevisionHistory([]); setError(null); setLoading(false); }, []); return { // 상태 loading, error, currentSession, sessionStatus, revisionHistory, // 액션 createRevisionSession, getSessionStatus, compareCategory, getSessionChanges, processRevisionAction, completeSession, cancelSession, getRevisionHistory, getRevisionSummary, getSupportedCategories, getRevisionActions, resetState, // 유틸리티 clearError: () => setError(null) }; };