File: //home/armgroup/libs/app/Http/Livewire/Admin/Discount/Create.php
<?php
namespace App\Http\Livewire\Admin\Discount;
use App\Enums\DiscountableType;
use App\Enums\DiscountType;
use App\Enums\NotificationType;
use App\Events\DiscountSaved;
use App\Http\Livewire\ConvertEmptyStringsToNull;
use App\Http\Livewire\General;
use App\Models\Brand;
use App\Models\Category;
use App\Models\Discount;
use App\Models\Product;
use App\Models\User;
use BenSampo\Enum\Rules\EnumValue;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Livewire\Component;
use Spatie\Permission\Models\Role;
class Create extends Component
{
use ConvertEmptyStringsToNull, General;
public $title;
public $code;
public $type;
public $amount;
public $minimum_order_price;
public $usage;
public $start_date;
public $end_date;
public $discountable_type;
public $items;
public $item_id;
public $roles;
public $role_id;
public $max_point;
public $min_point;
public $max_wallet;
public $min_wallet;
public $users;
public $user_id;
public $notification_type;
public function render()
{
return view('livewire.admin.discount.create');
}
public function hydrate()
{
$this->dispatchBrowserEvent('add-select2-event');
}
public function mount()
{
$this->type = DiscountType::PERCENT;
$this->notification_type = NotificationType::EMAIL;
$this->roles = Role::select('id', 'name')->get();
$this->role_id = [];
$this->discountable_type = DiscountableType::PRODUCT;
$this->items = Product::where('status', true)->select('id', 'name')->get();
$this->item_id = [];
$this->user_id = [];
$this->users = User::with('roles')->where('active', true)->select('id', 'name')->get();
}
public function updatedDiscountableType($value)
{
$this->item_id = [];
switch ($value) {
case DiscountableType::BRAND :
$this->items = Brand::select('id', 'name')->get();
break;
case DiscountableType::CATEGORY :
$this->items = Category::where('status', true)
->where('type', Product::class)
->select('id', 'name')
->get();
break;
case DiscountableType::PRODUCT :
$this->items = Product::where('status', true)->select('id', 'name')->get();
break;
default:
$this->items = [];
}
}
public function filterUsers()
{
$this->user_id = [];
$this->validate([
'min_point' => 'nullable|min:0|max:999999999999|integer',
'max_point' => 'nullable|min:0|max:999999999999|integer',
'min_wallet' => 'nullable|min:0|max:999999999999|integer',
'max_wallet' => 'nullable|min:0|max:999999999999|integer',
'role_id' => 'nullable|array',
'role_id.*' => 'nullable|in:customer,'.implode(',', $this->roles->pluck('id')->toArray()),
]);
$this->users = User::with('roles')
->where('active', true)
->when(count($this->role_id), function ($q) {
return $q->whereHas('roles', fn (Builder $builder) => $builder->whereIn('id', $this->role_id))
->when(in_array('customer', $this->role_id), function ($query) {
return $query->orWhereDoesntHave('roles');
});
})
->when($this->min_point, function ($q) {
return $q->whereHas('points', fn (Builder $builder) => $builder->havingRaw('SUM(amount) >= '.$this->min_point));
})
->when($this->max_point, function ($q) {
return $q->whereHas('points', fn (Builder $builder) => $builder->havingRaw('SUM(amount) <= '.$this->max_point));
})
->when($this->min_wallet, function ($q) {
return $q->whereHas('wallets', fn (Builder $builder) => $builder->havingRaw('SUM(amount) >= '.$this->min_wallet));
})
->when($this->max_wallet, function ($q) {
return $q->whereHas('wallets', fn (Builder $builder) => $builder->havingRaw('SUM(amount) <= '.$this->max_wallet));
})
->select('id', 'name')
->get();
$this->ajaxDoneMessage('لیست کاربران آپدیت شد', 'info');
}
protected function rules()
{
$max = $this->type == DiscountType::PERCENT ? 99 : 1000000000;
return [
'title' => ['required', 'string', 'max:250'],
'code' => ['required', 'string', 'max:20', 'min:5', 'unique:discounts'],
'type' => ['required', new EnumValue(DiscountType::class, false)],
'discountable_type' => ['required', new EnumValue(DiscountableType::class, false)],
'amount' => ['required', 'integer', 'min:1', 'max:'.$max],
'minimum_order_price' => ['nullable', 'integer', 'min:1', 'max:1000000000'],
'usage' => ['nullable', 'integer', 'between:1,100'],
'start_date' => ['required', 'date'],
'end_date' => ['required', 'date', 'after:start_date'],
'item_id' => ['nullable', 'array'],
'user_id' => ['nullable', 'array'],
'user_id.*' => ['exists:users,id'],
'notification_type' => ['required', new EnumValue(NotificationType::class, false)],
];
}
public function store()
{
$this->validate();
if (count($this->item_id) && count(array_diff($this->item_id, $this->items->pluck('id')->toArray()))) {
$this->addError('item_id', 'آیتم انتخاب شده معتبر نیست');
return;
}
DB::transaction(function () {
$discount = Discount::create([
'user_id' => auth()->id(),
'title' => $this->title,
'code' => $this->code,
'type' => $this->type,
'amount' => $this->amount,
'minimum_order_price' => $this->minimum_order_price,
'usage' => $this->usage,
'start_date' => $this->start_date,
'end_date' => $this->end_date,
'discountable_type' => $this->discountable_type,
'discountable_items' => count($this->item_id) ? $this->item_id : null,
'notification_type' => $this->notification_type,
'is_general' => ! count($this->user_id),
]);
if (count($this->user_id)) {
$discount->users()->attach($this->user_id,
['created_at' => Carbon::now(), 'updated_at' => Carbon::now()]);
}
DiscountSaved::dispatch($discount);
});
$this->doneMessage();
return redirect()->route('admin.discounts.index');
}
}