#!/usr/bin/env python3 """ TK-MP-Project 완전한 DB 스키마 생성 스크립트 백엔드 SQLAlchemy 모델을 기반으로 PostgreSQL 스키마를 자동 생성 """ import sys import os from datetime import datetime # 백엔드 모듈 경로 추가 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from sqlalchemy import create_engine, MetaData from sqlalchemy.schema import CreateTable, CreateIndex from app.models import Base from app.auth.models import User, LoginLog, UserSession, Permission, RolePermission def generate_schema_sql(): """SQLAlchemy 모델을 기반으로 완전한 PostgreSQL 스키마 생성""" # 메모리 내 SQLite 엔진 생성 (스키마 생성용) engine = create_engine('sqlite:///:memory:', echo=False) # 모든 테이블 생성 Base.metadata.create_all(engine) # PostgreSQL 방언으로 변환 from sqlalchemy.dialects import postgresql schema_lines = [] schema_lines.append("-- ================================") schema_lines.append("-- TK-MP-Project 완전한 데이터베이스 스키마") schema_lines.append(f"-- 자동 생성일: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") schema_lines.append("-- SQLAlchemy 모델 기반 자동 생성") schema_lines.append("-- ================================") schema_lines.append("") # 테이블 생성 SQL 생성 for table in Base.metadata.sorted_tables: create_table_sql = str(CreateTable(table).compile(dialect=postgresql.dialect())) # SQLite -> PostgreSQL 변환 create_table_sql = create_table_sql.replace('DATETIME', 'TIMESTAMP') create_table_sql = create_table_sql.replace('BOOLEAN', 'BOOLEAN') create_table_sql = create_table_sql.replace('TEXT', 'TEXT') create_table_sql = create_table_sql.replace('JSON', 'JSONB') schema_lines.append(f"-- {table.name} 테이블") schema_lines.append(f"CREATE TABLE IF NOT EXISTS {create_table_sql[13:]};") # "CREATE TABLE " 제거 schema_lines.append("") # 인덱스 생성 schema_lines.append("-- ================================") schema_lines.append("-- 인덱스 생성") schema_lines.append("-- ================================") schema_lines.append("") for table in Base.metadata.sorted_tables: for index in table.indexes: create_index_sql = str(CreateIndex(index).compile(dialect=postgresql.dialect())) schema_lines.append(f"CREATE INDEX IF NOT EXISTS {create_index_sql[13:]};") # "CREATE INDEX " 제거 # 필수 데이터 삽입 schema_lines.append("") schema_lines.append("-- ================================") schema_lines.append("-- 필수 기본 데이터 삽입") schema_lines.append("-- ================================") schema_lines.append("") # 기본 관리자 계정 schema_lines.append("-- 기본 관리자 계정 (비밀번호: admin123)") schema_lines.append("INSERT INTO users (username, password, name, email, role, access_level, department, position, status) VALUES") schema_lines.append("('admin', '$2b$12$ld4LDOW5mxkiRQEkXfMUIep/aIzFleQZ4yoL10ZQkUxGqnkYuhNMW', '시스템 관리자', 'admin@tkmp.com', 'admin', 'admin', 'IT', '시스템 관리자', 'active'),") schema_lines.append("('system', '$2b$12$ld4LDOW5mxkiRQEkXfMUIep/aIzFleQZ4yoL10ZQkUxGqnkYuhNMW', '시스템 계정', 'system@tkmp.com', 'system', 'system', 'IT', '시스템 계정', 'active')") schema_lines.append("ON CONFLICT (username) DO NOTHING;") schema_lines.append("") # 기본 권한 데이터 schema_lines.append("-- 기본 권한 데이터") permissions = [ ('bom.view', 'BOM 조회 권한', 'bom'), ('bom.create', 'BOM 생성 권한', 'bom'), ('bom.edit', 'BOM 수정 권한', 'bom'), ('bom.delete', 'BOM 삭제 권한', 'bom'), ('project.view', '프로젝트 조회 권한', 'project'), ('project.create', '프로젝트 생성 권한', 'project'), ('project.edit', '프로젝트 수정 권한', 'project'), ('file.upload', '파일 업로드 권한', 'file'), ('file.download', '파일 다운로드 권한', 'file'), ('user.view', '사용자 조회 권한', 'user'), ('user.create', '사용자 생성 권한', 'user'), ('system.admin', '시스템 관리 권한', 'system') ] schema_lines.append("INSERT INTO permissions (permission_name, description, module) VALUES") for i, (name, desc, module) in enumerate(permissions): comma = "," if i < len(permissions) - 1 else "" schema_lines.append(f"('{name}', '{desc}', '{module}'){comma}") schema_lines.append("ON CONFLICT (permission_name) DO NOTHING;") schema_lines.append("") # 완료 메시지 schema_lines.append("-- ================================") schema_lines.append("-- 스키마 생성 완료") schema_lines.append("-- ================================") schema_lines.append("") schema_lines.append("DO $$") schema_lines.append("BEGIN") schema_lines.append(" RAISE NOTICE '✅ TK-MP-Project 완전한 데이터베이스 스키마가 성공적으로 생성되었습니다!';") schema_lines.append(" RAISE NOTICE '👤 기본 계정: admin/admin123, system/admin123';") schema_lines.append(" RAISE NOTICE '🔐 권한 시스템: 모듈별 세분화된 권한 적용';") schema_lines.append(" RAISE NOTICE '📊 자동 생성: SQLAlchemy 모델 기반 완전 동기화';") schema_lines.append("END $$;") return '\n'.join(schema_lines) def main(): """메인 실행 함수""" try: print("🔄 SQLAlchemy 모델 분석 중...") schema_sql = generate_schema_sql() # 스키마 파일 저장 output_file = os.path.join(os.path.dirname(__file__), '..', '..', 'database', 'init', '00_auto_generated_schema.sql') os.makedirs(os.path.dirname(output_file), exist_ok=True) with open(output_file, 'w', encoding='utf-8') as f: f.write(schema_sql) print(f"✅ 완전한 DB 스키마가 생성되었습니다: {output_file}") print("📋 포함된 내용:") print(" - 모든 SQLAlchemy 모델 기반 테이블") print(" - 필수 인덱스") print(" - 기본 관리자 계정") print(" - 기본 권한 데이터") print("🚀 배포 시 이 파일이 자동으로 실행됩니다.") except Exception as e: print(f"❌ 스키마 생성 실패: {str(e)}") sys.exit(1) if __name__ == "__main__": main()