You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
8.6 KiB
PHP
255 lines
8.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Events\NotificationEvent;
|
|
use App\Services\GeneralService;
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
|
|
class Voucher extends Model
|
|
{
|
|
const UNSOLD = 0;
|
|
|
|
const SOLD = 1;
|
|
|
|
protected $fillable = [
|
|
'name',
|
|
'description',
|
|
'location_profile_id',
|
|
'username',
|
|
'password',
|
|
'quota',
|
|
'profile',
|
|
'comment',
|
|
'is_sold', //menandakan sudah terjual atau belum
|
|
];
|
|
|
|
protected $appends = [
|
|
'validate_price',
|
|
'validate_display_price',
|
|
'validate_price_poin',
|
|
'validate_bonus_poin',
|
|
'discount',
|
|
'status',
|
|
'created_at_formated',
|
|
];
|
|
|
|
private static $instance = [];
|
|
|
|
private static function getInstance()
|
|
{
|
|
if (count(self::$instance) == 0) {
|
|
self::$instance = [
|
|
'customer' => Customer::find(auth()->guard('customer')->id()),
|
|
];
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public function locationProfile()
|
|
{
|
|
return $this->belongsTo(LocationProfile::class, 'location_profile_id');
|
|
}
|
|
|
|
public function validatePrice(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
if ($this->locationProfile->prices->count() > 0) {
|
|
$price = $this->locationProfile->prices;
|
|
if (auth()->guard('customer')->check()) {
|
|
$customer = self::getInstance()['customer'];
|
|
|
|
return $price->where('customer_level_id', $customer->customer_level_id)
|
|
->value('price');
|
|
}
|
|
|
|
return $price->max('price');
|
|
}
|
|
|
|
return $this->locationProfile->price;
|
|
});
|
|
}
|
|
|
|
public function validateDisplayPrice(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
if ($this->locationProfile->prices->count() > 0) {
|
|
$price = $this->locationProfile->prices;
|
|
if (auth()->guard('customer')->check()) {
|
|
$customer = self::getInstance()['customer'];
|
|
|
|
return $price->where('customer_level_id', $customer->customer_level_id)
|
|
->value('display_price');
|
|
}
|
|
|
|
return $price->max('display_price');
|
|
}
|
|
|
|
return $this->locationProfile->display_price;
|
|
});
|
|
}
|
|
|
|
public function validateBonusPoin(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
if ($this->locationProfile->prices->count() > 0) {
|
|
$price = $this->locationProfile->prices;
|
|
if (auth()->guard('customer')->check()) {
|
|
$customer = self::getInstance()['customer'];
|
|
|
|
return $price->where('customer_level_id', $customer->customer_level_id)
|
|
->value('bonus_poin');
|
|
}
|
|
|
|
return $price->max('bonus_poin');
|
|
}
|
|
|
|
return $this->locationProfile->bonus_poin;
|
|
});
|
|
}
|
|
|
|
public function validatePricePoin(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
if ($this->locationProfile->prices->count() > 0) {
|
|
$price = $this->locationProfile->prices;
|
|
if (auth()->guard('customer')->check()) {
|
|
$customer = self::getInstance()['customer'];
|
|
|
|
return $price->where('customer_level_id', $customer->customer_level_id)
|
|
->value('price_poin');
|
|
}
|
|
|
|
return $price->max('price_poin');
|
|
}
|
|
|
|
return $this->locationProfile->price_poin;
|
|
});
|
|
}
|
|
|
|
public function discount(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
if ($this->locationProfile->prices->count() > 0) {
|
|
$price = $this->locationProfile->prices;
|
|
if (auth()->guard('customer')->check()) {
|
|
$customer = self::getInstance()['customer'];
|
|
|
|
return $price->where('customer_level_id', $customer->customer_level_id)
|
|
->value('discount');
|
|
}
|
|
|
|
return $price->min('discount');
|
|
}
|
|
|
|
return $this->locationProfile->discount;
|
|
});
|
|
}
|
|
|
|
public function status(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
return [
|
|
'color' => $this->is_sold == self::SOLD ? 'bg-green-200 border-green-600' : 'bg-yellow-100 border-yellow-300',
|
|
'text' => $this->is_sold == self::SOLD ? 'Ya' : 'Tidak',
|
|
];
|
|
});
|
|
}
|
|
|
|
public function createdAtFormated(): Attribute
|
|
{
|
|
return Attribute::make(get: function () {
|
|
return $this->created_at->format('d/m/Y H:i:s');
|
|
});
|
|
}
|
|
|
|
public function check_stock_notification()
|
|
{
|
|
$count = Voucher::where([
|
|
['is_sold', '=', self::UNSOLD],
|
|
['location_profile_id', '=', $this->location_profile_id],
|
|
])->count();
|
|
|
|
$treshold = $this->locationProfile->min_stock;
|
|
|
|
if ($count <= $treshold) {
|
|
$notification = Notification::create([
|
|
'entity_type' => User::class,
|
|
'description' => 'stok voucher ' . $this->locationProfile->name . ' (' . $this->locationProfile->location->name . ') ' . ' tersisa : ' . $count,
|
|
'url' => route('voucher.profile', $this->locationProfile->location_id),
|
|
'type' => Notification::TYPE_VOUCHER_STOCK,
|
|
]);
|
|
|
|
NotificationEvent::dispatch([
|
|
'id' => $notification->id,
|
|
'description' => $notification->description,
|
|
'url' => $notification->url,
|
|
'type' => Notification::TYPE_VOUCHER_STOCK,
|
|
'format_created_at' => now()->translatedFormat('d F Y H:i:s'),
|
|
'stock_notifications' => Notification::where('entity_type', User::class)
|
|
->where('type', Notification::TYPE_VOUCHER_STOCK)
|
|
->where('is_read', Notification::UNREAD)->limit(10)
|
|
->orderBy('created_at', 'desc')
|
|
->get(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public static function stats(Location $location)
|
|
{
|
|
$locationCallback = fn ($q) => $q->where('location_id', $location->id);
|
|
$count_voucher_total = Voucher::whereHas('locationProfile', $locationCallback)->count();
|
|
|
|
$sum_voucher_total = Voucher::whereHas('locationProfile', $locationCallback)
|
|
->join('location_profiles', 'location_profiles.id', '=', 'vouchers.location_profile_id')
|
|
->selectRaw('(sum(location_profiles.price)) as total')
|
|
->value('total');
|
|
|
|
$count_voucher_sold = Voucher::whereHas('locationProfile', $locationCallback)
|
|
->where('is_sold', Voucher::SOLD)->count();
|
|
$count_voucher_unsold = Voucher::whereHas('locationProfile', $locationCallback)
|
|
->where('is_sold', Voucher::UNSOLD)->count();
|
|
$sum_voucher_unsold = Voucher::whereHas('locationProfile', $locationCallback)
|
|
->where('is_sold', Voucher::UNSOLD)
|
|
->join('location_profiles', 'location_profiles.id', '=', 'vouchers.location_profile_id')
|
|
->selectRaw('(sum(location_profiles.price)) as total')
|
|
->value('total');
|
|
|
|
$sum_voucher_sold = SaleItem::whereHas('voucher', function ($q) use ($locationCallback) {
|
|
return $q->whereHas('locationProfile', $locationCallback);
|
|
})
|
|
->whereHas('sale', function ($q) {
|
|
$q->where('payed_with', Sale::PAYED_WITH_DEPOSIT)
|
|
->orWhere('payed_with', Sale::PAYED_WITH_PAYLATER);
|
|
})
|
|
->selectRaw('SUM(price * quantity) as total')
|
|
->value('total');
|
|
|
|
return [
|
|
'count_voucher_total' => $count_voucher_total,
|
|
'sum_voucher_total' => $sum_voucher_total,
|
|
'count_voucher_sold' => $count_voucher_sold,
|
|
'sum_voucher_sold' => $sum_voucher_sold,
|
|
'count_voucher_unsold' => $count_voucher_unsold,
|
|
'sum_voucher_unsold' => $sum_voucher_unsold,
|
|
];
|
|
}
|
|
|
|
public function create_bonus_poin(Customer $customer)
|
|
{
|
|
$bonus = $this->validate_bonus_poin;
|
|
|
|
if ($bonus > 0) {
|
|
$customer = Customer::find($customer->id);
|
|
$poin = $customer->poins()->create([
|
|
'debit' => $bonus,
|
|
'description' => GeneralService::generateBonusPoinCode(),
|
|
'narration' => 'Bonus Poin Pembelian Voucher',
|
|
]);
|
|
|
|
$poin->update_customer_balance();
|
|
}
|
|
}
|
|
}
|