> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Teams Service

> The **Teams Service** is the subsystem within Nextedy PLANNINGBOARD that models your organization's team structure as first-class Polarion data — work items representing teams, membership assignments 

This page explains what the Teams Service is, how it is structured, and why it exists — not how to configure it step by step.

## Why a Teams Service Exists

Planningboard already supports organizing swimlanes by assignee (the **Users (Assignee)** assignment type). That mode reads Polarion user roles and populates one swimlane per user in the project. It works well when you have a small, stable project with no multi-team overlay.

As soon as you need to answer questions like "which users belong to Team Alpha this sprint?" or "how much capacity does the backend team have in weeks 3 and 4 of this PI?", a flat user-role list is not enough. You need a model that captures:

* **Team identity** — a named entity that can be referenced across projects
* **Membership over time** — people join and leave teams; a member's availability changes
* **Capacity per member** — each person may be allocated at a different percentage
* **Aggregate team capacity** — the total hours the team can deliver in a window

The Teams Service provides exactly this model, represented entirely inside Polarion as standard work items with custom fields — no external database or API is required.

## How Teams Are Represented

Each team is a **Polarion work item** of a specific type (the "Team WI"). The Teams Service locates teams by querying work items in the current project (and any supporting projects assigned to it). Because teams are ordinary work items, they inherit all Polarion capabilities: access control, custom fields, workflow, documents, and links.

Team membership is also represented as work items — one work item per team assignment — with at minimum two date fields (`from` and `to`) that bracket the period during which a person belongs to a team. The Teams Service reads these assignment work items when it resolves "which users are on this team right now?" and "which users were active during this specific date range?"

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/zUlmOSLBIQ0HyaAX/planningboard/diagrams/concepts/teams-service/diagram-1.svg?fit=max&auto=format&n=zUlmOSLBIQ0HyaAX&q=85&s=a0202dffaaa55819f12af9f13d1bd9c2" alt="Hierarchy of a Polarion Project containing Work Items of type team, each Team (Backend, Frontend) containing Assignment work items with user, from, and to dates" width="820" height="350" data-path="planningboard/diagrams/concepts/teams-service/diagram-1.svg" />
</Frame>

A "supporting project" is a Polarion project whose teams are made available to the current project. The Teams Service discovers teams from both the current project and any supporting projects automatically, using a query that matches both `project.id` and the supporting project field. Team IDs from supporting projects are remapped transparently so callers always work with local references.

## The Capacity Model

When `useTeamsService` is enabled together with `userCapacityLoad`, the board calculates capacity from the ground up rather than from a flat hours-per-day figure.

The calculation chain works as follows:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/zUlmOSLBIQ0HyaAX/planningboard/diagrams/concepts/teams-service/diagram-2.svg?fit=max&auto=format&n=zUlmOSLBIQ0HyaAX&q=85&s=7c31504918939af4be8e12beae55b5a8" alt="Capacity calculation chain: each team member's working calendar, off-day entries, and assignment percent combine into a per-member capacity formula, and member capacities sum into total Team Capacity" width="780" height="450" data-path="planningboard/diagrams/concepts/teams-service/diagram-2.svg" />
</Frame>

Each member's **working calendar** is resolved individually. If a user has no calendar configured, the system falls back to a base user's calendar (configured via the `nextedy.gantt.calendarHolder` property) and then to the system-default calendar. This means capacity values vary correctly from sprint to sprint as holidays and leave change the available working days.

The result is a `Map<String, Float>` — user IDs mapped to individual capacity hours — which the board uses to populate per-user capacity bars inside swimlanes.

### Capacity Modifiers

An optional layer called **capacity modifiers** can reduce team capacity by a percentage. This is controlled by the `nextedy.gantt.useTeamCapacityModifiers` configuration property (default: `false`). When enabled, the Teams Service reads two integer fields from the team work item — by default `capModA` and `capModB` (overridable via `nextedy.gantt.capacityModifierAField`) — and applies the percentage reduction before returning capacity figures.

Capacity modifiers let you account for overhead, ceremonies, or planned unavailability at the team level without adjusting individual member calendars.

## What the Service Exposes to the Board

The Teams Service interface (`IPlanningBoardTeamsService`) provides the following logical operations to the board engine:

| Operation                    | What it returns                                                     |
| ---------------------------- | ------------------------------------------------------------------- |
| Get team work item           | The work item representing a specific team (by team ID and project) |
| Get all teams                | All teams in the project, including teams from supporting projects  |
| Get team user IDs (basic)    | All user IDs assigned to the team                                   |
| Get team user IDs (filtered) | User IDs filtered by active-only flag and/or date range             |
| Get team users (basic)       | Full user objects for all team members                              |
| Get team users (filtered)    | Full user objects filtered by active-only flag and/or date range    |
| Get team capacity            | Total team capacity in hours for a date range                       |
| Get user capacity            | Individual user capacity in hours within a team for a date range    |
| Get all user capacities      | Map of user ID → capacity hours for all team members                |

Two variants exist for date-range operations: one that accepts `Date` objects (with time component) and one that accepts `DateOnly` objects (date only, no time zone consideration). The board uses the variant appropriate to the planning context — sprint planning typically works with date-only boundaries.

Users that cannot be resolved in Polarion are excluded from filtered results. This means a stale assignment work item pointing at a deleted user account does not cause errors; the user simply does not appear in membership or capacity results.

