Files
beabigegg 61fe01cb6b feat: implement workload heatmap module
- Backend (FastAPI):
  - Workload heatmap API with load level calculation
  - User workload detail endpoint with task breakdown
  - Redis caching for workload calculations (1hr TTL)
  - Department isolation and access control
  - WorkloadSnapshot model for historical data
  - Alembic migration for workload_snapshots table

- API Endpoints:
  - GET /api/workload/heatmap - Team workload overview
  - GET /api/workload/user/{id} - User workload detail
  - GET /api/workload/me - Current user workload

- Load Levels:
  - normal: <80%, warning: 80-99%, overloaded: >=100%

- Tests:
  - 26 unit/API tests
  - 15 E2E automated tests
  - 77 total tests passing

- OpenSpec:
  - add-resource-workload change archived
  - resource-management spec updated

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:13:21 +08:00

79 lines
1.9 KiB
Python

from pydantic import BaseModel
from typing import Optional, List
from datetime import date, datetime
from decimal import Decimal
from enum import Enum
class LoadLevel(str, Enum):
"""Workload level classification."""
NORMAL = "normal"
WARNING = "warning"
OVERLOADED = "overloaded"
UNAVAILABLE = "unavailable"
class TaskWorkloadInfo(BaseModel):
"""Task information for workload detail view."""
task_id: str
title: str
project_id: str
project_name: str
due_date: Optional[datetime] = None
original_estimate: Optional[Decimal] = None
status: Optional[str] = None
class UserWorkloadSummary(BaseModel):
"""Summary of a user's workload for heatmap display."""
user_id: str
user_name: str
department_id: Optional[str] = None
department_name: Optional[str] = None
capacity_hours: Decimal
allocated_hours: Decimal
load_percentage: Optional[Decimal] = None
load_level: LoadLevel
task_count: int
class WorkloadHeatmapResponse(BaseModel):
"""Response for workload heatmap API."""
week_start: date
week_end: date
users: List[UserWorkloadSummary]
class UserWorkloadDetail(BaseModel):
"""Detailed workload for a specific user."""
user_id: str
user_name: str
week_start: date
week_end: date
capacity_hours: Decimal
allocated_hours: Decimal
load_percentage: Optional[Decimal] = None
load_level: LoadLevel
tasks: List[TaskWorkloadInfo]
class WorkloadSnapshotResponse(BaseModel):
"""Response for workload snapshot."""
id: str
user_id: str
week_start: date
allocated_hours: Decimal
capacity_hours: Decimal
load_percentage: Decimal
task_count: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class CapacityUpdate(BaseModel):
"""Request to update user capacity."""
capacity: Decimal