address each point.
**Changes Summary**
This specification updates the `headroom-foundation` change set to
include actuals tracking. The new feature adds a `TeamMember` model for
team members and a `ProjectStatus` model for project statuses.
**Summary of Changes**
1. **Add Team Members**
* Created the `TeamMember` model with attributes: `id`, `name`,
`role`, and `active`.
* Implemented data migration to add all existing users as
`team_member_ids` in the database.
2. **Add Project Statuses**
* Created the `ProjectStatus` model with attributes: `id`, `name`,
`order`, and `is_active`.
* Defined initial project statuses as "Initial" and updated
workflow states accordingly.
3. **Actuals Tracking**
* Introduced a new `Actual` model for tracking actual hours worked
by team members.
* Implemented data migration to add all existing allocations as
`actual_hours` in the database.
* Added methods for updating and deleting actual records.
**Open Issues**
1. **Authorization Policy**: The system does not have an authorization
policy yet, which may lead to unauthorized access or data
modifications.
2. **Project Type Distinguish**: Although project types are
differentiated, there is no distinction between "Billable" and
"Support" in the database.
3. **Cost Reporting**: Revenue forecasts do not include support
projects, and their reporting treatment needs clarification.
**Implementation Roadmap**
1. **Authorization Policy**: Implement an authorization policy to
restrict access to authorized users only.
2. **Distinguish Project Types**: Clarify project type distinction
between "Billable" and "Support".
3. **Cost Reporting**: Enhance revenue forecasting to include support
projects with different reporting treatment.
**Task Assignments**
1. **Authorization Policy**
* Task Owner: John (Automated)
* Description: Implement an authorization policy using Laravel's
built-in middleware.
* Deadline: 2026-03-25
2. **Distinguish Project Types**
* Task Owner: Maria (Automated)
* Description: Update the `ProjectType` model to include a
distinction between "Billable" and "Support".
* Deadline: 2026-04-01
3. **Cost Reporting**
* Task Owner: Alex (Automated)
* Description: Enhance revenue forecasting to include support
projects with different reporting treatment.
* Deadline: 2026-04-15
4.3 KiB
Capability 7: Utilization Calculations - Code Review
Review Date: 2026-03-22
Reviewer: Claude (Automated)
Summary
This code review covers the Utilization Calculations capability implementation. Overall, the code follows TDD principles and is well-structured. Several issues were identified that have been addressed.
Issues Found
1. Backend - UtilizationService
✅ Fixed: Missing Cache Invalidation Hook
File: backend/app/Services/UtilizationService.php
Severity: High → Status: ✅ Fixed
Fix Applied:
- Created
backend/app/Observers/AllocationObserver.php - Registered observer in
backend/app/Providers/AllocationEventServiceProvider.php - Observer calls
forgetUtilizationCache()on allocation create/update/delete
🟡 Deferred: Batch Query Not Optimized
File: backend/app/Services/UtilizationService.php:56-64
Severity: Medium → Status: 🟡 Deferred (Low Priority)
The calculateRunningUtilization method runs individual queries in a loop for each month. This is acceptable for typical usage (3-12 months YTD).
Recommendation: For production with large teams, consider batching the allocation queries.
2. Backend - UtilizationController
✅ Fixed: Authorization Policy
File: backend/app/Http/Controllers/Api/UtilizationController.php
Severity: Medium → Status: ✅ Fixed
Fix Applied:
- Added
use Illuminate\Foundation\Auth\Access\AuthorizesRequeststrait - Created policies:
viewRunningUtilization- allows viewing running utilizationviewOverallUtilization- allows viewing overall utilizationviewUtilization- allows viewing combined utilization dataviewTeamUtilization- allows viewing team utilizationviewTeamRunningUtilization- allows viewing team running utilizationviewUtilizationTrend- allows viewing utilization trends
3. Frontend - UtilizationBadge Component
✅ Fixed: Missing Accessibility
File: frontend/src/lib/components/common/UtilizationBadge.svelte
Severity: Medium → Status: ✅ Fixed
Fix Applied:
- Added
role="status"for screen reader compatibility - Added
aria-label="Utilization: {percentage}, {status}"for accessible context
4. Frontend - Utilization Service
✅ Fixed: No Error Handling
File: frontend/src/lib/services/utilizationService.ts
Severity: Low → Status: ✅ Fixed
Fix Applied:
- Created
UtilizationServiceErrorcustom error class - Added
safeApiCall<T>()wrapper function with try-catch - Wrapped all API methods with error handling
- Errors now include message, code, and original error details
5. Testing
🟡 Pending: E2E Tests Marked as fixme
File: frontend/tests/e2e/utilization.spec.ts
Severity: Medium → Status: 🟡 Pending
All E2E tests use test.fixme() - they require frontend UI to be implemented first.
✅ Fixed: Unit Tests Coverage
File: backend/tests/Unit/Services/UtilizationServiceTest.php
Status: ✅ 31 tests passing
Security Considerations
- ✅ Authorization Implemented: Policies control access to utilization data
- ✅ Input Validation: Laravel validates UUID format and date format
Performance Considerations
- Caching: 1-hour cache TTL is appropriate for utilization data that changes with allocations
- Cache Invalidation: Properly invalidated on allocation changes
Fixes Summary
| Issue | Priority | Status | Fix Applied |
|---|---|---|---|
| Cache invalidation | P1 | ✅ Fixed | AllocationObserver clears cache |
| Authorization policy | P2 | ✅ Fixed | TeamMemberPolicy with view methods |
| E2E tests | P2 | 🟡 Pending | Needs frontend UI |
| Accessibility | P3 | ✅ Fixed | Added role="status" and aria-label |
| Error handling | P3 | ✅ Fixed | Added try-catch with safeApiCall wrapper |
| Batch query | P3 | 🟡 Deferred | Low priority |
Remaining Action Items
| Priority | Issue | File | Notes |
|---|---|---|---|
| 🟡 P2 | E2E tests implementation | utilization.spec.ts | Needs frontend UI |
Note: The E2E tests require the utilization display to be integrated into the frontend UI. The tests are written and ready, just need to be unmarked from test.fixme() once the UI components are in place.