- 기존 4단계 권한을 admin/user 2단계로 단순화 - 페이지별 세부 접근 권한 관리 시스템 추가 - 부적합 조회 시 일반 사용자는 본인 등록 건만 조회 가능하도록 제한 - 관리자 전용 전체 부적합 조회 API 추가 (/api/issues/admin/all) Backend Changes: - models.py: UserPagePermission 모델 추가, UserRole 단순화 - page_permissions.py: 페이지 권한 관리 API 라우터 추가 - auth.py: 사용자 목록 조회 및 비밀번호 초기화 API 추가 - issues.py: 권한별 부적합 조회 제한 로직 구현 - 마이그레이션: 010~012 권한 시스템 관련 DB 스키마 변경
133 lines
5.0 KiB
Python
133 lines
5.0 KiB
Python
from sqlalchemy import Column, Integer, BigInteger, String, DateTime, Float, Boolean, Text, ForeignKey, Enum, Index
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import relationship
|
|
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" # 일반 사용자
|
|
|
|
class IssueStatus(str, enum.Enum):
|
|
new = "new"
|
|
progress = "progress"
|
|
complete = "complete"
|
|
|
|
class IssueCategory(str, enum.Enum):
|
|
material_missing = "material_missing"
|
|
design_error = "design_error" # 설계미스 (기존 dimension_defect 대체)
|
|
incoming_defect = "incoming_defect"
|
|
inspection_miss = "inspection_miss" # 검사미스 (신규 추가)
|
|
etc = "etc" # 기타
|
|
|
|
class User(Base):
|
|
__tablename__ = "users"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
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)
|
|
is_active = Column(Boolean, default=True)
|
|
created_at = Column(DateTime, default=get_kst_now)
|
|
|
|
# Relationships
|
|
issues = relationship("Issue", back_populates="reporter")
|
|
daily_works = relationship("DailyWork", back_populates="created_by")
|
|
projects = relationship("Project", back_populates="created_by")
|
|
page_permissions = relationship("UserPagePermission", back_populates="user", foreign_keys="UserPagePermission.user_id")
|
|
|
|
class UserPagePermission(Base):
|
|
__tablename__ = "user_page_permissions"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
|
page_name = Column(String(50), nullable=False)
|
|
can_access = Column(Boolean, default=False)
|
|
granted_by_id = Column(Integer, ForeignKey("users.id"))
|
|
granted_at = Column(DateTime, default=get_kst_now)
|
|
notes = Column(Text)
|
|
|
|
# Relationships
|
|
user = relationship("User", back_populates="page_permissions", foreign_keys=[user_id])
|
|
granted_by = relationship("User", foreign_keys=[granted_by_id], post_update=True)
|
|
|
|
# Unique constraint
|
|
__table_args__ = (
|
|
Index('idx_user_page_permissions_user_id', 'user_id'),
|
|
Index('idx_user_page_permissions_page_name', 'page_name'),
|
|
)
|
|
|
|
class Issue(Base):
|
|
__tablename__ = "issues"
|
|
|
|
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)
|
|
reporter_id = Column(Integer, ForeignKey("users.id"))
|
|
project_id = Column(BigInteger, ForeignKey("projects.id"))
|
|
report_date = Column(DateTime, default=get_kst_now)
|
|
work_hours = Column(Float, default=0)
|
|
detail_notes = Column(Text)
|
|
|
|
# Relationships
|
|
reporter = relationship("User", back_populates="issues")
|
|
project = relationship("Project", back_populates="issues")
|
|
|
|
class Project(Base):
|
|
__tablename__ = "projects"
|
|
|
|
id = Column(BigInteger, primary_key=True, index=True)
|
|
job_no = Column(String, unique=True, nullable=False, index=True)
|
|
project_name = Column(String, nullable=False)
|
|
created_by_id = Column(Integer, ForeignKey("users.id"))
|
|
created_at = Column(DateTime, default=get_kst_now)
|
|
is_active = Column(Boolean, default=True)
|
|
|
|
# Relationships
|
|
created_by = relationship("User", back_populates="projects")
|
|
issues = relationship("Issue", back_populates="project")
|
|
|
|
class DailyWork(Base):
|
|
__tablename__ = "daily_works"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
date = Column(DateTime, nullable=False, index=True)
|
|
worker_count = Column(Integer, nullable=False)
|
|
regular_hours = Column(Float, nullable=False)
|
|
overtime_workers = Column(Integer, default=0)
|
|
overtime_hours = Column(Float, default=0)
|
|
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=get_kst_now)
|
|
|
|
# Relationships
|
|
created_by = relationship("User", back_populates="daily_works")
|
|
|
|
class ProjectDailyWork(Base):
|
|
__tablename__ = "project_daily_works"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
date = Column(DateTime, nullable=False, index=True)
|
|
project_id = Column(BigInteger, ForeignKey("projects.id"), nullable=False)
|
|
hours = Column(Float, nullable=False)
|
|
created_by_id = Column(Integer, ForeignKey("users.id"))
|
|
created_at = Column(DateTime, default=get_kst_now)
|
|
|
|
# Relationships
|
|
project = relationship("Project")
|
|
created_by = relationship("User")
|