# Teams & Templates

Team membership, roles, and reusable task templates


Teams, membership, estimate scales, task templates, and custom-field plumbing in the Operation plugin.

Backend code lives under `backend/plugins/operation_api/src/modules/{team,template,fields}/`. Teams are the scoping unit: statuses, cycles, triage queues, and task estimate scales all hang off a team.

## Data models

- **`operation_teams`**: `{ icon, name, description, memberIds: [String], estimateType: Int, cycleEnabled: Boolean, triageEnabled: Boolean }`.
- **`operation_team_members`**: `{ memberId, teamId, role }`; `role` supports `admin` / `member` / `lead` in the model but is deprecated on the GraphQL type.
- **`operation_templates`**: `{ name, defaults: JSON, teamId, createdBy }`; per-team task templates whose `defaults` prefill a new task.

Creating a team (`teamAdd` → [`Team.createTeam`](https://github.com/erxes/erxes/blob/f91e8c6f4714c910a32c6b6e14fe085f6435c89e/backend/plugins/operation_api/src/modules/team/db/models/Team.ts)) inserts `TeamMember` rows for the creator and `memberIds`, then seeds the five default statuses (`backlog`, `todo`, `in progress`, `done`, `cancelled`); see [Tasks & Statuses](https://erxes.io/docs/operation-tasks).

## Estimate scales

`estimateType` is one of `TeamEstimateTypes` ([`team/utils.ts`](https://github.com/erxes/erxes/blob/f91e8c6f4714c910a32c6b6e14fe085f6435c89e/backend/plugins/operation_api/src/modules/team/utils.ts)): `NOT_IN_USE=1`, `DEFAULT=2` (0–5), `FIBONACCI=3` (0,1,2,3,5,8), `EXPONENTIAL=4` (0,1,2,4,8,16). `getTeamEstimateChoises(teamId)` (sic; the operation name is misspelled in the schema) returns the `{ value, label }` list for the team's type, or `null` when estimates are off.

> [!WARNING]
> **Switching estimateType wipes estimates**
>
> `updateTeam` sets `estimatePoint: null` on every task of the team when `estimateType` changes to `NOT_IN_USE`. Other scale switches keep existing values even if they are not in the new scale.

Toggling `cycleEnabled` on SaaS (`VERSION=saas`) also updates the organization's `cycleEnabled` flag, which is what the daily cycle worker filters on; see [Projects, Cycles & Milestones](https://erxes.io/docs/operation-projects-cycles).

## Queries and mutations

| Operation | Kind | Permission |
| --- | --- | --- |
| `getTeam(_id)` / `getTeams(name, userId, teamIds, projectId, isTriageEnabled, teamId, orderBy)` | query | `teamRead` |
| `getTeamMembers(teamId, teamIds)` | query | `teamRead` |
| `getTeamEstimateChoises(teamId)` | query | `teamRead` |
| `teamAdd(name, description, icon, memberIds)` / `teamUpdate(_id, …estimateType, cycleEnabled, triageEnabled)` | mutation | `teamCreate` / `teamUpdate` |
| `teamRemove(_id)` | mutation | `teamRemove` |
| `teamAddMembers(_id, memberIds)` / `teamRemoveMember(teamId, memberId)` / `teamUpdateMember(_id)` | mutation | `teamMemberManage` |
| `operationTemplates(teamId)` / `operationTemplateDetail(_id)` | query | login only; no `checkPermission` |
| `operationTemplateAdd(name, defaults, teamId)` / `operationTemplateEdit` / `operationTemplateRemove` | mutation | login only; no `checkPermission` |

## Custom fields

`fields.getFieldList` on the plugin tRPC router returns the filterable/inputable field list for `moduleType: 'task'` or `'project'`. [`modules/fields/fieldUtils.ts`](https://github.com/erxes/erxes/blob/f91e8c6f4714c910a32c6b6e14fe085f6435c89e/backend/plugins/operation_api/src/modules/fields/fieldUtils.ts) builds it from the Mongoose schemas plus hand-declared options: `priority` renders `No Priority`/`Minor`/`Medium`/`High`/`Critical` (values 0–4), `statusType` maps to the `STATUS_TYPES` labels, and `teamId`, `assigneeId`, `createdBy`, `tagIds` get selection configs (e.g. `queryName: 'users'`).

Custom property values are stored on the record under `propertiesData` keyed by Core field id; the plugin meta exposes `task` and `project` property types with `systemFields` `code`/`name`/`type` shown as "Basic information" in Settings → Properties. `propertiesData` is only written through `task.createFromSource`; the task GraphQL type does not expose it.

## Permissions

Team module actions: `teamRead` (always granted), `teamCreate`, `teamUpdate`, `teamRemove`, `teamMemberManage` (membership changes). Template resolvers perform no `checkPermission` call, so they fall back to the platform default (any logged-in user). Scopes are `own` (creator), `group` (member's teams), `all`. A member who cannot see a team has lost the `group` scope; re-add them with `teamAddMembers`.

