feat: 사진 업로드 기능 개선 및 카테고리 업데이트

- 사진 2장까지 업로드 지원
- 카메라 촬영 + 갤러리 선택 분리
- 이미지 압축 및 최적화 (ImageUtils)
- iPhone .mpo 파일 JPEG 변환 지원
- 카테고리 변경: 치수불량 → 설계미스, 검사미스 추가
- KST 시간대 설정
- URL 해시 처리로 목록관리 페이지 이동 개선
- 로그인 OAuth2 form-data 형식 수정
- 업로드 속도 개선 및 프로그레스바 추가
This commit is contained in:
hyungi
2025-09-18 07:00:28 +09:00
parent f6bdb68d19
commit 44e2fb2e44
32 changed files with 988 additions and 177 deletions

View File

@@ -1,24 +1,32 @@
from sqlalchemy import Column, Integer, String, DateTime, Float, Boolean, Text, ForeignKey, Enum
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from datetime import datetime
from datetime import datetime, timezone, timedelta
import enum
# 한국 시간대 설정
KST = timezone(timedelta(hours=9))
def get_kst_now():
"""현재 한국 시간 반환"""
return datetime.now(KST)
Base = declarative_base()
class UserRole(str, enum.Enum):
ADMIN = "admin"
USER = "user"
admin = "admin"
user = "user"
class IssueStatus(str, enum.Enum):
NEW = "new"
PROGRESS = "progress"
COMPLETE = "complete"
new = "new"
progress = "progress"
complete = "complete"
class IssueCategory(str, enum.Enum):
MATERIAL_MISSING = "material_missing"
DIMENSION_DEFECT = "dimension_defect"
INCOMING_DEFECT = "incoming_defect"
material_missing = "material_missing"
design_error = "design_error" # 설계미스 (기존 dimension_defect 대체)
incoming_defect = "incoming_defect"
inspection_miss = "inspection_miss" # 검사미스 (신규 추가)
class User(Base):
__tablename__ = "users"
@@ -27,9 +35,9 @@ class User(Base):
username = Column(String, unique=True, index=True, nullable=False)
hashed_password = Column(String, nullable=False)
full_name = Column(String)
role = Column(Enum(UserRole), default=UserRole.USER)
role = Column(Enum(UserRole), default=UserRole.user)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
created_at = Column(DateTime, default=get_kst_now)
# Relationships
issues = relationship("Issue", back_populates="reporter")
@@ -40,11 +48,12 @@ class Issue(Base):
id = Column(Integer, primary_key=True, index=True)
photo_path = Column(String)
photo_path2 = Column(String) # 두 번째 사진 경로
category = Column(Enum(IssueCategory), nullable=False)
description = Column(Text, nullable=False)
status = Column(Enum(IssueStatus), default=IssueStatus.NEW)
status = Column(Enum(IssueStatus), default=IssueStatus.new)
reporter_id = Column(Integer, ForeignKey("users.id"))
report_date = Column(DateTime, default=datetime.utcnow)
report_date = Column(DateTime, default=get_kst_now)
work_hours = Column(Float, default=0)
detail_notes = Column(Text)
@@ -63,7 +72,7 @@ class DailyWork(Base):
overtime_total = Column(Float, default=0)
total_hours = Column(Float, nullable=False)
created_by_id = Column(Integer, ForeignKey("users.id"))
created_at = Column(DateTime, default=datetime.utcnow)
created_at = Column(DateTime, default=get_kst_now)
# Relationships
created_by = relationship("User", back_populates="daily_works")

View File

@@ -14,8 +14,9 @@ class IssueStatus(str, Enum):
class IssueCategory(str, Enum):
material_missing = "material_missing"
dimension_defect = "dimension_defect"
design_error = "design_error" # 설계미스 (기존 dimension_defect 대체)
incoming_defect = "incoming_defect"
inspection_miss = "inspection_miss" # 검사미스 (신규 추가)
# User schemas
class UserBase(BaseModel):
@@ -64,6 +65,7 @@ class IssueBase(BaseModel):
class IssueCreate(IssueBase):
photo: Optional[str] = None # Base64 encoded image
photo2: Optional[str] = None # Second Base64 encoded image
class IssueUpdate(BaseModel):
category: Optional[IssueCategory] = None
@@ -72,10 +74,12 @@ class IssueUpdate(BaseModel):
detail_notes: Optional[str] = None
status: Optional[IssueStatus] = None
photo: Optional[str] = None # Base64 encoded image for update
photo2: Optional[str] = None # Second Base64 encoded image for update
class Issue(IssueBase):
id: int
photo_path: Optional[str] = None
photo_path2: Optional[str] = None # 두 번째 사진 경로
status: IssueStatus
reporter_id: int
reporter: User