# Monday.com-style Boards Module

## Context

The request is to build a Monday.com-style task/project management system: Boards → Groups (colored
swimlanes) → Items with fully customizable Columns (Status, People, Date, Number, Dropdown, etc.),
viewable as Table, Kanban, Calendar, and Gantt, plus a basic Automation engine.

This CRM already has two task-like systems:
- **Task module** (`app/Models/Task.php`, `TaskController.php`) — flat list, single assignee, fixed
  fields (priority/type/due date), one `is_completed` boolean, recurring-task job. No boards/columns/views.
- **Project/ProjectTicket module** (`app/Models/Project.php`, `ProjectTicket.php`) — a Project belongs to
  a Lead, has a team/chat/media files; `ProjectTicket` has a fixed `status` field and belongs to a Project.
  This is conceptually the closest existing thing to "board with items and a status," but fixed-schema
  and scoped only to Lead-driven delivery projects.

Per your decisions: **Boards is a new, independent module** — it does not touch, replace, or migrate
either existing system. Board Items **do** link to Leads/Companies (new capability, not reusing
Project/Task's linkage). Column types are a **fixed built-in set** (not a generic plugin registry).
v1 scope includes **all four views** (Table, Kanban, Calendar, Gantt) and a **basic automation engine**,
and item-level collaboration (comments/attachments/activity log) **reuses the existing Task patterns**
(`TaskQuery`, `TaskAttachment`, Spatie activitylog).

This is a large module — the plan below is organized into build phases so it can be shipped and
reviewed incrementally, but all phases are in scope for "v1" per your answers.

## Data Model

New tables (new migrations, one per table, following the existing `Schema::create` + FK + soft-delete
style seen in `create_tasks_table.php`):

- **`boards`**: `id, name, description, created_by (FK users), lead_id (nullable FK leads), company_id
  (nullable FK companies), is_deleted, timestamps, softDeletes`. A board is generic; `lead_id`/
  `company_id` are optional context links (a board can be fully standalone or tied to a Lead/Company).
- **`board_members`**: `id, board_id (FK), user_id (FK users), role (enum: owner/editor/viewer),
  timestamps`. Per-board sharing — Monday.com boards are shared with specific people, not just gated by
  a global role. Unique on `(board_id, user_id)`.
- **`board_groups`**: `id, board_id (FK), name, color, position (int, for ordering), is_deleted,
  timestamps`. The swimlane/section within a board (e.g. "To Do", "In Progress").
- **`board_columns`**: `id, board_id (FK), name, type (enum: text, status, people, date, number,
  dropdown, checkbox, link), position (int), config (json, nullable — e.g. status column's label/color
  options, dropdown's choice list), is_deleted, timestamps`.
- **`board_items`**: `id, board_id (FK), group_id (FK board_groups), name, position (int), created_by
  (FK users), lead_id (nullable FK leads), company_id (nullable FK companies), start_date (nullable date,
  for Gantt), due_date (nullable date, for Gantt/Calendar), is_deleted, timestamps, softDeletes`. The
  "row"/task-equivalent. `start_date`/`due_date` are promoted to real columns (not just column-values)
  because Gantt/Calendar views need to query them directly and efficiently, matching how `Task` already
  has first-class `start_date`/`due_date` rather than storing them generically.
- **`item_column_values`**: `id, item_id (FK board_items), column_id (FK board_columns), text_value
  (nullable string), number_value (nullable decimal), date_value (nullable date), option_value (nullable
  json — for status/dropdown/people: `{"selected": [...]}`, unique on `(item_id, column_id)`,
  timestamps`. One row per (item, column); which value column is populated depends on the column's
  `type`. This mirrors a typed-EAV pattern — simplest approach that still supports the fixed column-type
  set decided above, and keeps queries per view straightforward (e.g. Kanban groups by
  `option_value->selected[0]` on the board's designated status column).
- **`item_dependencies`**: `id, item_id (FK board_items), depends_on_item_id (FK board_items),
  timestamps`. Minimal finish-to-start dependency link for Gantt view.
- **`item_comments`**: mirrors `TaskQuery`'s shape (`item_id, user_id, message, timestamps`) — Q&A/updates
  thread per item.
- **`item_attachments`**: mirrors `TaskAttachment`'s shape (`item_id, user_id, file_path,
  original_filename, timestamps`).
- **`board_automations`**: `id, board_id (FK), name, trigger_type (enum: status_changed, date_arrived,
  item_created), trigger_config (json — e.g. `{"column_id":.., "to_value":".."}`), action_type (enum:
  notify_user, change_column_value, move_to_group), action_config (json), is_active (bool), created_by,
  timestamps`.
- **`automation_logs`**: `id, automation_id (FK), item_id (FK), status (fired/failed), error_message
  (nullable), created_at`. Same "make Graph-API-style failures visible" reasoning as the CAPI plan —
  automations that silently fail are undebuggable otherwise.

## Models

One model per table above under `app/Models/`, following existing conventions (typed relations,
`protected $fillable`, `protected $casts` for dates/json). Key relations:
- `Board hasMany BoardGroup, BoardColumn, BoardItem; hasMany BoardMember; belongsTo Lead/Company nullable`
- `BoardItem belongsTo Board, BoardGroup; hasMany ItemColumnValue, ItemComment, ItemAttachment,
  ItemDependency (both directions)`
- `ItemColumnValue belongsTo BoardItem, BoardColumn`

## Services (business logic stays out of controllers, per project convention)

- **`app/Services/BoardService.php`** — board/group/column CRUD, reordering (position updates),
  member management (add/remove/change role).
- **`app/Services/ItemService.php`** — item CRUD, `setColumnValue(BoardItem $item, BoardColumn $column,
  mixed $value)` (validates/normalizes per column type, upserts `ItemColumnValue`, fires
  `ItemColumnValueChanged` event for automations to listen to), move-to-group, position updates.
- **`app/Services/BoardViewService.php`** — one method per view, each returning data shaped for that
  view without extra client-side transformation:
  - `tableView(Board $board)` — items + all column values, grouped by `board_group`, sorted by `position`.
  - `kanbanView(Board $board, BoardColumn $groupByColumn)` — items bucketed by the selected status-type
    column's current value.
  - `calendarView(Board $board, Carbon $month)` — items whose `due_date` (or a date-type column, v1:
    just the item's own `due_date`) falls in the given month.
  - `ganttView(Board $board)` — items with `start_date`/`due_date` plus `item_dependencies` edges.
- **`app/Services/AutomationEngineService.php`** — `evaluate(BoardItem $item, string $triggerType, array
  $context)`: finds matching active `BoardAutomation`s for the item's board, checks `trigger_config`
  against `$context`, executes the matching `action_type` (uses `SendsPushNotifications` trait /
  `PushNotificationService` for `notify_user`, calls back into `ItemService` for
  `change_column_value`/`move_to_group`), logs outcome to `automation_logs`.

**New pattern flag:** this codebase has no event/observer/listener usage anywhere today (confirmed
during exploration — CAPI plan noted the same). Automations fundamentally require a trigger mechanism,
so this module introduces two small Laravel Events — `ItemColumnValueChanged`, `ItemCreated` — dispatched
from `ItemService`, with a single `AutomationListener` that calls `AutomationEngineService::evaluate()`.
This is a deliberate, scoped exception to "no events in this codebase," not a wholesale architecture
change — nothing outside the Boards module uses it.

## Controllers & Routes

Following the existing `setting`/`campaign`/`task` prefix + POST-endpoint + in-controller
`$user->can('board_management.board.{create|read|update|delete|override}')` permission-check pattern
(Spatie), all under `Route::middleware('account_validation')` → `auth:sanctum`:

- `app/Http/Controllers/BoardController.php` — `create/update/delete/fetch`, group CRUD, column CRUD,
  member management (`board/member/add`, `/remove`, `/update_role`).
- `app/Http/Controllers/BoardItemController.php` — `create/update/delete`, `set_column_value`,
  `move_to_group`, `reorder`, plus the four view endpoints: `board/item/view/table`,
  `/view/kanban`, `/view/calendar`, `/view/gantt`.
- `app/Http/Controllers/BoardItemCommentController.php` / attachment controller — mirrors
  `TaskController`'s `create_task_query`/`upload_task_attachments` methods structurally.
- `app/Http/Controllers/BoardAutomationController.php` — `create/update/delete/fetch` automations.
- New permission module `board_management.*` (board, item, automation resources) — add to wherever
  `task_management`/`waba_credential` permissions are currently seeded.

## Docs

Per CLAUDE.md's doc-maintenance table:
- `docs/api.md` — all new endpoints.
- `docs/database.md` — all new tables.
- `docs/business-rules.md` — new "Boards" section: column types, view semantics, automation
  trigger/action types, and the explicit note that this is separate from Task and Project/ProjectTicket.
- `docs/architecture.md` — the new Events/Listener pattern (since it's the first use of Laravel events
  in this codebase) and the new Services listed above.

## Suggested Build Phases (all in v1 scope, sequenced for reviewable PRs)

1. **Foundation**: `boards`/`board_members`/`board_groups`/`board_columns`/`board_items`/
   `item_column_values` migrations + models + `BoardService`/`ItemService` + Table view only.
2. **Kanban + Calendar views**: `BoardViewService::kanbanView`/`calendarView` + corresponding endpoints.
3. **Gantt view**: `item_dependencies` table + `ganttView`.
4. **Collaboration**: `item_comments`/`item_attachments` + controllers, activitylog wiring.
5. **Automations**: `board_automations`/`automation_logs` + events/listener + `AutomationEngineService`.

## Verification

1. Create a board, add 2 groups, add one column of each type (text/status/people/date/number/dropdown/
   checkbox/link), create 3 items with values across those columns.
2. Table view: confirm all items + column values return correctly grouped/ordered.
3. Kanban view: group by the Status column, confirm items bucket correctly and moving an item's status
   value moves it between buckets.
4. Calendar view: confirm items with `due_date` in the queried month appear, others don't.
5. Gantt view: add a dependency between two items, confirm both items and the dependency edge are
   returned with correct date ranges.
6. Automations: create a "when Status changes to Done → notify assigned People" automation, change an
   item's status via the API, confirm a push notification fires and an `automation_logs` row is written;
   then deactivate the automation and confirm it no longer fires.
7. Confirm existing `/task/*` and Project/ProjectTicket endpoints are completely unaffected (no shared
   tables/models touched).
