프로젝트 생성 및 관리 기능 완성
Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled

백엔드:
- POST /dashboard/projects 엔드포인트 추가
- 프로젝트 생성 기능 구현
- 중복 코드 검사
- GET /dashboard/projects 컬럼명 수정 (실제 DB 스키마에 맞춤)
- PATCH /dashboard/projects/{id} 컬럼명 수정

프론트엔드:
- 메인 대시보드에 프로젝트 관리 섹션 추가
- ' 새 프로젝트' 버튼으로 생성 폼 표시/숨김
- '✏️ 이름 수정' 버튼으로 프로젝트 이름 수정
- 프로젝트 생성 폼:
  - 프로젝트 코드 (필수)
  - 프로젝트 이름 (필수)
  - 고객사명 (선택)
- 실시간 프로젝트 목록 갱신
- API 연동 완료
This commit is contained in:
Hyungi Ahn
2025-10-14 07:14:55 +09:00
parent 003983872c
commit 6d8bb468c3
2 changed files with 267 additions and 24 deletions

View File

@@ -427,6 +427,78 @@ async def get_quick_actions(
raise HTTPException(status_code=500, detail=f"빠른 작업 조회 실패: {str(e)}")
@router.post("/projects")
async def create_project(
official_project_code: str = Query(..., description="프로젝트 코드"),
project_name: str = Query(..., description="프로젝트 이름"),
client_name: str = Query(None, description="고객사명"),
current_user: dict = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
새 프로젝트 생성
Args:
official_project_code: 프로젝트 코드 (예: J24-001)
project_name: 프로젝트 이름
client_name: 고객사명 (선택)
Returns:
dict: 생성된 프로젝트 정보
"""
try:
# 중복 확인
check_query = text("SELECT id FROM projects WHERE official_project_code = :code")
existing = db.execute(check_query, {"code": official_project_code}).fetchone()
if existing:
raise HTTPException(status_code=400, detail="이미 존재하는 프로젝트 코드입니다")
# 프로젝트 생성
insert_query = text("""
INSERT INTO projects (official_project_code, project_name, client_name, status)
VALUES (:code, :name, :client, 'active')
RETURNING *
""")
new_project = db.execute(insert_query, {
"code": official_project_code,
"name": project_name,
"client": client_name
}).fetchone()
db.commit()
# 활동 로그 기록
ActivityLogger.log_activity(
db=db,
user_id=current_user.get('user_id'),
action="CREATE_PROJECT",
target_type="PROJECT",
target_id=new_project.id,
details=f"프로젝트 생성: {official_project_code} - {project_name}"
)
return {
"success": True,
"message": "프로젝트가 생성되었습니다",
"project": {
"id": new_project.id,
"official_project_code": new_project.official_project_code,
"project_name": new_project.project_name,
"client_name": new_project.client_name,
"status": new_project.status
}
}
except HTTPException:
raise
except Exception as e:
db.rollback()
logger.error(f"프로젝트 생성 실패: {str(e)}")
raise HTTPException(status_code=500, detail=f"프로젝트 생성 실패: {str(e)}")
@router.get("/projects")
async def get_projects(
current_user: dict = Depends(get_current_user),
@@ -442,10 +514,12 @@ async def get_projects(
query = text("""
SELECT
id,
job_no,
official_project_code,
job_name,
project_type,
project_name,
client_name,
design_project_code,
design_project_name,
status,
created_at,
updated_at
FROM projects
@@ -458,11 +532,13 @@ async def get_projects(
for row in results:
projects.append({
"id": row.id,
"job_no": row.job_no,
"official_project_code": row.official_project_code,
"job_name": row.job_name,
"project_name": row.job_name, # 호환성을 위해 추가
"project_type": row.project_type,
"project_name": row.project_name,
"job_name": row.project_name, # 호환성을 위해 추가
"client_name": row.client_name,
"design_project_code": row.design_project_code,
"design_project_name": row.design_project_name,
"status": row.status,
"created_at": row.created_at.isoformat() if row.created_at else None,
"updated_at": row.updated_at.isoformat() if row.updated_at else None
})
@@ -506,14 +582,14 @@ async def update_project_name(
# 프로젝트 이름 업데이트
update_query = text("""
UPDATE projects
SET job_name = :job_name,
SET project_name = :project_name,
updated_at = CURRENT_TIMESTAMP
WHERE id = :project_id
RETURNING *
""")
updated = db.execute(update_query, {
"job_name": job_name,
"project_name": job_name,
"project_id": project_id
}).fetchone()
@@ -534,9 +610,9 @@ async def update_project_name(
"message": "프로젝트 이름이 수정되었습니다",
"project": {
"id": updated.id,
"job_no": updated.job_no,
"job_name": updated.job_name,
"official_project_code": updated.official_project_code
"official_project_code": updated.official_project_code,
"project_name": updated.project_name,
"job_name": updated.project_name # 호환성
}
}