with('establishment:id,name'); $this->scopeEstablishmentQuery($query); $promotions = $query ->orderByDesc('starts_at') ->get() ->map(fn (Promotion $promotion) => $this->formatPromotion($promotion)); return Inertia::render('Supervisor/Promotions/Index', [ 'promotions' => $promotions, 'establishments' => $this->establishmentOptions(), 'machineTypes' => $this->machineTypeOptions(), 'discountTypes' => $this->discountTypeOptions(), ]); } 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 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 */ 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', ]; } }