MIF_E31232103/app/Http/Controllers/AdminRental/PromoController.php

217 lines
7.7 KiB
PHP

<?php
namespace App\Http\Controllers\AdminRental;
use App\Http\Controllers\Controller;
use App\Http\Requests\StorePromoRequest;
use App\Http\Requests\UpdatePromoRequest;
use App\Models\Promo;
use App\Models\RentalCompany;
use App\Services\ActivityLogService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
class PromoController extends Controller
{
public function __construct(
private readonly ActivityLogService $activityLogService,
) {}
public function index(Request $request): View|RedirectResponse
{
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()->route('admin-rental.dashboard')->with('error', 'Akun admin rental ini belum memiliki rental company.');
}
$request->validate([
'search' => ['nullable', 'string', 'max:100'],
'status' => ['nullable', 'in:active,inactive'],
]);
$promos = Promo::query()
->where('rental_company_id', $rentalCompany->id)
->when($request->filled('search'), function ($query) use ($request): void {
$search = $request->string('search')->toString();
$query->where(function ($subQuery) use ($search): void {
$subQuery->where('title', 'like', '%' . $search . '%')
->orWhere('promo_code', 'like', '%' . strtoupper($search) . '%');
});
})
->when($request->filled('status'), function ($query) use ($request): void {
$query->where('status', $request->string('status')->toString());
})
->latest('id')
->paginate(10)
->withQueryString();
return view('admin-rental.promos.index', compact('promos', 'rentalCompany'));
}
public function create(): View|RedirectResponse
{
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
return redirect()->route('admin-rental.dashboard')->with('error', 'Akun admin rental ini belum memiliki rental company.');
}
$this->authorize('create', Promo::class);
$promo = new Promo([
'discount_type' => Promo::DISCOUNT_PERCENT,
'status' => Promo::STATUS_ACTIVE,
'min_transaction' => 0,
'loyal_only' => false,
]);
return view('admin-rental.promos.create', compact('promo', 'rentalCompany'));
}
public function store(StorePromoRequest $request): RedirectResponse
{
$this->authorize('create', Promo::class);
$rentalCompany = $this->getRentalCompanyOrAbort();
$validated = $request->validated();
$promo = Promo::create([
'rental_company_id' => $rentalCompany->id,
'title' => $validated['title'],
'promo_code' => strtoupper($validated['promo_code']),
'description' => $validated['description'] ?? null,
'discount_type' => $validated['discount_type'],
'discount_value' => $validated['discount_value'],
'min_transaction' => $validated['min_transaction'] ?? 0,
'start_date' => $validated['start_date'],
'end_date' => $validated['end_date'],
'quota' => $validated['quota'] ?? null,
'used_count' => 0,
'loyal_only' => $request->boolean('loyal_only'),
'status' => $validated['status'],
]);
$this->activityLogService->log(
action: 'promo.created',
description: 'Admin rental membuat promo: ' . $validated['title'],
targetType: 'promo',
targetId: $promo->id,
meta: ['promo_code' => $promo->promo_code, 'discount_value' => $promo->discount_value]
);
return redirect()->route('admin-rental.promos.index')->with('success', 'Promo berhasil ditambahkan.');
}
public function edit(Promo $promo): View
{
$rentalCompany = $this->getRentalCompanyOrAbort();
$this->ensurePromoBelongsToRental($promo, $rentalCompany->id);
$this->authorize('update', $promo);
return view('admin-rental.promos.edit', compact('promo', 'rentalCompany'));
}
public function update(UpdatePromoRequest $request, Promo $promo): RedirectResponse
{
$this->authorize('update', $promo);
$rentalCompany = $this->getRentalCompanyOrAbort();
$this->ensurePromoBelongsToRental($promo, $rentalCompany->id);
$validated = $request->validated();
$promo->update([
'title' => $validated['title'],
'promo_code' => strtoupper($validated['promo_code']),
'description' => $validated['description'] ?? null,
'discount_type' => $validated['discount_type'],
'discount_value' => $validated['discount_value'],
'min_transaction' => $validated['min_transaction'] ?? 0,
'start_date' => $validated['start_date'],
'end_date' => $validated['end_date'],
'quota' => $validated['quota'] ?? null,
'loyal_only' => $request->boolean('loyal_only'),
'status' => $validated['status'],
]);
$this->activityLogService->log(
action: 'promo.updated',
description: 'Admin rental memperbarui promo: ' . $validated['title'],
targetType: 'promo',
targetId: $promo->id,
meta: ['promo_code' => $promo->promo_code, 'discount_value' => $promo->discount_value]
);
return redirect()->route('admin-rental.promos.index')->with('success', 'Promo berhasil diperbarui.');
}
public function destroy(Promo $promo): RedirectResponse
{
$this->authorize('delete', $promo);
$rentalCompany = $this->getRentalCompanyOrAbort();
$this->ensurePromoBelongsToRental($promo, $rentalCompany->id);
$promoCode = $promo->promo_code;
$promoId = $promo->id;
$promo->delete();
$this->activityLogService->log(
action: 'promo.deleted',
description: 'Admin rental menghapus promo: ' . $promoCode,
targetType: 'promo',
targetId: $promoId,
meta: ['promo_code' => $promoCode]
);
return redirect()->route('admin-rental.promos.index')->with('success', 'Promo berhasil dihapus.');
}
public function toggle(Promo $promo): RedirectResponse
{
$this->authorize('update', $promo);
$rentalCompany = $this->getRentalCompanyOrAbort();
$this->ensurePromoBelongsToRental($promo, $rentalCompany->id);
$oldStatus = $promo->status;
$newStatus = $promo->status === Promo::STATUS_ACTIVE ? Promo::STATUS_INACTIVE : Promo::STATUS_ACTIVE;
$promo->update([
'status' => $newStatus,
]);
$this->activityLogService->log(
action: 'promo.toggled',
description: 'Admin rental mengubah status promo: ' . $promo->promo_code . ' dari ' . $oldStatus . ' ke ' . $newStatus,
targetType: 'promo',
targetId: $promo->id,
meta: ['old_status' => $oldStatus, 'new_status' => $newStatus]
);
return back()->with('success', 'Status promo berhasil diperbarui.');
}
private function getRentalCompany(): ?RentalCompany
{
return Auth::user()?->rentalCompany;
}
private function getRentalCompanyOrAbort(): RentalCompany
{
$rentalCompany = $this->getRentalCompany();
if (!$rentalCompany) {
abort(404);
}
return $rentalCompany;
}
private function ensurePromoBelongsToRental(Promo $promo, int $rentalCompanyId): void
{
if ((int) $promo->rental_company_id !== $rentalCompanyId) {
abort(404);
}
}
}