115 lines
3.7 KiB
PHP
115 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Exceptions\MachineNotAvailableException;
|
|
use App\Models\Booking;
|
|
use App\Models\Machine;
|
|
use App\Models\User;
|
|
use App\Models\Wash;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
|
|
class WashService
|
|
{
|
|
public function __construct(
|
|
private readonly WalletService $walletService,
|
|
private readonly PricingService $pricingService,
|
|
private readonly MachineIntegrationService $machineIntegrationService,
|
|
private readonly AuditService $auditService,
|
|
) {}
|
|
|
|
public function startWash(
|
|
User $user,
|
|
Machine $machine,
|
|
string $triggerMethod,
|
|
?int $bookingId = null,
|
|
?string $program = null,
|
|
): Wash {
|
|
return DB::transaction(function () use ($user, $machine, $triggerMethod, $bookingId, $program) {
|
|
$machine = Machine::query()->whereKey($machine->id)->lockForUpdate()->firstOrFail();
|
|
|
|
if (! in_array($machine->status, ['available', 'reserved'], true)) {
|
|
throw new MachineNotAvailableException("Statut actuel : {$machine->status}");
|
|
}
|
|
|
|
$booking = null;
|
|
if ($bookingId !== null) {
|
|
$booking = Booking::query()
|
|
->whereKey($bookingId)
|
|
->where('user_id', $user->id)
|
|
->where('machine_id', $machine->id)
|
|
->lockForUpdate()
|
|
->firstOrFail();
|
|
|
|
if (! in_array($booking->status, ['confirmed', 'active'], true)) {
|
|
throw new \RuntimeException('La réservation n\'est pas valide pour démarrer un lavage.');
|
|
}
|
|
}
|
|
|
|
$cost = $booking !== null
|
|
? (float) $booking->reserved_amount
|
|
: $this->pricingService->getActivePrice($machine);
|
|
|
|
if ($booking === null) {
|
|
$this->walletService->debit(
|
|
$user,
|
|
$cost,
|
|
Wash::class,
|
|
null,
|
|
'wash-debit:'.Str::uuid(),
|
|
['machine_id' => $machine->id],
|
|
);
|
|
}
|
|
|
|
$wash = Wash::query()->create([
|
|
'uuid' => (string) Str::uuid(),
|
|
'user_id' => $user->id,
|
|
'machine_id' => $machine->id,
|
|
'booking_id' => $booking?->id,
|
|
'trigger_method' => $triggerMethod,
|
|
'status' => 'pending_start',
|
|
'program' => $program,
|
|
'cost' => $cost,
|
|
]);
|
|
|
|
$result = $this->machineIntegrationService->startCycle($machine, [
|
|
'wash_id' => $wash->id,
|
|
'wash_uuid' => $wash->uuid,
|
|
'program' => $program,
|
|
'requested_by_user_id' => $user->id,
|
|
], $user);
|
|
|
|
if (! $result->success) {
|
|
throw new \RuntimeException('Échec du démarrage du cycle machine.');
|
|
}
|
|
|
|
$command = $machine->commands()->latest('id')->first();
|
|
|
|
$wash->update([
|
|
'status' => 'running',
|
|
'machine_command_id' => $command?->id,
|
|
'started_at' => now(),
|
|
]);
|
|
|
|
if ($booking !== null) {
|
|
$booking->update(['status' => 'active']);
|
|
}
|
|
|
|
$machine->update(['current_user_id' => $user->id]);
|
|
|
|
$this->auditService->log(
|
|
$user,
|
|
'wash.started',
|
|
$wash,
|
|
null,
|
|
$wash->fresh()->toArray(),
|
|
$machine->establishment?->organization_id,
|
|
$machine->establishment_id,
|
|
);
|
|
|
|
return $wash->fresh(['machine', 'booking']);
|
|
});
|
|
}
|
|
}
|