BFI cart addItem method & test

This commit is contained in:
Fabian @ Blax Software 2025-12-09 09:42:59 +01:00
parent beebee6b82
commit 6fede41426
2 changed files with 47 additions and 11 deletions

View File

@ -137,30 +137,65 @@ class Cart extends Model
}); });
} }
/**
* Add an item to the cart or increase quantity if it already exists.
*
* @param Model&Cartable $cartable The item to add to cart
* @param int $quantity The quantity to add
* @param array<string, mixed> $parameters Additional parameters for the cart item
* @return CartItem
* @throws \Exception If the item doesn't implement Cartable interface
*/
public function addToCart( public function addToCart(
Model $cartable, Model $cartable,
$quantity = 1, int $quantity = 1,
$parameters = [] array $parameters = []
): CartItem { ): CartItem {
// $cartable must implement Cartable // $cartable must implement Cartable
if (! $cartable instanceof Cartable) { if (! $cartable instanceof Cartable) {
throw new \Exception("Item must implement the Cartable interface."); throw new \Exception("Item must implement the Cartable interface.");
} }
// Check if item already exists in cart with same parameters
$existingItem = $this->items()
->where('purchasable_id', $cartable->getKey())
->where('purchasable_type', get_class($cartable))
->get()
->first(function ($item) use ($parameters) {
$existingParams = is_array($item->parameters)
? $item->parameters
: (array) $item->parameters;
// Sort both arrays to ensure consistent comparison
ksort($existingParams);
ksort($parameters);
return $existingParams === $parameters;
});
if ($existingItem) {
// Update quantity and subtotal
$newQuantity = $existingItem->quantity + $quantity;
$existingItem->update([
'quantity' => $newQuantity,
'subtotal' => ($cartable->getCurrentPrice()) * $newQuantity,
]);
return $existingItem->fresh();
}
// Create new cart item
$cartItem = $this->items()->create([ $cartItem = $this->items()->create([
'purchasable_id' => $cartable->getKey(), 'purchasable_id' => $cartable->getKey(),
'purchasable_type' => get_class($cartable), 'purchasable_type' => get_class($cartable),
'quantity' => $quantity, 'quantity' => $quantity,
'price' => $cartable?->getCurrentPrice(), 'price' => $cartable->getCurrentPrice(),
'regular_price' => $cartable?->getCurrentPrice(false) ?? $cartable?->unit_amount, 'regular_price' => $cartable->getCurrentPrice(false) ?? $cartable->unit_amount,
'subtotal' => ($cartable?->getCurrentPrice()) * $quantity, 'subtotal' => ($cartable->getCurrentPrice()) * $quantity,
'parameters' => $parameters, 'parameters' => $parameters,
]); ]);
$cartItem = $cartItem->fresh(); return $cartItem->fresh();
return $cartItem;
} }
public function checkout(): static public function checkout(): static
@ -177,7 +212,7 @@ class Cart extends Model
foreach ($items as $item) { foreach ($items as $item) {
$product = $item->purchasable; $product = $item->purchasable;
$quantity = $item->quantity; $quantity = $item->quantity;
// Extract booking dates from parameters if this is a booking product // Extract booking dates from parameters if this is a booking product
$from = null; $from = null;
$until = null; $until = null;
@ -185,7 +220,7 @@ class Cart extends Model
$params = is_array($item->parameters) ? $item->parameters : (array) $item->parameters; $params = is_array($item->parameters) ? $item->parameters : (array) $item->parameters;
$from = $params['from'] ?? null; $from = $params['from'] ?? null;
$until = $params['until'] ?? null; $until = $params['until'] ?? null;
// Convert to Carbon instances if they're strings // Convert to Carbon instances if they're strings
if ($from && is_string($from)) { if ($from && is_string($from)) {
$from = \Carbon\Carbon::parse($from); $from = \Carbon\Carbon::parse($from);

View File

@ -319,6 +319,7 @@ class CartManagementTest extends TestCase
); );
$this->assertCount(2, $cart->fresh()->items); $this->assertCount(2, $cart->fresh()->items);
$this->assertEquals($productPrice->unit_amount * 3, $cart->getTotal());
} }
/** @test */ /** @test */