ldc-boutique-cnc-sable/app/Http/Controllers/Bo/DiscountsController.php

172 lines
5.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Discounts\StoreDiscountRequest;
use App\Http\Requests\Bo\Discounts\UpdateDiscountRequest;
use App\Models\Discount;
use App\Models\Product;
use App\Services\DataTableService;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\TogglesModelStatus;
use Domain\Enums\DiscountType;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class DiscountsController extends Controller
{
use ChangesModelOrder;
use TogglesModelStatus;
public function index(DataTableService $dataTable): View
{
$this->authorize('viewAny', Discount::class);
$query = Discount::query();
$dataTable->sortQuery(Discount::class, $query);
$discounts = $dataTable->paginateQuery($query);
return view('bo.discounts.index', compact('discounts'));
}
public function create(): View
{
$this->authorize('create', Discount::class);
$discountTypes = DiscountType::cases();
$existingProds = Product::query()
->select(['id', 'name'])
->orderBy('name')
->get();
$selectedProds = [];
return view('bo.discounts.create', compact(
'discountTypes',
'existingProds',
'selectedProds'
));
}
public function store(StoreDiscountRequest $request): RedirectResponse
{
$this->authorize('create', Discount::class);
return DB::transaction(function () use ($request) {
$discount = new Discount();
$discount->fill($request->only(
$discount->getFillable()
));
$discount->value = $request->getDiscountValue();
if ($discount->saveOrFail()) {
$this->syncAssociatedProducts(
$request->getAssociatedProductsIds(),
$discount
);
return to_route('bo.discounts.edit', $discount)
->with('success', trans('crud.messages.has_been_created', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
}
return to_route('bo.discounts.create')
->with('error', trans('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
});
}
public function edit(Discount $discount): View
{
$this->authorize('update', $discount);
$discountTypes = DiscountType::cases();
$selectedProds = $discount->products()
->select(['products.id', 'products.name'])
->get();
$existingProds = Product::query()
->select(['id', 'name'])
->whereNotIn('id', $selectedProds->pluck('id'))
->orderBy('name')
->get();
return view('bo.discounts.edit', compact(
'discount',
'discountTypes',
'existingProds',
'selectedProds',
));
}
public function update(UpdateDiscountRequest $request, Discount $discount): RedirectResponse
{
$this->authorize('update', $discount);
return DB::transaction(function () use ($request, $discount) {
$discount->fill($request->only(
$discount->getFillable()
));
$discount->value = $request->getDiscountValue();
$this->syncAssociatedProducts(
$request->getAssociatedProductsIds(),
$discount
);
if ($discount->saveOrFail()) {
return to_route('bo.discounts.edit', $discount)
->with('success', trans('crud.messages.has_been_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
}
return to_route('bo.discounts.edit', $discount)
->with('error', trans('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
});
}
public function destroy(Discount $discount): RedirectResponse
{
$this->authorize('delete', $discount);
return DB::transaction(function () use ($discount) {
if ($discount->deleteOrFail()) {
return to_route('bo.discounts.index')
->with('warning', trans('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
}
return to_route('bo.discounts.edit', $discount)
->with('error', trans('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.discounts', 1)),
]));
});
}
/** @param array<string> $productIdList */
private function syncAssociatedProducts(array $productIdList, Discount $discount): void
{
$discount->products()
->whereNotIn('id', $productIdList)
->update(['discount_id' => null]);
if (! empty($productIdList)) {
Product::query()
->whereIn('id', $productIdList)
->update(['discount_id' => $discount->id]);
}
}
}