Files
backend/app/Http/Controllers/Supervisor/PricingPageController.php
T
2026-06-28 12:29:53 +02:00

179 lines
6.0 KiB
PHP

<?php
namespace App\Http\Controllers\Supervisor;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Supervisor\Concerns\ScopesSupervisorResources;
use App\Models\Establishment;
use App\Models\PricingRule;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class PricingPageController extends Controller
{
use ScopesSupervisorResources;
public function index(Request $request): Response
{
$query = PricingRule::query()
->with(['establishment:id,name', 'machine:id,uuid,name']);
$this->scopeEstablishmentQuery($query);
$rules = $query
->orderBy('priority')
->orderBy('slot_start')
->get()
->map(fn (PricingRule $rule) => $this->formatRule($rule));
return Inertia::render('Supervisor/Pricing/Index', [
'rules' => $rules,
'establishments' => $this->establishmentOptions(),
'machineTypes' => $this->machineTypeOptions(),
'dayTypes' => $this->dayTypeOptions(),
]);
}
public function store(Request $request): RedirectResponse
{
$validated = $this->validateRule($request);
$this->assertEstablishmentAccessible((int) $validated['establishment_id']);
PricingRule::query()->create($validated);
return redirect()->route('supervisor.pricing.index')
->with('success', 'Règle tarifaire créée.');
}
public function update(Request $request, int $id): RedirectResponse
{
$rule = $this->findAccessibleRule($id);
$validated = $this->validateRule($request);
$this->assertEstablishmentAccessible((int) $validated['establishment_id']);
$rule->update($validated);
return redirect()->route('supervisor.pricing.index')
->with('success', 'Règle tarifaire mise à jour.');
}
public function destroy(int $id): RedirectResponse
{
$rule = $this->findAccessibleRule($id);
$rule->delete();
return redirect()->route('supervisor.pricing.index')
->with('success', 'Règle tarifaire supprimée.');
}
/**
* @return array<string, mixed>
*/
private function validateRule(Request $request): array
{
return $request->validate([
'establishment_id' => ['required', 'integer', 'exists:establishments,id'],
'machine_id' => ['nullable', 'integer', 'exists:machines,id'],
'machine_type' => ['nullable', 'in:washer_small,washer_large,dryer_small,dryer_large'],
'day_type' => ['required', 'in:weekday,weekend,holiday,all'],
'slot_start' => ['required', 'date_format:H:i'],
'slot_end' => ['required', 'date_format:H:i', 'after:slot_start'],
'price' => ['required', 'numeric', 'min:0'],
'label' => ['nullable', 'string', 'max:100'],
'requires_app' => ['boolean'],
'priority' => ['integer', 'min:0'],
'is_active' => ['boolean'],
]);
}
private function findAccessibleRule(int $id): PricingRule
{
$query = PricingRule::query()->where('id', $id);
$this->scopeEstablishmentQuery($query);
return $query->firstOrFail();
}
private function assertEstablishmentAccessible(int $establishmentId): void
{
$supervisor = $this->supervisor();
$exists = Establishment::query()
->where('id', $establishmentId)
->where('organization_id', $supervisor->organization_id)
->when($supervisor->establishment_id, fn ($q) => $q->where('id', $supervisor->establishment_id))
->exists();
abort_unless($exists, 403);
}
/**
* @return array<string, mixed>
*/
private function formatRule(PricingRule $rule): array
{
return [
'id' => $rule->id,
'establishment_id' => $rule->establishment_id,
'establishment_name' => $rule->establishment?->name,
'machine_id' => $rule->machine_id,
'machine_name' => $rule->machine?->name,
'machine_type' => $rule->machine_type,
'machine_type_label' => $rule->machine_type ? ($this->machineTypeOptions()[$rule->machine_type] ?? $rule->machine_type) : null,
'day_type' => $rule->day_type,
'day_type_label' => $this->dayTypeOptions()[$rule->day_type] ?? $rule->day_type,
'slot_start' => $rule->slot_start ? substr((string) $rule->slot_start, 0, 5) : null,
'slot_end' => $rule->slot_end ? substr((string) $rule->slot_end, 0, 5) : null,
'price' => (float) $rule->price,
'label' => $rule->label,
'requires_app' => $rule->requires_app,
'priority' => $rule->priority,
'is_active' => $rule->is_active,
];
}
/**
* @return array<int, array{id: int, name: string}>
*/
private function establishmentOptions(): array
{
$supervisor = $this->supervisor();
return Establishment::query()
->where('organization_id', $supervisor->organization_id)
->when($supervisor->establishment_id, fn ($q) => $q->where('id', $supervisor->establishment_id))
->orderBy('name')
->get(['id', 'name'])
->map(fn (Establishment $e) => ['id' => $e->id, 'name' => $e->name])
->all();
}
/**
* @return array<string, string>
*/
private function machineTypeOptions(): array
{
return [
'washer_small' => 'Lave-linge petit',
'washer_large' => 'Lave-linge grand',
'dryer_small' => 'Sèche-linge petit',
'dryer_large' => 'Sèche-linge grand',
];
}
/**
* @return array<string, string>
*/
private function dayTypeOptions(): array
{
return [
'all' => 'Tous les jours',
'weekday' => 'Semaine',
'weekend' => 'Week-end',
'holiday' => 'Jours fériés',
];
}
}