88 lines
3.9 KiB
Python
88 lines
3.9 KiB
Python
from sqlalchemy import Column, Integer, String, DateTime, Date, Enum, ForeignKey, Float, JSON
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy.sql import func
|
|
from database import Base
|
|
from .user import DepartmentRole
|
|
import enum
|
|
|
|
|
|
class ProjectStatus(str, enum.Enum):
|
|
PLANNING = "planning"
|
|
IN_PROGRESS = "in_progress"
|
|
ON_HOLD = "on_hold"
|
|
COMPLETED = "completed"
|
|
CANCELLED = "cancelled"
|
|
|
|
|
|
class ProjectType(str, enum.Enum):
|
|
TV = "tv"
|
|
CINEMA = "cinema"
|
|
GAME = "game"
|
|
|
|
|
|
class Project(Base):
|
|
__tablename__ = "projects"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
name = Column(String, nullable=False, index=True)
|
|
code_name = Column(String, nullable=False, unique=True, index=True) # Unique project code
|
|
client_name = Column(String, nullable=False, index=True) # Client/studio name
|
|
project_type = Column(Enum(ProjectType), nullable=False) # TV, Cinema, Game
|
|
description = Column(String)
|
|
status = Column(Enum(ProjectStatus), nullable=False, default=ProjectStatus.PLANNING)
|
|
start_date = Column(Date)
|
|
end_date = Column(Date)
|
|
|
|
# Technical specifications
|
|
frame_rate = Column(Float, nullable=True) # Frames per second (1-120 fps)
|
|
data_drive_path = Column(String, nullable=True) # Physical path for project data storage
|
|
publish_storage_path = Column(String, nullable=True) # Path for approved work delivery
|
|
delivery_image_resolution = Column(String, nullable=True) # Required image resolution
|
|
delivery_movie_specs_by_department = Column(JSON, nullable=True) # Delivery movie specs per department
|
|
|
|
# Project-specific settings
|
|
upload_data_location = Column(String, nullable=True) # Custom upload storage path
|
|
asset_task_templates = Column(JSON, nullable=True) # Default tasks per asset category
|
|
shot_task_templates = Column(JSON, nullable=True) # Default tasks for shots
|
|
enabled_asset_tasks = Column(JSON, nullable=True) # Enabled/disabled asset tasks per category
|
|
enabled_shot_tasks = Column(JSON, nullable=True) # Enabled/disabled shot tasks
|
|
|
|
# Custom task types
|
|
custom_asset_task_types = Column(JSON, nullable=True) # Custom task types for assets
|
|
custom_shot_task_types = Column(JSON, nullable=True) # Custom task types for shots
|
|
|
|
# Custom task statuses
|
|
custom_task_statuses = Column(JSON, nullable=True) # Custom task statuses for project
|
|
|
|
# Project thumbnail
|
|
thumbnail_path = Column(String, nullable=True) # Path to project thumbnail image
|
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
# Relationships
|
|
episodes = relationship("Episode", back_populates="project", cascade="all, delete-orphan")
|
|
shots = relationship("Shot", back_populates="project", cascade="all, delete-orphan")
|
|
assets = relationship("Asset", back_populates="project", cascade="all, delete-orphan")
|
|
project_members = relationship("ProjectMember", back_populates="project", cascade="all, delete-orphan")
|
|
tasks = relationship("Task", back_populates="project", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f"<Project(id={self.id}, name='{self.name}', status='{self.status}')>"
|
|
|
|
|
|
class ProjectMember(Base):
|
|
__tablename__ = "project_members"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
|
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
|
|
department_role = Column(Enum(DepartmentRole), nullable=True)
|
|
joined_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
# Relationships
|
|
user = relationship("User", back_populates="project_memberships")
|
|
project = relationship("Project", back_populates="project_members")
|
|
|
|
def __repr__(self):
|
|
return f"<ProjectMember(user_id={self.user_id}, project_id={self.project_id}, role='{self.department_role}')>" |