Add per-project Department management

Departments are now a customizable per-project list (standard + custom),
matching the existing custom task type/status pattern, instead of a fixed
7-value enum. They're usable directly on tasks (new field, independent of
assignee) and continue to drive team member department roles.
This commit is contained in:
2026-07-22 04:03:33 +08:00
parent 11e1369f2f
commit c09710f4e5
20 changed files with 1220 additions and 75 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
# Models package
from .user import User, UserRole, DepartmentRole
from .user import User, UserRole
from .project import Project, ProjectMember, ProjectStatus
from .episode import Episode, EpisodeStatus
from .asset import Asset, AssetCategory, AssetStatus
@@ -17,7 +17,7 @@ from .role import Role, Permission, role_permissions, user_roles
__all__ = [
# User models
"User", "UserRole", "DepartmentRole",
"User", "UserRole",
# Project models
"Project", "ProjectMember", "ProjectStatus",
# Episode models
+4 -2
View File
@@ -2,7 +2,6 @@ from sqlalchemy import Column, Integer, String, DateTime, Date, Enum, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from database import Base
from .user import DepartmentRole
import enum
@@ -54,6 +53,9 @@ class Project(Base):
# Custom task statuses
custom_task_statuses = Column(JSON, nullable=True) # Custom task statuses for project
# Custom departments
custom_departments = Column(JSON, nullable=True) # Custom departments for project (in addition to standard ones)
# Submission configuration per task type
submission_config_by_task_type = Column(JSON, nullable=True) # Allowed file types, naming pattern, required flag per task type
@@ -80,7 +82,7 @@ class ProjectMember(Base):
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)
department_role = Column(String, nullable=True) # Free-form: standard department or a project's custom department
joined_at = Column(DateTime(timezone=True), server_default=func.now())
# Relationships
+1
View File
@@ -56,6 +56,7 @@ class Task(Base):
name = Column(String, nullable=False, index=True)
description = Column(Text)
status = Column(String, nullable=False, default="not_started") # Changed from Enum to String to support custom statuses
department = Column(String, nullable=True) # Standard or project-custom department, independent of assignee
start_date = Column(Date)
deadline = Column(Date)
created_at = Column(DateTime(timezone=True), server_default=func.now())
-10
View File
@@ -12,16 +12,6 @@ class UserRole(str, enum.Enum):
DEVELOPER = "developer"
class DepartmentRole(str, enum.Enum):
LAYOUT = "layout"
ANIMATION = "animation"
LIGHTING = "lighting"
COMPOSITE = "composite"
MODELING = "modeling"
RIGGING = "rigging"
SURFACING = "surfacing"
class User(Base):
__tablename__ = "users"