From a2166668674d27eca4e8761e44af17703f6a9246 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sun, 28 Jun 2026 22:42:38 +0000 Subject: [PATCH] Fix stale Staff On Site count after sign-out. Compute staff presence stats outside the dashboard cache so counts update immediately when employees sign out. Co-authored-by: Cursor --- .../Frontdesk/DashboardController.php | 35 +++++++++++-------- .../Feature/FrontdeskEmployeePresenceTest.php | 22 ++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Frontdesk/DashboardController.php b/app/Http/Controllers/Frontdesk/DashboardController.php index 30793b9..f39e69f 100644 --- a/app/Http/Controllers/Frontdesk/DashboardController.php +++ b/app/Http/Controllers/Frontdesk/DashboardController.php @@ -4,8 +4,8 @@ namespace App\Http\Controllers\Frontdesk; use App\Http\Controllers\Controller; use App\Http\Controllers\Frontdesk\Concerns\ScopesToAccount; -use App\Models\Employee; use App\Models\EmployeePresence; +use App\Models\Organization; use App\Models\Visit; use App\Services\Frontdesk\OrganizationResolver; use Illuminate\Http\Request; @@ -28,27 +28,15 @@ class DashboardController extends Controller $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request)); $cacheKey = "fd:dashboard:{$owner}:{$organization->id}:".($branchScope ?? 'all'); - $stats = Cache::remember($cacheKey, 60, function () use ($visitQuery, $owner, $organization, $branchScope) { + $stats = Cache::remember($cacheKey, 60, function () use ($visitQuery) { $today = (clone $visitQuery)->where(function ($q) { $q->whereDate('checked_in_at', today()) ->orWhereDate('scheduled_at', today()); }); - $employeeIds = Employee::owned($owner) - ->where('organization_id', $organization->id) - ->where('active', true); - if ($branchScope !== null) { - $employeeIds->where('branch_id', $branchScope); - } - $employeeIds = $employeeIds->pluck('id'); - - $presenceQuery = EmployeePresence::query()->whereIn('employee_id', $employeeIds); - return [ 'visitors_today' => (clone $today)->count(), 'currently_inside' => (clone $visitQuery)->currentlyInside()->count(), - 'staff_on_site' => (clone $presenceQuery)->where('status', EmployeePresence::STATUS_ON_SITE)->count(), - 'staff_stepped_out' => (clone $presenceQuery)->where('status', EmployeePresence::STATUS_STEPPED_OUT)->count(), 'expected_arrivals' => (clone $visitQuery)->whereIn('status', [ Visit::STATUS_EXPECTED, Visit::STATUS_SCHEDULED, @@ -71,6 +59,8 @@ class DashboardController extends Controller ]; }); + $stats = array_merge($stats, $this->staffPresenceStats($request, $owner, $organization)); + $currentVisitors = (clone $visitQuery)->currentlyInside() ->with(['visitor', 'host']) ->latest('checked_in_at') @@ -112,4 +102,21 @@ class DashboardController extends Controller 'stats', 'currentVisitors', 'expectedVisitors', 'pendingApprovals', 'staffSteppedOut', 'organization', )); } + + /** @return array{staff_on_site: int, staff_stepped_out: int} */ + protected function staffPresenceStats(Request $request, string $owner, Organization $organization): array + { + $query = EmployeePresence::query() + ->whereHas('employee', function ($q) use ($owner, $organization, $request) { + $q->owned($owner) + ->where('organization_id', $organization->id) + ->where('active', true); + $this->scopeToBranch($request, $q, 'branch_id'); + }); + + return [ + 'staff_on_site' => (clone $query)->where('status', EmployeePresence::STATUS_ON_SITE)->count(), + 'staff_stepped_out' => (clone $query)->where('status', EmployeePresence::STATUS_STEPPED_OUT)->count(), + ]; + } } diff --git a/tests/Feature/FrontdeskEmployeePresenceTest.php b/tests/Feature/FrontdeskEmployeePresenceTest.php index 9d72b66..6443861 100644 --- a/tests/Feature/FrontdeskEmployeePresenceTest.php +++ b/tests/Feature/FrontdeskEmployeePresenceTest.php @@ -10,6 +10,7 @@ use App\Models\Organization; use App\Models\User; use App\Services\Frontdesk\EmployeePresenceService; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Cache; use Tests\TestCase; class FrontdeskEmployeePresenceTest extends TestCase @@ -155,4 +156,25 @@ class FrontdeskEmployeePresenceTest extends TestCase ->assertSee('Jane Staff', false) ->assertSee('Staff on premises', false); } + + public function test_dashboard_staff_on_site_updates_immediately_after_sign_out(): void + { + Cache::flush(); + + $employee = $this->createEmployee(); + $service = app(EmployeePresenceService::class); + $service->signIn($employee); + + $this->actingAs($this->user) + ->get(route('frontdesk.dashboard')) + ->assertOk() + ->assertViewHas('stats', fn (array $stats) => $stats['staff_on_site'] === 1); + + $service->signOut($employee); + + $this->actingAs($this->user) + ->get(route('frontdesk.dashboard')) + ->assertOk() + ->assertViewHas('stats', fn (array $stats) => $stats['staff_on_site'] === 0); + } }