179 lines
6.0 KiB
PHP
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',
|
|
];
|
|
}
|
|
}
|