✅ 주요 완성 기능: - 프로젝트 생성 API (project_name 필드 포함) - 엑셀 파일 업로드 및 파싱 시스템 - 자재 DB 저장 (2837개 자재 성공 저장) - 자재 조회 및 요약 통계 API - 외래키 관계 정상 동작 (projects -> files -> materials) 📊 테스트 결과: - MP7 PIPING PROJECT Rev.2 프로젝트 생성 - 00.MP7 PIPING R.2_BOM.XLS 파일 업로드 성공 - NIPPLE, PIPE 등 자재 분류 및 재질 추출 - ASTM A106, SCH 80, 1인치 사이즈 등 정확 파싱 🛠️ 기술 스택: - FastAPI + PostgreSQL + SQLAlchemy - pandas를 활용한 엑셀 파싱 - 외래키 제약조건 적용된 정규화 DB 설계
129 lines
4.5 KiB
Python
129 lines
4.5 KiB
Python
from fastapi import FastAPI, Depends, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import text
|
|
from typing import List
|
|
from datetime import datetime
|
|
|
|
from .database import get_db, engine
|
|
from .models import Base, Project
|
|
from .schemas import ProjectCreate, ProjectResponse
|
|
from .api import files
|
|
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
app = FastAPI(
|
|
title="TK-MP-Project API",
|
|
description="BOM 시스템 개발 프로젝트 - Phase 3: 파일 처리 시스템",
|
|
version="1.0.0",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc"
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
app.include_router(files.router, prefix="/api/files", tags=["파일 관리"])
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
return {
|
|
"message": "TK-MP-Project API Server",
|
|
"version": "1.0.0 - Phase 3",
|
|
"status": "running",
|
|
"timestamp": datetime.now().isoformat(),
|
|
"new_features": [
|
|
"✅ Phase 1: 기반 시스템 구축",
|
|
"✅ Phase 2: 데이터베이스 연동",
|
|
"🔄 Phase 3: 파일 처리 시스템 개발 중"
|
|
]
|
|
}
|
|
|
|
@app.get("/health")
|
|
async def health_check(db: Session = Depends(get_db)):
|
|
try:
|
|
result = db.execute(text("SELECT 1 as test"))
|
|
test_value = result.fetchone()[0]
|
|
|
|
return {
|
|
"status": "healthy",
|
|
"database": "connected",
|
|
"test_query": test_value == 1,
|
|
"timestamp": datetime.now().isoformat(),
|
|
"phase": "Phase 3 - 파일 처리 시스템"
|
|
}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"데이터베이스 연결 실패: {str(e)}")
|
|
|
|
@app.get("/api/projects", response_model=List[ProjectResponse])
|
|
async def get_projects(db: Session = Depends(get_db)):
|
|
try:
|
|
result = db.execute(text("""
|
|
SELECT id, official_project_code, project_name, design_project_code,
|
|
is_code_matched, status, created_at, updated_at
|
|
FROM projects
|
|
ORDER BY created_at DESC
|
|
"""))
|
|
projects = result.fetchall()
|
|
|
|
return [
|
|
ProjectResponse(
|
|
id=project.id,
|
|
official_project_code=project.official_project_code,
|
|
project_name=project.project_name,
|
|
design_project_code=project.design_project_code,
|
|
is_code_matched=project.is_code_matched,
|
|
status=project.status,
|
|
created_at=project.created_at,
|
|
updated_at=project.updated_at
|
|
)
|
|
for project in projects
|
|
]
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"프로젝트 조회 실패: {str(e)}")
|
|
|
|
@app.post("/api/projects", response_model=ProjectResponse)
|
|
async def create_project(project: ProjectCreate, db: Session = Depends(get_db)):
|
|
try:
|
|
insert_query = text("""
|
|
INSERT INTO projects (official_project_code, project_name, design_project_code, is_code_matched, status, created_at)
|
|
VALUES (:official_code, :project_name, :design_code, :is_matched, :status, :created_at)
|
|
RETURNING id, official_project_code, project_name, design_project_code, is_code_matched, status, created_at, updated_at
|
|
""")
|
|
|
|
result = db.execute(insert_query, {
|
|
"official_code": project.official_project_code,
|
|
"project_name": project.project_name,
|
|
"design_code": project.design_project_code,
|
|
"is_matched": project.is_code_matched,
|
|
"status": project.status,
|
|
"created_at": datetime.now()
|
|
})
|
|
|
|
new_project = result.fetchone()
|
|
db.commit()
|
|
|
|
return ProjectResponse(
|
|
id=new_project.id,
|
|
official_project_code=new_project.official_project_code,
|
|
project_name=new_project.project_name,
|
|
design_project_code=new_project.design_project_code,
|
|
is_code_matched=new_project.is_code_matched,
|
|
status=new_project.status,
|
|
created_at=new_project.created_at,
|
|
updated_at=new_project.updated_at
|
|
)
|
|
|
|
except Exception as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=500, detail=f"프로젝트 생성 실패: {str(e)}")
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)
|