# Team Management Migration Guide

## Overview

This guide covers the migration from the legacy capacity allocation model to the new Sprint Participants model.

## What Changed

### Before (Legacy Model)

```
Project
└── All Members (via project_members)
    └── Capacity tracked in: project_sprint_capacity_allocations
```

All project members appeared in capacity planning for all sprints.

### After (New Model)

```
Project
└── Project Members (via project_members)
    └── Sprint Participants (via project_sprint_participants)
        └── Capacity stored directly on participant record
```

Only explicitly selected participants appear in sprint capacity.

## Database Changes

### New Tables

#### `project_sprint_participants`

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `project_sprint_id` | UUID | FK to sprint |
| `user_id` | UUID | FK to user |
| `capacity_md` | DECIMAL(6,2) | Optional capacity allocation |
| `added_by_user_id` | UUID | Who added the participant |
| `created_at` | TIMESTAMP | Record creation |
| `updated_at` | TIMESTAMP | Last update |

#### `ticket_watchers`

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `ticket_id` | UUID | FK to ticket |
| `user_id` | UUID | FK to user |
| `added_by_user_id` | UUID | Who added the watcher |
| `created_at` | TIMESTAMP | Record creation |
| `updated_at` | TIMESTAMP | Last update |

### Migration Script

The migration `2026_06_15_100002_migrate_capacity_allocations_to_participants.php` performs:

1. Reads all existing `project_sprint_capacity_allocations`
2. For each allocation:
   - Checks if participant already exists (skip if yes)
   - Creates `SprintParticipant` with same user and capacity
3. Logs migration statistics

### Running the Migration

```bash
# Run pending migrations
php artisan migrate

# Or run specific migration
php artisan migrate --path=database/migrations/2026_06_15_100002_migrate_capacity_allocations_to_participants.php
```

## Code Changes

### Services Updated

#### `SprintTeamCapacityService`

The capacity planning service now:

1. Checks for `SprintParticipant` records first
2. Falls back to legacy `ProjectSprintCapacityAllocation` if no participants exist
3. Returns `is_participant` flag in team data

```php
// In planningDashboard()
$participants = SprintParticipant::where('project_sprint_id', $sprint->id)->get();
$useParticipants = $participants->isNotEmpty();

if ($useParticipants) {
    // Use participant records for capacity
} else {
    // Fall back to legacy allocations
}
```

#### `ProjectWorkItemService` & `WorkItemDetailService`

Assignment validation now includes project membership check:

```php
if (isset($data['current_assignee_id'])) {
    $this->assignmentValidator->validateAssignee(
        $data['current_assignee_id'],
        $project->id
    );
}
```

### New Service

#### `ProjectAssignmentValidator`

Validates that assignees are project members:

```php
public function validateAssignee(?string $userId, ?string $projectId): void
{
    if ($userId === null || $projectId === null) {
        return;
    }
    
    if (!$this->isProjectMemberOrOwner($userId, $projectId)) {
        throw new BusinessException('User must be added to the project before assignment.');
    }
}
```

## API Changes

### New Endpoints

#### Sprint Participants

```
GET    /api/v1/projects/{project}/sprints/{sprint}/participants
POST   /api/v1/projects/{project}/sprints/{sprint}/participants
PATCH  /api/v1/projects/{project}/sprints/{sprint}/participants/{user}
DELETE /api/v1/projects/{project}/sprints/{sprint}/participants/{user}
PUT    /api/v1/projects/{project}/sprints/{sprint}/participants/sync
GET    /api/v1/projects/{project}/sprints/{sprint}/participants/eligible
```

#### Ticket Watchers

```
GET    /api/v1/tickets/{ticket}/watchers
POST   /api/v1/tickets/{ticket}/watchers
DELETE /api/v1/tickets/{ticket}/watchers/{user}
POST   /api/v1/tickets/{ticket}/watchers/toggle
GET    /api/v1/tickets/{ticket}/watchers/status
GET    /api/v1/tickets/{ticket}/watchers/candidates
```

### Existing Endpoints Enhanced

#### Work Item Update

```http
PATCH /api/v1/projects/{project}/work-items/{ticket}
```

Now validates `current_assignee_id` against project membership.

## Frontend Changes

### New Components

#### ProjectTeamPage

New Team tab at `/projects/:id/team` containing:
- Team summary metrics
- Members table with roles and workload
- Workload dashboard view

#### Board & Backlog Cards

Updated to show:
- Avatar stack for assignee + collaborators
- Collaborator count icon
- Watcher count icon

### Updated Types

```typescript
interface BoardTicket {
  // ... existing fields
  collaborators?: Array<{ id: string; name: string }>;
  collaborator_count?: number;
  watcher_count?: number;
}

interface ProjectWorkItem {
  // ... existing fields
  collaborators?: Array<{ id: string; name: string }>;
  collaborator_count?: number;
  watcher_count?: number;
}
```

### New Route

```
/projects/:id/team → ProjectTeamPage
```

### Navigation

Team tab added to project subnav (after Executive, before Backlog).

## Backward Compatibility

### Transition Period

The system maintains backward compatibility during migration:

1. **Capacity Service** falls back to legacy allocations
2. **Old allocations** remain in database
3. **Sync endpoint** writes to both systems if needed

### Recommended Approach

1. Run migration to copy allocations to participants
2. Monitor for any issues
3. Eventually deprecate legacy allocations table

## Testing Checklist

After migration:

- [ ] Capacity planning shows correct participants
- [ ] Sprint capacity totals are accurate
- [ ] Workload calculations use participants only
- [ ] Assignment validation blocks non-members
- [ ] Watchers can be added/removed
- [ ] Board cards show collaborators/watchers
- [ ] Team tab displays all members correctly

## Rollback

If needed, the migration can be rolled back:

```bash
php artisan migrate:rollback --step=1
```

The original `project_sprint_capacity_allocations` data is preserved.

## Questions?

For issues or questions:
1. Check the related documentation in `/docs/`
2. Review the test suite for expected behavior
3. Contact the development team
