FleetCart/Modules/FlashSale/Entities/FlashSale.php
2023-06-11 13:14:03 +01:00

148 lines
3.5 KiB
PHP

<?php
namespace Modules\FlashSale\Entities;
use Modules\Support\Money;
use Modules\Admin\Ui\AdminTable;
use Modules\Support\Eloquent\Model;
use Modules\Product\Entities\Product;
use Modules\Support\Eloquent\Translatable;
class FlashSale extends Model
{
use Translatable;
/**
* Active flash sale.
*
* @var self
*/
private static $active;
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['translations'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['id'];
/**
* The attributes that are translatable.
*
* @var array
*/
public $translatedAttributes = ['campaign_name'];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
static::saved(function ($flashSale) {
if (! empty(request()->has('products'))) {
$flashSale->saveProducts(request('products'));
}
});
}
/**
* Get the active flash sale.
*
* @param int $id
* @return self
*/
public static function active()
{
if (is_callable(self::$active)) {
return call_user_func(self::$active);
}
return new self;
}
/**
* Set an active flash sale campaign.
*
* @param int $id
* @return void
*/
public static function activeCampaign($id)
{
self::$active = function () use ($id) {
return once(function () use ($id) {
return self::withEligibleProducts()->where('id', $id)->firstOrNew([]);
});
};
}
public static function contains(Product $product)
{
return self::active()->products->contains($product);
}
public static function pivot(Product $product)
{
return self::active()->products->find($product)->pivot;
}
public static function remainingQty(Product $product)
{
$flashSaleProduct = self::pivot($product);
return $flashSaleProduct->qty - $flashSaleProduct->sold;
}
public function scopeWithEligibleProducts($query)
{
$query->with(['products' => function ($query) {
$query->forCard()->wherePivot('end_date', '>', now());
}]);
}
public function products()
{
return $this->belongsToMany(Product::class, 'flash_sale_products')
->using(FlashSaleProduct::class)
->withPivot(['id', 'end_date', 'price', 'qty'])
->orderBy('position');
}
public function getPriceAttribute($price)
{
return Money::inDefaultCurrency($price);
}
public function saveProducts($products)
{
$this->products()->sync(
$this->buildProductPivots($products)
);
}
private function buildProductPivots($products)
{
return collect($products)->values()->mapWithKeys(function ($attributes, $index) {
return [$attributes['product_id'] => [
'end_date' => $attributes['end_date'],
'price' => $attributes['price'],
'qty' => $attributes['qty'],
'position' => $index,
]];
});
}
public function table()
{
return new AdminTable($this->query());
}
}