319 lines
11 KiB
JavaScript
319 lines
11 KiB
JavaScript
/**
|
|
* 리비전 관리 훅
|
|
* - 리비전 세션 생성, 관리, 완료
|
|
* - 자재 비교 및 변경사항 처리
|
|
* - 리비전 히스토리 조회
|
|
*/
|
|
|
|
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)
|
|
};
|
|
};
|