# Tasks & Workflow — BAMS Legal

> Matter-linked task management driven by reusable checklist templates, so
> common workflows don't get re-typed for every new matter. Staff-only.

---

## Table of Contents

1. [Task Template](#task-template)
2. [Task](#task)
3. [Task Comment](#task-comment)
4. [Task Lifecycle](#task-lifecycle)
5. [Notes & Guidelines](#notes--guidelines)

---

## Task Template

### Schema (Template)

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `id` | Integer | Auto | — | Primary key |
| `firm_id` | FK | Yes | — | |
| `name` | String | Yes | — | e.g. "New Suit Filing" |
| `applies_to` | Enum | No | `null` | `MatterType` filter, or null = any |
| `is_active` | Boolean | No | `true` | |

### Schema (Template Item)

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `id` | Integer | Auto | — | Primary key |
| `task_template_id` | FK | Yes | — | |
| `title` | String | Yes | — | |
| `sort_order` | Integer | No | `0` | |
| `due_offset_days` | Integer | No | `null` | Days from matter's `date_opened` |
| `default_assignee_role` | Enum | No | `null` | `lead_counsel`, `counsel`, `paralegal` |

### Admin Routes

**Base:** `/admin/task-templates` · **Auth:** session, permission `tasks.create` (admin management)

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/task-templates` | List templates |
| `POST` | `/admin/task-templates` | Create a template with items |
| `PATCH` | `/admin/task-templates/:id` | Update a template's items |
| `DELETE` | `/admin/task-templates/:id` | Deactivate |

### Validation Rules

| Field | Rules |
|---|---|
| `name` | Required. Unique per firm. |
| `items` | At least 1 item required. |
| `due_offset_days` | Optional. Integer ≥ 0. |

---

## Task

### Schema

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `id` | Integer | Auto | — | Primary key |
| `ulid` | ULID | Auto | — | Public identifier |
| `firm_id` | FK | Yes | — | |
| `matter_id` | FK | No | `null` | Null for non-matter (general firm) tasks |
| `title` | String | Yes | — | |
| `description` | Text | No | `null` | |
| `assigned_to` | FK (User) | No | `null` | |
| `assigned_by` | FK (User) | Yes | — | |
| `due_date` | Date | No | `null` | |
| `priority` | Enum | No | `normal` | `low`, `normal`, `high`, `urgent` |
| `status` | Enum | No | `open` | `open`, `in_progress`, `done`, `cancelled` |
| `completed_at` | Timestamp | No | `null` | |

### Admin Routes

**Base:** `/admin/tasks` · **Auth:** session, permission `tasks.view` / `tasks.viewAll`

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/tasks` | List ("My Tasks" default; firm-wide with `tasks.viewAll`) |
| `GET` | `/admin/tasks/:id` | Get task detail |
| `POST` | `/admin/matters/:id/tasks` | Create a matter-linked task |
| `POST` | `/admin/tasks` | Create a general (non-matter) task |
| `PATCH` | `/admin/tasks/:id` | Update task fields |
| `PATCH` | `/admin/tasks/:id/status` | Change status |
| `DELETE` | `/admin/tasks/:id` | Delete |
| `POST` | `/admin/matters/:id/apply-template` | Apply a task template to an existing matter |

### Request & Response Examples

**Apply a template** — `POST /admin/matters/:id/apply-template`

```json
{ "task_template_id": 3 }
```

```json
{
  "success": true,
  "data": { "tasks_created": 6 },
  "message": "6 tasks created from the \"New Suit Filing\" checklist."
}
```

**Change status** — `PATCH /admin/tasks/:id/status`

```json
{ "status": "done" }
```

```json
{
  "success": true,
  "data": { "id": 305, "status": "done", "completed_at": "2026-07-05T10:12:00Z" },
  "message": "Task marked done."
}
```

### Validation Rules

| Field | Rules |
|---|---|
| `title` | Required. Max 255. |
| `assigned_to` | Optional. If matter-linked, must be on the matter's team (or explicitly overridden with a permission). |
| `status` transition | `cancelled` and `done` are terminal — reopening requires an explicit "reopen" action, not a plain status PATCH. |

---

## Task Comment

### Schema

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `id` | Integer | Auto | — | Primary key |
| `task_id` | FK | Yes | — | |
| `user_id` | FK | Yes | — | |
| `comment` | Text | Yes | — | |

### Admin Routes

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/tasks/:id/comments` | List comments |
| `POST` | `/admin/tasks/:id/comments` | Post a comment |

---

## Task Lifecycle

```
Matter registered (matching template found)
  or  POST /admin/matters/:id/apply-template
        │
        ▼
  Tasks created: due_date = matter.date_opened + due_offset_days
                 assigned_to resolved from default_assignee_role against
                 the matter team (unassigned if no match — flagged for
                 lead counsel to triage)
        │
        ▼
  PATCH /admin/tasks/:id/status → in_progress → done
        │
        ▼ (if matter-linked)
  matter_events row appended: "task_completed"
```

---

## Notes & Guidelines

- Applying a template never duplicates tasks — re-applying the same template
  to a matter that already has its tasks is blocked with a conflict response
  unless explicitly forced.
- Overdue tasks (`due_date` in the past, status not `done`/`cancelled`) surface
  on the matter page banner and the "My Tasks" dashboard widget (M10) — this
  read is a shared query, not duplicated logic.
- There is no portal-facing task API — tasks are an internal workflow tool
  only; clients never see them, even indirectly.
