feat(tickets): wire team_id filter and team-scoped dashboard query #295

Merged
vas2000-work merged 2 commits from feat/PMS-406-ticket-team-scope-filter into main 2026-06-18 00:53:30 +02:00
Owner

Wire the existing but inert tickets.team_id filter into the WHERE builder so GET /api/v1/tickets?team_id= actually scopes the list, and add a team dimension to the operations dashboard so the full-screen TV-view (MAPPS-256) can request a single team's KPI set. The IT / HR / service-vendor split is modeled as distinct teams rows, not a hardcoded enum.

build_ticket_filter_sql now emits t.team_id = $n (data and count queries) when TicketFilter.team_id is Some, and a "my teams" scope (my_teams flag) that restricts to the caller's team_members via a correlated subquery, so the frontend does not resolve team ids itself. The caller id is threaded into list_ticket_responses from RequireAuth; the portal path passes None.

list_ticket_responses validates team_id belongs to the caller's tenant (validate_fk on teams) before binding, so a cross-tenant team id 4xx-rejects rather than silently returning a tenant-only list. The tenant predicate t.tenant_id = $1 stays the unconditional first condition; team scoping is additive only.

ReportsService::dashboard takes an optional team_id and appends a parameterized AND team_id = $n to all four aggregates (open_by_priority, sla_warnings, sla_breached, ticket_trend_30d); absent the param the output is unchanged. Surfaced as a query param on GET /reports/dashboard and the dashboard CSV export.

Migration 054 adds idx_tickets_tenant_team on tickets(tenant_id, team_id) so the team-scoped list and dashboard queries stay fast. Integration test covers the team_id filter, cross-tenant rejection, and the my_teams union.

#PMS-406

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Wire the existing but inert `tickets.team_id` filter into the WHERE builder so GET /api/v1/tickets?team_id=<uuid> actually scopes the list, and add a team dimension to the operations dashboard so the full-screen TV-view (MAPPS-256) can request a single team's KPI set. The IT / HR / service-vendor split is modeled as distinct `teams` rows, not a hardcoded enum. build_ticket_filter_sql now emits `t.team_id = $n` (data and count queries) when TicketFilter.team_id is Some, and a "my teams" scope (my_teams flag) that restricts to the caller's team_members via a correlated subquery, so the frontend does not resolve team ids itself. The caller id is threaded into list_ticket_responses from RequireAuth; the portal path passes None. list_ticket_responses validates team_id belongs to the caller's tenant (validate_fk on teams) before binding, so a cross-tenant team id 4xx-rejects rather than silently returning a tenant-only list. The tenant predicate `t.tenant_id = $1` stays the unconditional first condition; team scoping is additive only. ReportsService::dashboard takes an optional team_id and appends a parameterized `AND team_id = $n` to all four aggregates (open_by_priority, sla_warnings, sla_breached, ticket_trend_30d); absent the param the output is unchanged. Surfaced as a query param on GET /reports/dashboard and the dashboard CSV export. Migration 054 adds idx_tickets_tenant_team on tickets(tenant_id, team_id) so the team-scoped list and dashboard queries stay fast. Integration test covers the team_id filter, cross-tenant rejection, and the my_teams union. #PMS-406 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vas2000-work force-pushed feat/PMS-406-ticket-team-scope-filter from 2720fcae9e
Some checks failed
E2E / Playwright against staging (pull_request) Successful in 55s
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 1m48s
Integration / integration tests (pull_request) Failing after 2m13s
to 90e3717842
All checks were successful
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 1m8s
E2E / Playwright against staging (pull_request) Successful in 1m11s
Integration / integration tests (pull_request) Successful in 7m32s
Create release / Create release from merged PR (pull_request) Has been skipped
2026-06-18 00:44:22 +02:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!295
No description provided.