From ffe4f0f969141f20e0474434eebad299ee663cad Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Tue, 15 Jul 2025 12:45:35 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20jobs=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8D=94=EB=AF=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PostgreSQL jobs 테이블 스키마 생성 - 더미 프로젝트 데이터 2개 추가 (J24-001, J24-002) - 엔지니어링 업계 구조 반영 (엔드유저-클라이언트-EPC) - 가상환경 경로 이슈 해결 방법 문서화 --- backend/scripts/01_create_jobs_table.sql | 36 ++++++++ backend/scripts/02_modify_files_table.sql | 19 ++++ backend/scripts/03_insert_dummy_data.py | 108 ++++++++++++++++++++++ backend/scripts/create_jobs.sql | 19 ++++ backend/scripts/insert_dummy_jobs.py | 81 ++++++++++++++++ backend/scripts/setup_database.py | 73 +++++++++++++++ 6 files changed, 336 insertions(+) create mode 100644 backend/scripts/01_create_jobs_table.sql create mode 100644 backend/scripts/02_modify_files_table.sql create mode 100644 backend/scripts/03_insert_dummy_data.py create mode 100644 backend/scripts/create_jobs.sql create mode 100644 backend/scripts/insert_dummy_jobs.py create mode 100644 backend/scripts/setup_database.py diff --git a/backend/scripts/01_create_jobs_table.sql b/backend/scripts/01_create_jobs_table.sql new file mode 100644 index 0000000..cffba87 --- /dev/null +++ b/backend/scripts/01_create_jobs_table.sql @@ -0,0 +1,36 @@ +-- jobs 테이블 생성 +CREATE TABLE IF NOT EXISTS jobs ( + -- 기본 정보 + job_no VARCHAR(50) PRIMARY KEY, + job_name VARCHAR(200) NOT NULL, + + -- 계약 관계 (핵심) + client_name VARCHAR(100) NOT NULL, + + -- 프로젝트 정보 + end_user VARCHAR(100), + epc_company VARCHAR(100), + project_site VARCHAR(200), + + -- 상업 정보 + contract_date DATE, + delivery_date DATE, + delivery_terms VARCHAR(100), + + -- 상태 관리 (핵심) + status VARCHAR(20) DEFAULT '진행중', + delivery_completed_date DATE, + project_closed_date DATE, + + -- 관리 정보 + description TEXT, + created_by VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + is_active BOOLEAN DEFAULT true +); + +-- 인덱스 생성 +CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status); +CREATE INDEX IF NOT EXISTS idx_jobs_client ON jobs(client_name); +CREATE INDEX IF NOT EXISTS idx_jobs_created_at ON jobs(created_at); diff --git a/backend/scripts/02_modify_files_table.sql b/backend/scripts/02_modify_files_table.sql new file mode 100644 index 0000000..8c6edfa --- /dev/null +++ b/backend/scripts/02_modify_files_table.sql @@ -0,0 +1,19 @@ +-- files 테이블에 job_no 컬럼 추가 및 project_id 대체 + +-- 새 컬럼 추가 +ALTER TABLE files ADD COLUMN IF NOT EXISTS job_no VARCHAR(50); + +-- 외래키 제약조건 추가 (MySQL/PostgreSQL 문법) +-- MySQL의 경우: +-- ALTER TABLE files ADD CONSTRAINT fk_files_job_no FOREIGN KEY (job_no) REFERENCES jobs(job_no); + +-- PostgreSQL의 경우: +-- ALTER TABLE files ADD CONSTRAINT fk_files_job_no FOREIGN KEY (job_no) REFERENCES jobs(job_no); + +-- SQLite의 경우는 외래키 제약조건을 나중에 추가하기 어려우므로 생략 + +-- 인덱스 생성 +CREATE INDEX IF NOT EXISTS idx_files_job_no ON files(job_no); + +-- 기존 project_id 컬럼은 일단 유지 (호환성을 위해) +-- 나중에 완전 이전 후 DROP 할 예정 diff --git a/backend/scripts/03_insert_dummy_data.py b/backend/scripts/03_insert_dummy_data.py new file mode 100644 index 0000000..48220e5 --- /dev/null +++ b/backend/scripts/03_insert_dummy_data.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +""" +더미 프로젝트 데이터 생성 스크립트 +""" + +import sys +import os +from datetime import datetime, date +from sqlalchemy import create_engine, text + +# 프로젝트 루트를 Python path에 추가 +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +def create_dummy_jobs(): + """더미 Job 데이터 생성""" + + # 간단한 SQLite 연결 (실제 DB 설정에 맞게 수정) + try: + # 실제 프로젝트의 database.py 설정 사용 + from app.database import engine + print("✅ 데이터베이스 연결 성공") + except ImportError: + # 직접 연결 (개발용) + DATABASE_URL = "sqlite:///./test.db" # 실제 DB URL로 변경 + engine = create_engine(DATABASE_URL) + print("⚠️ 직접 데이터베이스 연결") + + # 더미 데이터 정의 + dummy_jobs = [ + { + 'job_no': 'J24-001', + 'job_name': '울산 SK에너지 정유시설 증설 배관공사', + 'client_name': '삼성엔지니어링', + 'end_user': 'SK에너지', + 'epc_company': '삼성엔지니어링', + 'project_site': '울산광역시 온산공단 SK에너지 정유공장', + 'contract_date': '2024-03-15', + 'delivery_date': '2024-08-30', + 'delivery_terms': 'FOB 울산항', + 'status': '진행중', + 'description': '정유시설 증설을 위한 배관 자재 공급 프로젝트. 고온고압 배관 및 특수 밸브 포함.', + 'created_by': 'admin' + }, + { + 'job_no': 'J24-002', + 'job_name': '포스코 광양 제철소 배관 정비공사', + 'client_name': '포스코', + 'end_user': '포스코', + 'epc_company': None, + 'project_site': '전남 광양시 포스코 광양제철소', + 'contract_date': '2024-04-02', + 'delivery_date': '2024-07-15', + 'delivery_terms': 'DDP 광양제철소 현장', + 'status': '진행중', + 'description': '제철소 정기 정비를 위한 배관 부품 교체. 내열성 특수강 배관 포함.', + 'created_by': 'admin' + } + ] + + try: + with engine.connect() as conn: + # 기존 더미 데이터 삭제 (개발용) + print("🧹 기존 더미 데이터 정리...") + conn.execute(text("DELETE FROM jobs WHERE job_no IN ('J24-001', 'J24-002')")) + + # 새 더미 데이터 삽입 + print("📝 더미 데이터 삽입 중...") + + for job in dummy_jobs: + insert_query = text(""" + INSERT INTO jobs ( + job_no, job_name, client_name, end_user, epc_company, + project_site, contract_date, delivery_date, delivery_terms, + status, description, created_by, is_active + ) VALUES ( + :job_no, :job_name, :client_name, :end_user, :epc_company, + :project_site, :contract_date, :delivery_date, :delivery_terms, + :status, :description, :created_by, :is_active + ) + """) + + conn.execute(insert_query, {**job, 'is_active': True}) + print(f"✅ {job['job_no']}: {job['job_name']}") + + # 커밋 + conn.commit() + + # 결과 확인 + result = conn.execute(text(""" + SELECT job_no, job_name, client_name, status + FROM jobs + WHERE job_no IN ('J24-001', 'J24-002') + """)) + jobs = result.fetchall() + + print(f"\n🎉 총 {len(jobs)}개 더미 Job 생성 완료!") + print("\n📋 생성된 더미 데이터:") + for job in jobs: + print(f" • {job[0]}: {job[1]} ({job[2]}) - {job[3]}") + + return True + + except Exception as e: + print(f"❌ 더미 데이터 생성 실패: {e}") + return False + +if __name__ == "__main__": + create_dummy_jobs() diff --git a/backend/scripts/create_jobs.sql b/backend/scripts/create_jobs.sql new file mode 100644 index 0000000..8e2411c --- /dev/null +++ b/backend/scripts/create_jobs.sql @@ -0,0 +1,19 @@ +CREATE TABLE IF NOT EXISTS jobs ( + job_no VARCHAR(50) PRIMARY KEY, + job_name VARCHAR(200) NOT NULL, + client_name VARCHAR(100) NOT NULL, + end_user VARCHAR(100), + epc_company VARCHAR(100), + project_site VARCHAR(200), + contract_date DATE, + delivery_date DATE, + delivery_terms VARCHAR(100), + status VARCHAR(20) DEFAULT '진행중', + delivery_completed_date DATE, + project_closed_date DATE, + description TEXT, + created_by VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + is_active BOOLEAN DEFAULT true +); diff --git a/backend/scripts/insert_dummy_jobs.py b/backend/scripts/insert_dummy_jobs.py new file mode 100644 index 0000000..72a8e4f --- /dev/null +++ b/backend/scripts/insert_dummy_jobs.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +import sys +import os +from datetime import datetime, date + +# 프로젝트 루트를 Python path에 추가 +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +try: + from app.database import engine + from sqlalchemy import text + print("✅ 데이터베이스 연결 성공") +except ImportError as e: + print(f"❌ 임포트 실패: {e}") + sys.exit(1) + +def insert_dummy_data(): + dummy_jobs = [ + { + 'job_no': 'J24-001', + 'job_name': '울산 SK에너지 정유시설 증설 배관공사', + 'client_name': '삼성엔지니어링', + 'end_user': 'SK에너지', + 'epc_company': '삼성엔지니어링', + 'project_site': '울산광역시 온산공단', + 'contract_date': '2024-03-15', + 'delivery_date': '2024-08-30', + 'delivery_terms': 'FOB 울산항', + 'description': '정유시설 증설을 위한 배관 자재 공급', + 'created_by': 'admin' + }, + { + 'job_no': 'J24-002', + 'job_name': '포스코 광양 제철소 배관 정비공사', + 'client_name': '포스코', + 'end_user': '포스코', + 'epc_company': None, + 'project_site': '전남 광양시 포스코 제철소', + 'contract_date': '2024-04-02', + 'delivery_date': '2024-07-15', + 'delivery_terms': 'DDP 광양제철소', + 'description': '제철소 정기 정비용 배관 부품', + 'created_by': 'admin' + } + ] + + try: + with engine.connect() as conn: + # 기존 더미 데이터 삭제 + conn.execute(text("DELETE FROM jobs WHERE job_no IN ('J24-001', 'J24-002')")) + + # 새 데이터 삽입 + for job in dummy_jobs: + query = text(""" + INSERT INTO jobs ( + job_no, job_name, client_name, end_user, epc_company, + project_site, contract_date, delivery_date, delivery_terms, + description, created_by, is_active + ) VALUES ( + :job_no, :job_name, :client_name, :end_user, :epc_company, + :project_site, :contract_date, :delivery_date, :delivery_terms, + :description, :created_by, :is_active + ) + """) + + conn.execute(query, {**job, 'is_active': True}) + print(f"✅ {job['job_no']}: {job['job_name']}") + + conn.commit() + print(f"\n🎉 {len(dummy_jobs)}개 더미 Job 생성 완료!") + + # 확인 + result = conn.execute(text("SELECT job_no, job_name, client_name FROM jobs")) + for row in result: + print(f" • {row[0]}: {row[1]} ({row[2]})") + + except Exception as e: + print(f"❌ 오류: {e}") + +if __name__ == "__main__": + insert_dummy_data() diff --git a/backend/scripts/setup_database.py b/backend/scripts/setup_database.py new file mode 100644 index 0000000..fba0ca6 --- /dev/null +++ b/backend/scripts/setup_database.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +전체 데이터베이스 설정 및 더미 데이터 생성 +""" + +import sys +import os +from sqlalchemy import create_engine, text + +# 프로젝트 루트를 Python path에 추가 +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +def setup_database(): + """데이터베이스 전체 설정""" + + try: + from app.database import engine + print("✅ 기존 데이터베이스 연결 사용") + except ImportError: + # 개발용 직접 연결 + DATABASE_URL = "sqlite:///./test.db" + engine = create_engine(DATABASE_URL) + print("⚠️ 개발용 SQLite 연결") + + try: + with engine.connect() as conn: + print("🏗️ 1단계: jobs 테이블 생성...") + + # jobs 테이블 생성 SQL 실행 + with open('scripts/01_create_jobs_table.sql', 'r', encoding='utf-8') as f: + sql_commands = f.read().split(';') + for command in sql_commands: + command = command.strip() + if command: + conn.execute(text(command)) + + print("✅ jobs 테이블 생성 완료") + + print("🔧 2단계: files 테이블 수정...") + + # files 테이블 수정 (선택적) + try: + with open('scripts/02_modify_files_table.sql', 'r', encoding='utf-8') as f: + sql_commands = f.read().split(';') + for command in sql_commands: + command = command.strip() + if command and not command.startswith('--'): + conn.execute(text(command)) + print("✅ files 테이블 수정 완료") + except Exception as e: + print(f"⚠️ files 테이블 수정 건너뜀: {e}") + + # 커밋 + conn.commit() + + print("🎯 3단계: 더미 데이터 생성...") + # 더미 데이터 스크립트 실행 + exec(open('scripts/03_insert_dummy_data.py').read()) + + print("\n🎉 전체 설정 완료!") + print("\n📋 다음 단계:") + print(" 1. API 서버 실행") + print(" 2. GET /jobs 엔드포인트 테스트") + print(" 3. Job 선택 후 BOM 파일 업로드") + + return True + + except Exception as e: + print(f"❌ 데이터베이스 설정 실패: {e}") + return False + +if __name__ == "__main__": + setup_database()