--- phase: 2 plan: "02-01" subsystem: backend tags: [service, controller, tests, api] dependency_graph: requires: [phase-1] provides: [heatmap-service, heatmap-api, phpunit-config] affects: [services.yaml] tech_stack: added: [phpunit] patterns: [mocked-repository, unit-test] key_files: created: - Service/HeatmapService.php - Controller/HeatmapController.php - Resources/config/routes.yaml - Tests/phpunit.xml - Tests/bootstrap.php - Tests/Service/HeatmapServiceTest.php - Tests/Controller/HeatmapControllerTest.php modified: - Resources/config/services.yaml decisions: - Removed final from HeatmapService to allow PHPUnit mocking in controller tests metrics: duration: ~5min completed: "2026-04-08" --- # Phase 2 Plan 01: HeatmapService, PHPUnit Tests, and API Endpoint Summary Data aggregation service querying t.date for timezone-correct daily grouping, JSON API controller at /heatmap/data, PHPUnit tests with mocked TimesheetRepository. ## What Was Built 1. **services.yaml** -- Added _defaults with autowire/autoconfigure, resource scanning for Controller/Service/Widget/EventSubscriber directories 2. **HeatmapService** -- Queries TimesheetRepository grouping by DATE(t.date), sums duration, counts entries, filters by user/date range/optional project, excludes running timesheets 3. **PHPUnit infrastructure** -- phpunit.xml config, bootstrap.php with dual autoloader path resolution (plugin root vs symlinked) 4. **HeatmapController** -- GET /heatmap/data returning JSON with days array and range object, IsGranted auth 5. **Controller test** -- Mocked service and user via container/token storage ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 1 - Bug] Fixed bootstrap autoloader paths** - **Found during:** Task 3 verification - **Issue:** Plan's bootstrap paths used `../../dev/kimai/` from Tests/ dir, resolving one level too high - **Fix:** Changed to `/../dev/kimai/` (single parent from Tests/) - **Files modified:** Tests/bootstrap.php - **Commit:** 7060cfc **2. [Rule 3 - Blocking] Removed final from HeatmapService** - **Found during:** Task 5 verification - **Issue:** PHPUnit cannot mock final classes; controller test failed with ClassIsFinalException - **Fix:** Changed `final class HeatmapService` to `class HeatmapService` - **Files modified:** Service/HeatmapService.php - **Commit:** 7060cfc ## Verification ``` PHPUnit 10.5.63 -- OK (4 tests, 15 assertions) ``` ## Commits | Hash | Message | |------|---------| | 7060cfc | feat: add HeatmapService, API controller, and PHPUnit tests |