statDate !== null ? Carbon::parse($this->statDate)->startOfDay() : now()->subDay()->startOfDay(); $dayStart = $date->copy(); $dayEnd = $date->copy()->endOfDay(); Establishment::query()->where('is_active', true)->each(function (Establishment $establishment) use ($dayStart, $dayEnd, $date) { DB::transaction(function () use ($establishment, $dayStart, $dayEnd, $date) { $machineIds = $establishment->machines()->pluck('id'); if ($machineIds->isEmpty()) { return; } $totalWashes = Wash::query() ->whereIn('machine_id', $machineIds) ->where('status', 'completed') ->whereBetween('ended_at', [$dayStart, $dayEnd]) ->count(); $totalRevenue = (float) Wash::query() ->whereIn('machine_id', $machineIds) ->where('status', 'completed') ->whereBetween('ended_at', [$dayStart, $dayEnd]) ->sum('cost'); $bookingsCount = Booking::query() ->whereIn('machine_id', $machineIds) ->whereBetween('created_at', [$dayStart, $dayEnd]) ->whereNotIn('status', ['cancelled']) ->count(); $noShowCount = Booking::query() ->whereIn('machine_id', $machineIds) ->where('status', 'no_show') ->whereBetween('slot_start', [$dayStart, $dayEnd]) ->count(); $userIds = Wash::query() ->whereIn('machine_id', $machineIds) ->whereBetween('started_at', [$dayStart, $dayEnd]) ->pluck('user_id') ->unique(); $topUpAmount = $userIds->isEmpty() ? 0.0 : (float) PaymentTransaction::query() ->whereIn('user_id', $userIds) ->where('status', 'succeeded') ->whereBetween('updated_at', [$dayStart, $dayEnd]) ->sum('amount'); $machineCount = max(1, $machineIds->count()); $minutesInDay = 24 * 60; $runningMinutes = Wash::query() ->whereIn('machine_id', $machineIds) ->where('status', 'completed') ->whereBetween('ended_at', [$dayStart, $dayEnd]) ->get(['duration_minutes']) ->sum(fn (Wash $wash) => $wash->duration_minutes ?? 0); $occupancyRate = round(min(100, ($runningMinutes / ($machineCount * $minutesInDay)) * 100), 2); DailyEstablishmentStat::query()->updateOrCreate( [ 'establishment_id' => $establishment->id, 'stat_date' => $date->toDateString(), ], [ 'total_washes' => $totalWashes, 'total_revenue' => $totalRevenue, 'bookings_count' => $bookingsCount, 'no_show_count' => $noShowCount, 'top_up_amount' => $topUpAmount, 'occupancy_rate' => $occupancyRate, ], ); }); }); } }