This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
<?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);
|
||||
$this->applyEstablishmentFilter($request, $query);
|
||||
|
||||
if ($request->filled('machine_type')) {
|
||||
$query->where('machine_type', $request->string('machine_type'));
|
||||
}
|
||||
|
||||
if ($request->filled('day_type')) {
|
||||
$query->where('day_type', $request->string('day_type'));
|
||||
}
|
||||
|
||||
if ($request->has('is_active') && $request->string('is_active')->toString() !== '') {
|
||||
$query->where('is_active', $request->boolean('is_active'));
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->string('search');
|
||||
$query->where('label', 'like', "%{$search}%");
|
||||
}
|
||||
|
||||
$rules = $query
|
||||
->tap(fn ($builder) => $this->applySort($request, $builder, [
|
||||
'establishment' => fn ($builder, string $direction) => $this->sortByRelatedEstablishment(
|
||||
$builder,
|
||||
'pricing_rules',
|
||||
'establishment_id',
|
||||
$direction,
|
||||
),
|
||||
'slot_start' => 'slot_start',
|
||||
'machine_type' => 'machine_type',
|
||||
'price' => 'price',
|
||||
'priority' => 'priority',
|
||||
'is_active' => 'is_active',
|
||||
], 'priority', 'asc'))
|
||||
->paginate($this->supervisorListPerPage($request))
|
||||
->withQueryString()
|
||||
->through(fn (PricingRule $rule) => $this->formatRule($rule));
|
||||
|
||||
return Inertia::render('Supervisor/Pricing/Index', [
|
||||
'rules' => $rules,
|
||||
'establishments' => $this->establishmentOptions(),
|
||||
'machineTypes' => $this->machineTypeOptions(),
|
||||
'dayTypes' => $this->dayTypeOptions(),
|
||||
'filters' => [
|
||||
'establishment_id' => $request->filled('establishment_id') ? (int) $request->input('establishment_id') : null,
|
||||
'machine_type' => $request->string('machine_type')->toString() ?: null,
|
||||
'day_type' => $request->string('day_type')->toString() ?: null,
|
||||
'is_active' => $request->has('is_active') && $request->string('is_active')->toString() !== ''
|
||||
? ($request->boolean('is_active') ? '1' : '0')
|
||||
: null,
|
||||
'search' => $request->string('search')->toString() ?: null,
|
||||
'sort' => $request->string('sort')->toString() ?: 'priority',
|
||||
'direction' => $request->string('direction')->toString() === 'desc' ? 'desc' : 'asc',
|
||||
'per_page' => $this->supervisorListPerPage($request),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
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<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',
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user