laravel-shop/src/Models/Cart.php

140 lines
3.7 KiB
PHP
Raw Normal View History

2025-11-21 10:49:41 +00:00
<?php
namespace Blax\Shop\Models;
use Blax\Shop\Contracts\Cartable;
2025-11-21 10:49:41 +00:00
use Blax\Workkit\Traits\HasExpiration;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Cart extends Model
{
use HasUuids, HasExpiration;
protected $fillable = [
'session_id',
'customer_type',
'customer_id',
'currency',
'status',
'last_activity_at',
'expires_at',
'converted_at',
'meta',
];
protected $casts = [
'expires_at' => 'datetime',
'converted_at' => 'datetime',
'last_activity_at' => 'datetime',
'meta' => 'object',
];
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->table = config('shop.tables.carts', 'carts');
}
public function customer(): MorphTo
{
return $this->morphTo();
}
// Alias for backward compatibility
public function user()
{
return $this->customer();
}
public function items(): HasMany
{
return $this->hasMany(config('shop.models.cart_item'), 'cart_id');
}
public function purchases(): HasMany
{
return $this->hasMany(config('shop.models.product_purchase', \Blax\Shop\Models\ProductPurchase::class), 'cart_id');
}
public function getTotal(): float
{
return $this->items->sum(function ($item) {
return $item->quantity * $item->price;
});
}
public function getTotalItems(): int
{
return $this->items->sum('quantity');
}
public function isExpired(): bool
{
return $this->expires_at && $this->expires_at->isPast();
}
public function isConverted(): bool
{
return !is_null($this->converted_at);
}
public function scopeActive($query)
{
return $query->whereNull('converted_at')
->where(function ($q) {
$q->whereNull('expires_at')
->orWhere('expires_at', '>', now());
});
}
public function scopeForUser($query, $userOrId)
{
if (is_object($userOrId)) {
return $query->where('customer_id', $userOrId->id)
->where('customer_type', get_class($userOrId));
}
// If just an ID is passed, try to determine the user model class
$userModel = config('auth.providers.users.model', \Workbench\App\Models\User::class);
return $query->where('customer_id', $userOrId)
->where('customer_type', $userModel);
}
2025-11-22 17:09:45 +00:00
protected static function booted()
{
static::deleting(function ($cart) {
$cart->items()->delete();
});
}
public function addToCart(
Model $cartable,
$quantity = 1,
$parameters = []
) : CartItem {
// $cartable must implement Cartable
if (! $cartable instanceof Cartable) {
throw new \Exception("Item must implement the Cartable interface.");
}
$cartItem = $this->items()->create([
'purchasable_id' => $cartable->getKey(),
'purchasable_type' => get_class($cartable),
'quantity' => $quantity,
'price' => ($cartable?->sale_unit_amount ?? $cartable?->unit_amount ?? 0),
'regular_price' => $cartable?->unit_amount,
'subtotal' => ($cartable?->sale_unit_amount ?? $cartable?->unit_amount ?? 0) * $quantity,
'parameters' => $parameters,
]);
$cartItem = $cartItem->fresh();
return $cartItem;
}
2025-11-21 10:49:41 +00:00
}