## How This Connects to Swimlane Configuration

When `useTeamsService = true` and the `assignmentMode` is set to `ASSIGNEE`, the board does not fall back to the flat project-role list. Instead it uses the Teams Service to resolve which users belong to the selected team (`selectedTeam`), and only those users appear as swimlane rows. This is fundamentally different from the standard Users (Assignee) mode:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/zUlmOSLBIQ0HyaAX/planningboard/diagrams/concepts/teams-service/diagram-3.svg?fit=max&auto=format&n=zUlmOSLBIQ0HyaAX&q=85&s=50e06e41aaf4912520054b494554692b" alt="Comparison of Standard Users (Assignee) mode (Project roles to user list to one swimlane per user) versus Teams Service + Assignee mode (selectedTeam to Teams Service to active members filtered by date to swimlane rows, feeding capacity bars populated from user calendar)" width="820" height="300" data-path="planningboard/diagrams/concepts/teams-service/diagram-3.svg" />
</Frame>

The swimlane rows therefore reflect **team membership at the time of planning**, not the static project-role assignment. A user who left the team before the sprint starts will not appear; a user who joins mid-sprint can appear depending on the active-only and date-range filters.

<Warning title="Coordination required for full team filtering">
  Team-based swimlane filtering requires two coordinated configurations: a `selectedTeam` parameter on the board widget (filters the swimlane rows) **and** a matching Plans query that filters iterations by team. If only one of the two is configured, swimlanes may filter correctly while the columns do not (or vice versa), producing a misleading view. See the swimlane assignment types guide for details.
</Warning>

## Known Limitations

The Teams Service capacity model has gaps compared to Nextedy GANTT's capacity features. These are confirmed limitations, not planned features:

* **No multi-assignee support.** Capacity load is calculated from the single assignee field on each work item. Work items with multiple assignees are not currently handled.
* **No sub-item effort distribution.** Capacity calculations do not aggregate effort from child or sub-items. Only the direct work item's effort contributes to load.
* **Custom Team WI types are not supported.** Planningboard requires Nextedy's standard Team work item structure (specific custom fields on the Team WI). Custom team work item types — even if they hold equivalent data — are not compatible with the Teams Service. By contrast, Nextedy GANTT 25.5.0+ introduced support for custom team WI types. Teams planning multi-product deployments where Gantt and Planningboard coexist should use the standard Team WI type to ensure compatibility with both products.
* **Page parameters not supported in swimlane row configuration.** Swimlane configuration (including team selection) uses static widget parameters. Dynamic filtering via Polarion page parameters (e.g. `$pageParameters.xxx`) is not supported. A common workaround is to create one Planningboard page per team, each with a hardcoded `selectedTeam` value.
* **Configuration properties are whitespace-sensitive.** The capacity configuration properties (including `nextedy.gantt.calendarHolder`, `nextedy.gantt.useTeamCapacityModifiers`, and `nextedy.gantt.capacityModifierAField`) must not contain leading or trailing whitespace. Whitespace causes silent misconfiguration — the property is not rejected; it simply does not match.

## Mental Model: Teams as First-Class Planning Entities

A useful way to think about the Teams Service is as a **layer of indirection** between individual people and the board's swimlane/capacity machinery.

Without the Teams Service, the board knows about users directly: it queries the project, finds users by role, and creates one swimlane per user. Capacity, if enabled, applies a uniform hours-per-day figure.

With the Teams Service, the board knows about **teams**, and teams know about **members** across time. The board asks "who is on team X and how much can they do in this window?" — the Teams Service answers by consulting assignment work items, user calendars, and off-day entries. The board receives a prepared answer; it does not need to understand the membership or calendar mechanics itself.

This indirection pays off when the same team structure is needed across multiple boards or multiple projects: a single set of Team work items, maintained in one project (or a shared supporting project), drives membership and capacity consistently across all boards that reference it.

<Note title="Relationship to Gantt">
  The `nextedy.gantt.calendarHolder` and `nextedy.gantt.useTeamCapacityModifiers` configuration properties are named with the `gantt` prefix because the Teams Service implementation is shared infrastructure between Planningboard and Nextedy GANTT. The properties apply to both products.
</Note>

## Related Concepts

* [Capacity Tracking](/planningboard/concepts/capacity-tracking) — how capacity bars are computed and displayed on the board
* [Swimlane Assignment Modes](/planningboard/concepts/assignment-modes) — the full set of swimlane assignment types, including the Users (Assignee) mode that the Teams Service augments
* [Normalization](/planningboard/concepts/normalization) — how capacity values are normalized across swimlanes for comparison

<Accordion title="Sources">
  **KB Articles**

  * What is 'Normalization'
  * Introduction to Planningboard
  * Swimlane Assignment Types

  **Support Tickets**

  * [#6546](https://support.nextedy.com/helpdesk/tickets/6546)
  * [#5760](https://support.nextedy.com/helpdesk/tickets/5760)
  * [#6605](https://support.nextedy.com/helpdesk/tickets/6605)

  **Source Code**

  * `IPlanningBoardTeamsService.java`
  * `PlanningBoardTeamsService.java`
  * `Config.java`
  * `AssignmentMode.java`
  * `PlanningBoardWidgetRenderer.java`
</Accordion>
