From 6956f7bf95c4bbbbcf9b1375b1f1ee28f8e168c5 Mon Sep 17 00:00:00 2001 From: Saad Zoubir Date: Tue, 24 Mar 2026 11:12:11 +0100 Subject: [PATCH] fix: correct architecture doc drift and add withPivot gotchas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Architecture doc fixes: - Replace `deadline` → `due_date` in all code examples (5 occurrences) - Replace `Declaration::workspace($workspace)` → `Declaration::where('workspace_id', ...)` (no such query scope exists; workspace() is a BelongsTo relationship) - Add missing `mise_en_demeure` status to transition table and flow diagram - Update transition rules: en_attente_client can transition to mise_en_demeure Project context additions: - Document WorkspaceUser pivot fields and withPivot requirement - Document correct column name (due_date not deadline) - Document Declaration scoping pattern (no workspace scope) - Document all 6 declaration statuses including mise_en_demeure Resolves Epic 2 retro action items A3, A4 (carried since Epic 1). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../planning-artifacts/architecture.md | 23 +++++++++++-------- _bmad-output/project-context.md | 6 ++++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/_bmad-output/planning-artifacts/architecture.md b/_bmad-output/planning-artifacts/architecture.md index 4c100c5..ba78798 100644 --- a/_bmad-output/planning-artifacts/architecture.md +++ b/_bmad-output/planning-artifacts/architecture.md @@ -456,6 +456,8 @@ $declarations = Declaration::where('workspace_id', $workspace->id) ``` Created → En cours → En attente client → En cours → Terminé → Fermé → [auto-archive] + ↘ ↗ ↗ + Mise en demeure ──────┘ ───────────┘ ↗ Created → En cours → Terminé → Fermé → [auto-archive] ``` @@ -466,7 +468,8 @@ Created → En cours → Terminé → Fermé → [auto-archive] |---|---|---|---| | `created` | Declaration just created | System | `en_cours` | | `en_cours` | Being worked on | Owner/Manager/Worker | `en_attente_client`, `termine` | -| `en_attente_client` | Waiting for client documents | Owner/Manager/Worker | `en_cours` | +| `en_attente_client` | Waiting for client documents | Owner/Manager/Worker | `en_cours`, `mise_en_demeure` | +| `mise_en_demeure` | Formal notice sent to client | Owner/Manager | `en_cours`, `ferme` | | `termine` | Work completed | Owner/Manager/Worker | `ferme` | | `ferme` | Closed (triggers auto-archive) | Owner/Manager | (archived) | @@ -522,7 +525,7 @@ public function bulkStore(BulkStoreDeclarationRequest $request) 'workspace_id' => $workspace->id, 'client_id' => $item['client_id'], 'type' => $item['type'], - 'deadline' => $item['deadline'], + 'due_date' => $item['due_date'], 'assigned_to' => $item['assigned_to'], 'status' => DeclarationStatus::Created, ]); @@ -560,7 +563,7 @@ protected function applyFilters(Builder $query, Request $request): Builder ) ->when($request->sort, fn ($q, $sort) => $q->orderBy($sort, $request->input('direction', 'asc')) - , fn ($q) => $q->orderBy('deadline', 'asc')); // default sort + , fn ($q) => $q->orderBy('due_date', 'asc')); // default sort } ``` @@ -579,7 +582,7 @@ function applyFilter(key: string, value: string | null) { } ``` -**Default sort: `deadline ASC`** (most urgent first) for declarations. **`name ASC`** for clients. +**Default sort: `due_date ASC`** (most urgent first) for declarations. **`name ASC`** for clients. ### Archive Query Patterns @@ -614,16 +617,16 @@ $dashboardData = Cache::remember( "dashboard:{$workspace->id}:{$user->id}", 300, // 5 minutes fn () => [ - 'total_active' => Declaration::workspace($workspace)->active()->forUser($user, $workspace)->count(), - 'by_status' => Declaration::workspace($workspace)->active()->forUser($user, $workspace) + 'total_active' => Declaration::where('workspace_id', $workspace->id)->active()->forUser($user, $workspace)->count(), + 'by_status' => Declaration::where('workspace_id', $workspace->id)->active()->forUser($user, $workspace) ->selectRaw('status, count(*) as count') ->groupBy('status') ->pluck('count', 'status'), - 'overdue' => Declaration::workspace($workspace)->active()->forUser($user, $workspace) - ->where('deadline', '<', now()) + 'overdue' => Declaration::where('workspace_id', $workspace->id)->active()->forUser($user, $workspace) + ->where('due_date', '<', now()) ->count(), - 'due_this_week' => Declaration::workspace($workspace)->active()->forUser($user, $workspace) - ->whereBetween('deadline', [now(), now()->endOfWeek()]) + 'due_this_week' => Declaration::where('workspace_id', $workspace->id)->active()->forUser($user, $workspace) + ->whereBetween('due_date', [now(), now()->endOfWeek()]) ->count(), ] ); diff --git a/_bmad-output/project-context.md b/_bmad-output/project-context.md index dfb2560..ebe54fc 100644 --- a/_bmad-output/project-context.md +++ b/_bmad-output/project-context.md @@ -154,6 +154,10 @@ _This file contains critical rules and patterns that AI agents must follow when - New business models must add Spatie `LogsActivity` trait + `getActivitylogOptions()` returning `logFillable()->logOnlyDirty()->dontSubmitEmptyLogs()` - New models with files must add Spatie `InteractsWithMedia` trait and implement `HasMedia` - Inertia render paths use lowercase subdirectory: `'clients/Index'`, not `'Clients/Index'` +- **WorkspaceUser pivot fields:** The `workspace_user` pivot table has `role` (cast to `WorkspaceUserRole` enum) and `permissions` (cast to array). Both `User::workspaces()` and `Workspace::users()` use `->withPivot('role', 'permissions')`. Access via `$user->workspaces()->first()->pivot->role`. The `WorkspaceUser` model extends `Pivot` (not `Model`) — use `Pivot::query()` for direct queries, not `WorkspaceUser::find()`. When eager-loading workspace members for controllers, always chain `->withPivot('role', 'permissions')` or the pivot data will be silently null. +- **Declaration column name:** The date column is `due_date`, NOT `deadline` — some older docs may reference `deadline` incorrectly +- **Declaration scoping:** There is no `Declaration::workspace()` query scope. Use `Declaration::where('workspace_id', $workspace->id)` instead. The model has `active()`, `archived()`, and `forUser()` scopes. +- **Declaration statuses:** 6 values — `created`, `en_cours`, `en_attente_client`, `mise_en_demeure`, `termine`, `ferme`. The `mise_en_demeure` status is a formal notice branch from `en_attente_client`. --- @@ -171,4 +175,4 @@ _This file contains critical rules and patterns that AI agents must follow when - Review quarterly for outdated rules - Remove rules that become obvious over time -Last Updated: 2026-03-08 +Last Updated: 2026-03-24