feat: 완전한 데이터베이스 스키마 정리 및 테스트 서버 안정화
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled

- 43개 테이블로 구성된 완전한 BOM 관리 시스템
- 카테고리별 상세 테이블 (9개): pipe, fitting, flange, valve, gasket, bolt, support, special, instrument
- 사용자 관리 시스템: users, login_logs, user_sessions, user_activity_logs
- 구매 관리 시스템: purchase_requests, purchase_request_items, purchase_items
- 리비전 관리 시스템: material_revisions_comparison, material_comparison_details
- 튜빙 시스템: tubing_categories, tubing_manufacturers, tubing_products, tubing_specifications
- 표준화/분류 시스템: material_standards, material_categories, material_patterns 등
- 권한 관리 시스템: permissions, role_permissions
- 고급 기능: user_requirements, pipe_end_preparations, material_tubing_mapping
- 성능 최적화: materials 테이블 17개 인덱스, GIN/복합/조건부 인덱스
- 데이터 무결성: 외래키 제약으로 일관성 보장
- 확장성: JSONB 활용한 유연한 메타데이터 저장
This commit is contained in:
hyungi
2025-10-21 12:33:05 +09:00
parent ab607dfa9a
commit edfe1bdf78

View File

@@ -174,8 +174,8 @@ function App() {
newSet.delete(projectId);
console.log('📦 활성화 프로젝트 업데이트:', { prev: Array.from(prev), new: Array.from(newSet) });
return newSet;
});
};
});
};
// 인증 상태 확인
useEffect(() => {
@@ -192,13 +192,13 @@ function App() {
}
} catch (error) {
console.error('인증 확인 실패:', error);
localStorage.removeItem('access_token');
localStorage.removeItem('user_data');
setIsAuthenticated(false);
localStorage.removeItem('access_token');
localStorage.removeItem('user_data');
setIsAuthenticated(false);
} finally {
setIsLoading(false);
}
};
};
checkAuth();
}, []);
@@ -213,7 +213,7 @@ function App() {
const renderCurrentPage = () => {
switch (currentPage) {
case 'dashboard':
return (
return (
<DashboardPage
user={user}
projects={projects}
@@ -279,14 +279,14 @@ function App() {
);
case 'system-settings':
return (
<SystemSettingsPage
<SystemSettingsPage
onNavigate={navigateToPage}
user={user}
/>
);
case 'account-settings':
return (
<AccountSettingsPage
<AccountSettingsPage
onNavigate={navigateToPage}
user={user}
onUserUpdate={(updatedUser) => {
@@ -297,21 +297,21 @@ function App() {
);
case 'user-management':
return (
<UserManagementPage
<UserManagementPage
onNavigate={navigateToPage}
user={user}
/>
);
case 'system-logs':
return (
<SystemLogsPage
<SystemLogsPage
onNavigate={navigateToPage}
user={user}
/>
);
case 'log-monitoring':
return (
<LogMonitoringPage
<LogMonitoringPage
onNavigate={navigateToPage}
user={user}
/>
@@ -339,20 +339,20 @@ function App() {
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '24px', marginBottom: '16px' }}></div>
<div style={{ fontSize: '16px', color: '#718096' }}> 없는 페이지입니다.</div>
<button
onClick={() => navigateToPage('dashboard')}
style={{
background: '#4299e1',
color: 'white',
border: 'none',
borderRadius: '6px',
padding: '12px 24px',
cursor: 'pointer',
marginTop: '16px'
}}
>
대시보드로 돌아가기
</button>
<button
onClick={() => navigateToPage('dashboard')}
style={{
background: '#4299e1',
color: 'white',
border: 'none',
borderRadius: '6px',
padding: '12px 24px',
cursor: 'pointer',
marginTop: '16px'
}}
>
대시보드로 돌아가기
</button>
</div>
</div>
);
@@ -376,21 +376,21 @@ function App() {
loadProjects();
};
return (
return (
<ErrorBoundary errorContext={{ user, currentPage, pageParams }}>
{isLoading ? (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
background: '#f7fafc'
}}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '24px', marginBottom: '16px' }}>🔄</div>
<div style={{ fontSize: '16px', color: '#718096' }}>로딩 ...</div>
</div>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
background: '#f7fafc'
}}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '24px', marginBottom: '16px' }}>🔄</div>
<div style={{ fontSize: '16px', color: '#718096' }}>로딩 ...</div>
</div>
</div>
) : !isAuthenticated ? (
<SimpleLogin onLoginSuccess={handleLoginSuccess} />
) : (
@@ -422,8 +422,8 @@ function App() {
</div>
{/* 페이지 컨텐츠 */}
{renderCurrentPage()}
</div>
{renderCurrentPage()}
</div>
)}
</ErrorBoundary>
);