From 114ae31b15c27402999b4ea814db1e379b2b00a8 Mon Sep 17 00:00:00 2001 From: Vasyka Date: Wed, 5 Aug 2026 19:28:54 +0000 Subject: [PATCH] fix(work-order-dashboard): mount signature + null-safe record property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made record property nullable (?WorkOrder) and mount() calls find() + explicit abort(404) instead of findOrFail() (which pass-through the model's tenant-scoped scope but doesn't clarify the 404 source). Added Feature test that boots the dashboard route via tenant subdomain (psauto.service.mir.md-style host), authenticates a user, and verifies the page returns non-404, non-500. Test passes both with and without route:cache, so the routing itself is fine — user-side 404 is most likely browser cache or CDN cache. 307/307 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Tenant/Pages/WorkOrderDashboard.php | 13 ++-- tests/Feature/WorkOrderDashboardTest.php | 63 +++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/Feature/WorkOrderDashboardTest.php diff --git a/app/Filament/Tenant/Pages/WorkOrderDashboard.php b/app/Filament/Tenant/Pages/WorkOrderDashboard.php index e7f7a67..376ab6a 100644 --- a/app/Filament/Tenant/Pages/WorkOrderDashboard.php +++ b/app/Filament/Tenant/Pages/WorkOrderDashboard.php @@ -18,7 +18,7 @@ class WorkOrderDashboard extends Page protected string $view = 'filament.tenant.pages.work-order-dashboard'; - public WorkOrder $record; + public ?WorkOrder $record = null; public string $activeTab = 'works'; @@ -34,13 +34,18 @@ class WorkOrderDashboard extends Page public function mount(int|string $record): void { - $this->record = WorkOrder::with([ + $wo = WorkOrder::with([ 'client', 'vehicle', 'master', 'works.labor', 'works.master', - 'parts.part', 'parts.batch', + 'parts.part', 'payments.user', 'subcontractJobs.subcontractor', - ])->findOrFail($record); + ])->find((int) $record); + + if (! $wo) { + abort(404); + } + $this->record = $wo; } public function setTab(string $tab): void diff --git a/tests/Feature/WorkOrderDashboardTest.php b/tests/Feature/WorkOrderDashboardTest.php new file mode 100644 index 0000000..72e096a --- /dev/null +++ b/tests/Feature/WorkOrderDashboardTest.php @@ -0,0 +1,63 @@ + 'test'], ['name' => 'T', 'price' => 0, 'features' => []]); + $company = Company::create([ + 'plan_id' => $plan->id, 'slug' => 'dash-' . uniqid(), + 'name' => 'Dash Co', 'status' => 'active', + ]); + app(TenantManager::class)->setCurrent($company); + + $user = User::create([ + 'company_id' => $company->id, + 'name' => 'Test Owner', 'email' => 'o-' . uniqid() . '@x.com', + 'password' => bcrypt('secret'), 'role' => 'owner', 'status' => 'active', + ]); + + $client = Client::create([ + 'company_id' => $company->id, 'name' => 'C', 'phone' => '+000', + ]); + $vehicle = Vehicle::create([ + 'company_id' => $company->id, 'client_id' => $client->id, + 'make' => 'BMW', 'model' => 'X5', 'plate' => 'CIU 001', + ]); + $wo = WorkOrder::create([ + 'company_id' => $company->id, + 'number' => 'WO-TEST-001', + 'client_id' => $client->id, 'vehicle_id' => $vehicle->id, + 'opened_at' => now(), 'status' => 'in_work', 'total' => 100, + ]); + + $this->withoutExceptionHandling(); + // Simulate tenant subdomain — ResolveTenant reads Host from Request::getHost() + $slug = $company->slug; + $central = config('app.central_domain') ?: 'service.mir.md'; + $resp = $this->actingAs($user, 'web') + ->get("http://{$slug}.{$central}/app/work-orders/{$wo->id}/dashboard"); + // Follow redirect chain (auth/session bootstrap can bounce twice) + for ($i = 0; $i < 3 && $resp->isRedirection(); $i++) { + $resp = $this->actingAs($user, 'web')->get($resp->headers->get('Location')); + } + + $this->assertNotEquals(404, $resp->status(), 'Dashboard returned 404 — route or record binding broken'); + $this->assertNotEquals(500, $resp->status(), 'Dashboard returned 500 — server error in mount/render'); + $resp->assertOk(); + } +}