107 lines
4.0 KiB
PHP
107 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\Booking;
|
|
use App\Models\DailyEstablishmentStat;
|
|
use App\Models\Establishment;
|
|
use App\Models\PaymentTransaction;
|
|
use App\Models\Wash;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class GenerateDailyStats implements ShouldQueue
|
|
{
|
|
use Queueable;
|
|
|
|
public function __construct(
|
|
public ?string $statDate = null,
|
|
) {}
|
|
|
|
public function handle(): void
|
|
{
|
|
$date = $this->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,
|
|
],
|
|
);
|
|
});
|
|
});
|
|
}
|
|
}
|