feat: 프로젝트별 순번 자동 할당 시스템 구현
🎯 핵심 개선사항: - 수신함에서 진행중/완료로 상태 변경시 project_sequence_no 자동 할당 - 프로젝트별로 1부터 시작하는 깔끔한 순번 체계 🔧 백엔드 수정: - inbox.py: update_issue_status에 자동 할당 로직 추가 - generate_project_sequence_no() DB 함수 활용 - 진행중/완료 상태 변경시에만 실행 📁 DB 마이그레이션: - 017_fix_project_sequence_no.sql 생성 - 기존 데이터 보정 (누락된 순번 0개 확인) - migration_log 테이블 구조에 맞게 로그 기록 📋 문서화: - DB_CHANGES_LOG.md 생성 및 업데이트 - 배포 가이드, 검증 방법, 주의사항 명시 - Docker 환경 기준 실행 방법 제공 ✅ 실행 완료 상태: - 마이그레이션 성공 (2025-10-26 11:15:44+09:00) - 백엔드 서비스 재시작 완료 - 모든 검증 항목 통과 Expected Result: 🎯 현황판에서 프로젝트별 No.1, No.2, No.3... 표시 🎯 6개월 후에도 각 프로젝트 내에서 작은 번호 유지 🎯 전체 통합 번호 대신 프로젝트별 깔끔한 순번 체계
This commit is contained in:
156
DB_CHANGES_LOG.md
Normal file
156
DB_CHANGES_LOG.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# 🗄️ DB 변경사항 로그
|
||||
|
||||
> **중요**: 배포 시 반드시 이 문서를 확인하여 DB 마이그레이션을 순서대로 실행하세요.
|
||||
|
||||
## 📋 변경사항 목록
|
||||
|
||||
### 2025.10.26 - 프로젝트별 순번 자동 할당 개선
|
||||
|
||||
**🎯 목적**: 수신함에서 진행 중/완료로 상태 변경 시 프로젝트별 순번이 자동 할당되도록 개선
|
||||
|
||||
#### 📁 파일 변경사항
|
||||
|
||||
**1. 백엔드 로직 수정**
|
||||
- **파일**: `backend/routers/inbox.py`
|
||||
- **변경내용**: `update_issue_status` 함수에 `project_sequence_no` 자동 할당 로직 추가
|
||||
- **코드**:
|
||||
```python
|
||||
# 진행 중 또는 완료 상태로 변경 시 프로젝트별 순번 자동 할당
|
||||
if status_request.review_status in [ReviewStatus.in_progress, ReviewStatus.completed]:
|
||||
if not issue.project_sequence_no:
|
||||
from sqlalchemy import text
|
||||
result = db.execute(
|
||||
text("SELECT generate_project_sequence_no(:project_id)"),
|
||||
{"project_id": issue.project_id}
|
||||
)
|
||||
issue.project_sequence_no = result.scalar()
|
||||
```
|
||||
|
||||
**2. 데이터 보정 마이그레이션**
|
||||
- **파일**: `backend/migrations/017_fix_project_sequence_no.sql`
|
||||
- **목적**: 기존에 진행 중/완료 상태인데 `project_sequence_no`가 누락된 데이터 보정
|
||||
|
||||
#### 🚀 배포 시 실행 순서
|
||||
|
||||
```bash
|
||||
# 1. 백엔드 코드 배포
|
||||
git pull origin master
|
||||
|
||||
# 2. DB 마이그레이션 실행 (Docker 환경)
|
||||
docker-compose exec backend python -c "
|
||||
import psycopg2
|
||||
import os
|
||||
|
||||
database_url = os.getenv('DATABASE_URL', 'postgresql://postgres:password@db:5432/mproject')
|
||||
conn = psycopg2.connect(database_url)
|
||||
cur = conn.cursor()
|
||||
|
||||
with open('migrations/017_fix_project_sequence_no.sql', 'r', encoding='utf-8') as f:
|
||||
cur.execute(f.read())
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print('✅ 마이그레이션 완료')
|
||||
"
|
||||
|
||||
# 3. 서비스 재시작
|
||||
docker-compose restart backend
|
||||
```
|
||||
|
||||
#### 🔍 검증 방법
|
||||
|
||||
**1. DB에서 직접 확인**:
|
||||
```sql
|
||||
-- 관리 중인 이슈 중 순번이 누락된 것이 있는지 확인
|
||||
SELECT COUNT(*) as missing_count
|
||||
FROM issues
|
||||
WHERE review_status IN ('in_progress', 'completed')
|
||||
AND project_sequence_no IS NULL;
|
||||
-- 결과: 0이어야 함
|
||||
|
||||
-- 프로젝트별 순번이 올바르게 할당되었는지 확인
|
||||
SELECT project_id, COUNT(*) as total_issues,
|
||||
MIN(project_sequence_no) as min_no,
|
||||
MAX(project_sequence_no) as max_no
|
||||
FROM issues
|
||||
WHERE review_status IN ('in_progress', 'completed')
|
||||
GROUP BY project_id
|
||||
ORDER BY project_id;
|
||||
-- 결과: 각 프로젝트별로 1부터 연속된 번호가 할당되어야 함
|
||||
```
|
||||
|
||||
**2. 프론트엔드에서 확인**:
|
||||
- 수신함에서 새로운 이슈를 "진행 중"으로 변경
|
||||
- 현황판에서 "No.1, No.2..." 형태로 프로젝트별 순번이 표시되는지 확인
|
||||
|
||||
#### ⚠️ 주의사항
|
||||
|
||||
1. **마이그레이션 실행 전 백업**: 중요한 데이터이므로 실행 전 DB 백업 권장
|
||||
2. **순서 준수**: 반드시 `016_add_management_fields.sql`이 먼저 실행된 상태여야 함
|
||||
3. **Docker 환경**: 마이그레이션은 Docker 컨테이너 내에서 실행해야 함
|
||||
4. **migration_log 테이블 구조**:
|
||||
- 컬럼명: `migration_file` (migration_name 아님)
|
||||
- 필수 컬럼: `migration_file`, `executed_at`, `status`, `notes`
|
||||
5. **롤백 방법**: 문제 발생 시 `project_sequence_no` 컬럼을 NULL로 설정 후 재실행
|
||||
|
||||
#### 📊 예상 결과
|
||||
|
||||
**Before**:
|
||||
```
|
||||
현황판: No. (빈값)
|
||||
프로젝트 A: 이슈들이 전체 통합 번호로 표시 (No.2, No.5, No.8...)
|
||||
```
|
||||
|
||||
**After**:
|
||||
```
|
||||
현황판: No.1, No.2, No.3...
|
||||
프로젝트 A: No.1, No.2, No.3
|
||||
프로젝트 B: No.1, No.2, No.3
|
||||
각 프로젝트별로 1부터 시작하는 깔끔한 순번
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 이전 변경사항
|
||||
|
||||
### 2025.10.25 - 관리함 필드 추가
|
||||
- **파일**: `backend/migrations/016_add_management_fields.sql`
|
||||
- **내용**: 관리함에서 사용할 추가 필드들 및 `generate_project_sequence_no()` 함수 생성
|
||||
|
||||
### 2025.10.24 - 사용자 부서 정보 추가
|
||||
- **파일**: `backend/migrations/015_add_user_department.sql`
|
||||
- **내용**: 사용자 테이블에 부서 정보 컬럼 추가
|
||||
|
||||
---
|
||||
|
||||
## 🔧 마이그레이션 실행 도구
|
||||
|
||||
**자동 마이그레이션 스크립트** (추후 개발 예정):
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# run_migrations.sh
|
||||
# 모든 마이그레이션을 순서대로 실행하는 스크립트
|
||||
```
|
||||
|
||||
**마이그레이션 상태 확인**:
|
||||
```sql
|
||||
-- 최근 실행된 마이그레이션 확인
|
||||
SELECT migration_file, executed_at, status, notes
|
||||
FROM migration_log
|
||||
ORDER BY executed_at DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 특정 마이그레이션 확인
|
||||
SELECT * FROM migration_log
|
||||
WHERE migration_file = '017_fix_project_sequence_no.sql';
|
||||
```
|
||||
|
||||
#### 📋 실행 완료 상태 (2025.10.26)
|
||||
|
||||
✅ **마이그레이션 성공적으로 완료됨**
|
||||
- **실행 시간**: 2025-10-26 11:15:44+09:00
|
||||
- **상태**: SUCCESS
|
||||
- **확인사항**:
|
||||
- `generate_project_sequence_no()` 함수 존재 ✅
|
||||
- `issues.project_sequence_no` 컬럼 존재 ✅
|
||||
- 순번이 누락된 관리 중인 이슈: 0개 ✅
|
||||
- 백엔드 서비스 재시작 완료 ✅
|
||||
87
backend/migrations/017_fix_project_sequence_no.sql
Normal file
87
backend/migrations/017_fix_project_sequence_no.sql
Normal file
@@ -0,0 +1,87 @@
|
||||
-- 프로젝트별 순번(project_sequence_no) 자동 할당 개선
|
||||
-- 수신함에서 진행 중/완료로 상태 변경 시 프로젝트별 순번이 자동 할당되도록 개선
|
||||
|
||||
DO $migration$
|
||||
DECLARE
|
||||
issue_record RECORD;
|
||||
seq_no INTEGER;
|
||||
updated_count INTEGER := 0;
|
||||
BEGIN
|
||||
RAISE NOTICE '=== 프로젝트별 순번 자동 할당 개선 마이그레이션 시작 ===';
|
||||
|
||||
-- 1. generate_project_sequence_no 함수가 존재하는지 확인
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'generate_project_sequence_no') THEN
|
||||
RAISE EXCEPTION '❌ generate_project_sequence_no 함수가 존재하지 않습니다. 016_add_management_fields.sql을 먼저 실행하세요.';
|
||||
END IF;
|
||||
|
||||
-- 2. 진행 중 또는 완료 상태인데 project_sequence_no가 NULL인 이슈들 찾기
|
||||
RAISE NOTICE '🔍 project_sequence_no가 누락된 이슈들을 찾는 중...';
|
||||
|
||||
FOR issue_record IN
|
||||
SELECT id, project_id, review_status
|
||||
FROM issues
|
||||
WHERE review_status IN ('in_progress', 'completed')
|
||||
AND project_sequence_no IS NULL
|
||||
ORDER BY project_id, reviewed_at NULLS LAST, report_date
|
||||
LOOP
|
||||
-- 프로젝트별 순번 생성
|
||||
SELECT generate_project_sequence_no(issue_record.project_id) INTO seq_no;
|
||||
|
||||
-- 순번 할당
|
||||
UPDATE issues
|
||||
SET project_sequence_no = seq_no
|
||||
WHERE id = issue_record.id;
|
||||
|
||||
updated_count := updated_count + 1;
|
||||
|
||||
RAISE NOTICE '✅ 이슈 ID: %, 프로젝트 ID: %, 할당된 순번: %',
|
||||
issue_record.id, issue_record.project_id, seq_no;
|
||||
END LOOP;
|
||||
|
||||
-- 3. 결과 요약
|
||||
RAISE NOTICE '=== 마이그레이션 완료 ===';
|
||||
RAISE NOTICE '📊 총 %개의 이슈에 프로젝트별 순번이 할당되었습니다.', updated_count;
|
||||
|
||||
-- 4. 검증
|
||||
DECLARE
|
||||
missing_count INTEGER;
|
||||
total_managed_count INTEGER;
|
||||
BEGIN
|
||||
-- 관리 중인 이슈 중 순번이 없는 것들 확인
|
||||
SELECT COUNT(*) INTO missing_count
|
||||
FROM issues
|
||||
WHERE review_status IN ('in_progress', 'completed')
|
||||
AND project_sequence_no IS NULL;
|
||||
|
||||
-- 전체 관리 중인 이슈 수
|
||||
SELECT COUNT(*) INTO total_managed_count
|
||||
FROM issues
|
||||
WHERE review_status IN ('in_progress', 'completed');
|
||||
|
||||
RAISE NOTICE '=== 검증 결과 ===';
|
||||
RAISE NOTICE '전체 관리 중인 이슈: %개', total_managed_count;
|
||||
RAISE NOTICE '순번이 누락된 이슈: %개', missing_count;
|
||||
|
||||
IF missing_count > 0 THEN
|
||||
RAISE WARNING '⚠️ 여전히 %개의 이슈에 순번이 누락되어 있습니다.', missing_count;
|
||||
ELSE
|
||||
RAISE NOTICE '✅ 모든 관리 중인 이슈에 순번이 정상적으로 할당되었습니다.';
|
||||
END IF;
|
||||
END;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE EXCEPTION '❌ 마이그레이션 실행 중 오류 발생: %', SQLERRM;
|
||||
END $migration$;
|
||||
|
||||
-- 마이그레이션 로그 기록
|
||||
INSERT INTO migration_log (migration_file, executed_at, status, notes)
|
||||
VALUES (
|
||||
'017_fix_project_sequence_no.sql',
|
||||
NOW(),
|
||||
'SUCCESS',
|
||||
'프로젝트별 순번 자동 할당 개선: 수신함에서 진행중/완료로 상태 변경시 project_sequence_no 자동 할당되도록 백엔드 로직 개선 및 기존 데이터 보정'
|
||||
) ON CONFLICT (migration_file) DO UPDATE SET
|
||||
executed_at = NOW(),
|
||||
status = EXCLUDED.status,
|
||||
notes = EXCLUDED.notes;
|
||||
Binary file not shown.
@@ -261,6 +261,16 @@ async def update_issue_status(
|
||||
issue.reviewed_by_id = current_user.id
|
||||
issue.reviewed_at = datetime.now()
|
||||
|
||||
# 진행 중 또는 완료 상태로 변경 시 프로젝트별 순번 자동 할당
|
||||
if status_request.review_status in [ReviewStatus.in_progress, ReviewStatus.completed]:
|
||||
if not issue.project_sequence_no:
|
||||
from sqlalchemy import text
|
||||
result = db.execute(
|
||||
text("SELECT generate_project_sequence_no(:project_id)"),
|
||||
{"project_id": issue.project_id}
|
||||
)
|
||||
issue.project_sequence_no = result.scalar()
|
||||
|
||||
# 완료 사진 업로드 처리
|
||||
if status_request.completion_photo and status_request.review_status == ReviewStatus.completed:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user