with('establishment:id,name'); $this->scopeEstablishmentQuery($query); $this->applyEstablishmentFilter($request, $query); if ($request->filled('machine_type')) { $query->where('machine_type', $request->string('machine_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('description', 'like', "%{$search}%"); } $promotions = $query ->tap(fn ($builder) => $this->applySort($request, $builder, [ 'establishment' => fn ($builder, string $direction) => $this->sortByRelatedEstablishment( $builder, 'promotions', 'establishment_id', $direction, ), 'discount_value' => 'discount_value', 'starts_at' => 'starts_at', 'ends_at' => 'ends_at', 'machine_type' => 'machine_type', 'is_active' => 'is_active', ], 'starts_at', 'desc')) ->paginate($this->supervisorListPerPage($request)) ->withQueryString() ->through(fn (Promotion $promotion) => $this->formatPromotion($promotion)); return Inertia::render('Supervisor/Promotions/Index', [ 'promotions' => $promotions, 'establishments' => $this->establishmentOptions(), 'machineTypes' => $this->machineTypeOptions(), 'discountTypes' => $this->discountTypeOptions(), 'filters' => [ 'establishment_id' => $request->filled('establishment_id') ? (int) $request->input('establishment_id') : null, 'machine_type' => $request->string('machine_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() ?: 'starts_at', 'direction' => $request->string('direction')->toString() === 'desc' ? 'desc' : 'asc', 'per_page' => $this->supervisorListPerPage($request), ], ]); } public function store(Request $request): RedirectResponse { $validated = $this->validatePromotion($request); $this->assertEstablishmentAccessible((int) $validated['establishment_id']); Promotion::query()->create($validated); return redirect()->route('supervisor.promotions.index') ->with('success', 'Promotion créée.'); } public function update(Request $request, int $id): RedirectResponse { $promotion = $this->findAccessiblePromotion($id); $validated = $this->validatePromotion($request); $this->assertEstablishmentAccessible((int) $validated['establishment_id']); $promotion->update($validated); return redirect()->route('supervisor.promotions.index') ->with('success', 'Promotion mise à jour.'); } public function destroy(int $id): RedirectResponse { $promotion = $this->findAccessiblePromotion($id); $promotion->delete(); return redirect()->route('supervisor.promotions.index') ->with('success', 'Promotion supprimée.'); } /** * @return array */ private function validatePromotion(Request $request): array { return $request->validate([ 'establishment_id' => ['required', 'integer', 'exists:establishments,id'], 'machine_type' => ['required', 'in:washer_small,washer_large,dryer_small,dryer_large,all'], 'discount_type' => ['required', 'in:percent,fixed'], 'discount_value' => ['required', 'numeric', 'min:0'], 'starts_at' => ['required', 'date'], 'ends_at' => ['required', 'date', 'after:starts_at'], 'description' => ['nullable', 'string', 'max:500'], 'is_active' => ['boolean'], ]); } private function findAccessiblePromotion(int $id): Promotion { $query = Promotion::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 */ private function formatPromotion(Promotion $promotion): array { return [ 'id' => $promotion->id, 'establishment_id' => $promotion->establishment_id, 'establishment_name' => $promotion->establishment?->name, 'machine_type' => $promotion->machine_type, 'machine_type_label' => $this->machineTypeOptions()[$promotion->machine_type] ?? $promotion->machine_type, 'discount_type' => $promotion->discount_type, 'discount_type_label' => $this->discountTypeOptions()[$promotion->discount_type] ?? $promotion->discount_type, 'discount_value' => (float) $promotion->discount_value, 'starts_at' => $promotion->starts_at?->format('Y-m-d\TH:i'), 'ends_at' => $promotion->ends_at?->format('Y-m-d\TH:i'), 'description' => $promotion->description, 'is_active' => $promotion->is_active, ]; } /** * @return array */ private function machineTypeOptions(): array { return [ 'all' => 'Toutes les machines', 'washer_small' => 'Lave-linge petit', 'washer_large' => 'Lave-linge grand', 'dryer_small' => 'Sèche-linge petit', 'dryer_large' => 'Sèche-linge grand', ]; } /** * @return array */ private function discountTypeOptions(): array { return [ 'percent' => 'Pourcentage', 'fixed' => 'Montant fixe', ]; } }