IA booking checking & simplifications, A test/trait
This commit is contained in:
parent
7a26c9a965
commit
c5b78071e7
|
|
@ -8,6 +8,7 @@ use Blax\Shop\Enums\ProductType;
|
|||
use Blax\Shop\Exceptions\InvalidDateRangeException;
|
||||
use Blax\Shop\Exceptions\NotEnoughAvailableInTimespanException;
|
||||
use Blax\Shop\Services\CartService;
|
||||
use Blax\Shop\Traits\ChecksIfBooking;
|
||||
use Blax\Shop\Traits\HasBookingPriceCalculation;
|
||||
use Blax\Workkit\Traits\HasExpiration;
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -19,7 +20,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
|||
|
||||
class Cart extends Model
|
||||
{
|
||||
use HasUuids, HasExpiration, HasFactory, HasBookingPriceCalculation;
|
||||
use HasUuids, HasExpiration, HasFactory, HasBookingPriceCalculation, ChecksIfBooking;
|
||||
|
||||
protected $fillable = [
|
||||
'session_id',
|
||||
|
|
@ -106,6 +107,18 @@ class Cart extends Model
|
|||
return $this->items->every(fn($item) => $item->is_booking);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cart contains at least one booking item
|
||||
*/
|
||||
public function isBooking(): bool
|
||||
{
|
||||
if ($this->items->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->items->contains(fn($item) => $item->is_booking);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of booking items in the cart
|
||||
*/
|
||||
|
|
@ -513,7 +526,7 @@ class Cart extends Model
|
|||
}
|
||||
|
||||
// Check booking product availability if dates are provided
|
||||
if ($cartable->isBooking() && !$cartable->isAvailableForBooking($from, $until, $quantity)) {
|
||||
if ($cartable->isBooking() && !$cartable->isPool() && !$cartable->isAvailableForBooking($from, $until, $quantity)) {
|
||||
throw new \Blax\Shop\Exceptions\NotEnoughStockException(
|
||||
"Product '{$cartable->name}' is not available for the requested period ({$from->format('Y-m-d')} to {$until->format('Y-m-d')})."
|
||||
);
|
||||
|
|
@ -901,7 +914,7 @@ class Cart extends Model
|
|||
}
|
||||
|
||||
// Validate booking products have required dates
|
||||
if ($product instanceof Product && $product->isBooking() && (!$from || !$until)) {
|
||||
if ($product instanceof Product && $product->isBooking() && !$product->isPool() && (!$from || !$until)) {
|
||||
throw new \Exception("Booking product '{$product->name}' requires a timespan (from/until dates).");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Blax\Shop\Models;
|
||||
|
||||
use Blax\Shop\Exceptions\InvalidDateRangeException;
|
||||
use Blax\Shop\Traits\ChecksIfBooking;
|
||||
use Blax\Shop\Traits\HasBookingPriceCalculation;
|
||||
use Blax\Workkit\Traits\HasMeta;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
|
|
@ -11,7 +12,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
|
||||
class CartItem extends Model
|
||||
{
|
||||
use HasUuids, HasMeta, HasBookingPriceCalculation;
|
||||
use HasUuids, HasMeta, HasBookingPriceCalculation, ChecksIfBooking;
|
||||
|
||||
protected $fillable = [
|
||||
'cart_id',
|
||||
|
|
@ -128,7 +129,7 @@ class CartItem extends Model
|
|||
// Fallback: check purchasable directly if no price_id
|
||||
if ($this->purchasable_type === config('shop.models.product', Product::class)) {
|
||||
$product = $this->purchasable;
|
||||
return $product && $product->isBooking();
|
||||
return $product && $this->checkProductIsBooking($product);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -144,7 +145,15 @@ class CartItem extends Model
|
|||
return false;
|
||||
}
|
||||
|
||||
return $product->isBooking();
|
||||
return $this->checkProductIsBooking($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this cart item is for a booking product (method alias)
|
||||
*/
|
||||
public function isBooking(): bool
|
||||
{
|
||||
return $this->is_booking;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Blax\Shop\Exceptions\HasNoPriceException;
|
|||
use Blax\Shop\Exceptions\InvalidBookingConfigurationException;
|
||||
use Blax\Shop\Exceptions\InvalidPoolConfigurationException;
|
||||
use Blax\Shop\Services\CartService;
|
||||
use Blax\Shop\Traits\ChecksIfBooking;
|
||||
use Blax\Shop\Traits\HasCategories;
|
||||
use Blax\Shop\Traits\HasPrices;
|
||||
use Blax\Shop\Traits\HasPricingStrategy;
|
||||
|
|
@ -32,7 +33,7 @@ use Illuminate\Support\Facades\Cache;
|
|||
|
||||
class Product extends Model implements Purchasable, Cartable
|
||||
{
|
||||
use HasFactory, HasUuids, HasMetaTranslation, HasStocks, HasPrices, HasPricingStrategy, HasCategories, HasProductRelations, MayBePoolProduct;
|
||||
use HasFactory, HasUuids, HasMetaTranslation, HasStocks, HasPrices, HasPricingStrategy, HasCategories, HasProductRelations, MayBePoolProduct, ChecksIfBooking;
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
|
|
@ -317,7 +318,7 @@ class Product extends Model implements Purchasable, Cartable
|
|||
*/
|
||||
public function isBooking(): bool
|
||||
{
|
||||
return $this->type === ProductType::BOOKING;
|
||||
return $this->checkProductIsBooking($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ class CartService
|
|||
}
|
||||
|
||||
// Check if booking product has timespan
|
||||
if ($product->isBooking() && (!$item->from || !$item->until)) {
|
||||
if ($product->isBooking() && !$product->isPool() && (!$item->from || !$item->until)) {
|
||||
$errors[] = "Booking product '{$product->name}' requires a timespan (from/until dates).";
|
||||
continue;
|
||||
}
|
||||
|
|
@ -408,7 +408,7 @@ class CartService
|
|||
}
|
||||
|
||||
// Validate stock availability for booking period
|
||||
if ($product->isBooking() && $item->from && $item->until) {
|
||||
if ($product->isBooking() && !$product->isPool() && $item->from && $item->until) {
|
||||
if (!$product->isAvailableForBooking($item->from, $item->until, $item->quantity)) {
|
||||
$errors[] = "'{$product->name}' is not available for the selected period (insufficient stock).";
|
||||
}
|
||||
|
|
@ -493,8 +493,8 @@ class CartService
|
|||
// Validate pricing before adding to cart
|
||||
$product->validatePricing(throwExceptions: true);
|
||||
|
||||
// Validate booking product configuration
|
||||
if ($product->isBooking()) {
|
||||
// Validate booking product configuration (but not for pools)
|
||||
if ($product->isBooking() && !$product->isPool()) {
|
||||
$product->validateBookingConfiguration();
|
||||
}
|
||||
|
||||
|
|
@ -503,7 +503,7 @@ class CartService
|
|||
$product->validatePoolConfiguration();
|
||||
}
|
||||
} // Check availability
|
||||
if ($product instanceof Product && $product->isBooking()) {
|
||||
if ($product instanceof Product && $product->isBooking() && !$product->isPool()) {
|
||||
if (!$product->isAvailableForBooking($from, $until, $quantity)) {
|
||||
$available = $product->getAvailableStock();
|
||||
throw InvalidBookingConfigurationException::notAvailableForPeriod(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Blax\Shop\Traits;
|
||||
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Models\Product;
|
||||
|
||||
/**
|
||||
* Trait to provide a unified way to check if something is booking-related.
|
||||
*
|
||||
* This trait provides the DRY principle for checking booking status across
|
||||
* Product, CartItem, Cart, and ProductPurchase models.
|
||||
*
|
||||
* The rule is:
|
||||
* - For regular products: is booking if type === ProductType::BOOKING
|
||||
* - For pool products: is booking if at least one single item is a booking product
|
||||
* - For cart items: is booking if the product is booking
|
||||
* - For carts: is booking if at least one item is booking
|
||||
* - For purchases: is booking if has from/until dates
|
||||
*/
|
||||
trait ChecksIfBooking
|
||||
{
|
||||
/**
|
||||
* Check if a Product is a booking product.
|
||||
* For pool products, checks if at least one single item is a booking product.
|
||||
*
|
||||
* @param Product $product
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkProductIsBooking(Product $product): bool
|
||||
{
|
||||
// For pool products, check if any single item is a booking product
|
||||
if ($product->type === ProductType::POOL) {
|
||||
return $product->hasBookingSingleItems();
|
||||
}
|
||||
|
||||
// For regular products, check the type
|
||||
return $product->type === ProductType::BOOKING;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,487 @@
|
|||
<?php
|
||||
|
||||
namespace Blax\Shop\Tests\Feature;
|
||||
|
||||
use Blax\Shop\Enums\ProductRelationType;
|
||||
use Blax\Shop\Enums\ProductType;
|
||||
use Blax\Shop\Models\Cart;
|
||||
use Blax\Shop\Models\Product;
|
||||
use Blax\Shop\Models\ProductPrice;
|
||||
use Blax\Shop\Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Workbench\App\Models\User;
|
||||
|
||||
class PoolBookingDetectionTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected User $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->user = User::factory()->create();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function pool_product_with_booking_items_is_detected_as_booking()
|
||||
{
|
||||
// Create pool
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
// Create booking single items
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
$spot2 = Product::factory()->create([
|
||||
'name' => 'Spot 2',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot2->increaseStock(1);
|
||||
|
||||
// Link booking items to pool
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
$pool->productRelations()->attach($spot2->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Test: Pool should be detected as booking
|
||||
$this->assertTrue($pool->isBooking(), 'Pool with booking items should be detected as booking');
|
||||
$this->assertTrue($pool->hasBookingSingleItems(), 'Pool should have booking single items');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function pool_product_without_booking_items_is_not_booking()
|
||||
{
|
||||
// Create pool
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Simple Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
// Create simple (non-booking) single items
|
||||
$item1 = Product::factory()->create([
|
||||
'name' => 'Item 1',
|
||||
'type' => ProductType::SIMPLE,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$item1->increaseStock(10);
|
||||
|
||||
$item2 = Product::factory()->create([
|
||||
'name' => 'Item 2',
|
||||
'type' => ProductType::SIMPLE,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$item2->increaseStock(10);
|
||||
|
||||
// Link simple items to pool
|
||||
$pool->productRelations()->attach($item1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
$pool->productRelations()->attach($item2->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Test: Pool should NOT be detected as booking
|
||||
$this->assertFalse($pool->isBooking(), 'Pool without booking items should not be detected as booking');
|
||||
$this->assertFalse($pool->hasBookingSingleItems(), 'Pool should not have booking single items');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function pool_cart_item_with_booking_items_is_detected_as_booking()
|
||||
{
|
||||
// Create pool
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
// Create price for pool
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 2000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
// Create booking single items
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
// Link booking items to pool
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create cart and add pool product
|
||||
$cart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
|
||||
$cartItem = $cart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
|
||||
// Test: Cart item should be detected as booking
|
||||
$this->assertTrue($cartItem->is_booking, 'Cart item for pool with booking items should be detected as booking');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function pool_cart_item_without_booking_items_is_not_booking()
|
||||
{
|
||||
// Create pool
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Simple Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
// Create price for pool
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 1000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
// Create simple (non-booking) single items
|
||||
$item1 = Product::factory()->create([
|
||||
'name' => 'Item 1',
|
||||
'type' => ProductType::SIMPLE,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$item1->increaseStock(10);
|
||||
|
||||
// Link simple items to pool
|
||||
$pool->productRelations()->attach($item1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create cart and add pool product
|
||||
$cart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
|
||||
$cartItem = $cart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 1000,
|
||||
'regular_price' => 1000,
|
||||
'unit_amount' => 1000,
|
||||
]);
|
||||
|
||||
// Test: Cart item should NOT be detected as booking
|
||||
$this->assertFalse($cartItem->is_booking, 'Cart item for pool without booking items should not be detected as booking');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cart_with_pool_booking_items_detects_booking_correctly()
|
||||
{
|
||||
// Create pool with booking items
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 2000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create cart and add pool product
|
||||
$cart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
|
||||
$cart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
|
||||
// Test: Cart should be detected as full booking
|
||||
$this->assertTrue($cart->is_full_booking, 'Cart with pool booking items should be detected as full booking');
|
||||
$this->assertEquals(1, $cart->bookingItems(), 'Cart should have 1 booking item');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function mixed_cart_with_pool_and_regular_items_not_full_booking()
|
||||
{
|
||||
// Create pool with booking items
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 2000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create regular product
|
||||
$regularProduct = Product::factory()->create([
|
||||
'name' => 'Regular Product',
|
||||
'type' => ProductType::SIMPLE,
|
||||
]);
|
||||
|
||||
$regularPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $regularProduct->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 1000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
// Create cart and add both products
|
||||
$cart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
|
||||
$cart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
|
||||
$cart->items()->create([
|
||||
'purchasable_id' => $regularProduct->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $regularPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 1000,
|
||||
'regular_price' => 1000,
|
||||
'unit_amount' => 1000,
|
||||
]);
|
||||
|
||||
// Test: Cart should NOT be full booking
|
||||
$this->assertFalse($cart->is_full_booking, 'Cart with mixed products should not be full booking');
|
||||
$this->assertEquals(1, $cart->bookingItems(), 'Cart should have 1 booking item');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cart_item_isBooking_method_works()
|
||||
{
|
||||
// Create pool with booking items
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 2000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create cart and add pool product
|
||||
$cart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
|
||||
$cartItem = $cart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
|
||||
// Test: isBooking() method should work
|
||||
$this->assertTrue($cartItem->isBooking(), 'CartItem isBooking() method should return true for booking items');
|
||||
$this->assertEquals($cartItem->is_booking, $cartItem->isBooking(), 'isBooking() should match is_booking attribute');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cart_isBooking_method_works()
|
||||
{
|
||||
// Create pool with booking items
|
||||
$pool = Product::factory()->create([
|
||||
'name' => 'Parking Pool',
|
||||
'type' => ProductType::POOL,
|
||||
'manage_stock' => false,
|
||||
]);
|
||||
|
||||
$poolPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 2000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
$spot1 = Product::factory()->create([
|
||||
'name' => 'Spot 1',
|
||||
'type' => ProductType::BOOKING,
|
||||
'manage_stock' => true,
|
||||
]);
|
||||
$spot1->increaseStock(1);
|
||||
|
||||
$pool->productRelations()->attach($spot1->id, [
|
||||
'type' => ProductRelationType::SINGLE->value,
|
||||
]);
|
||||
|
||||
// Create regular product
|
||||
$regularProduct = Product::factory()->create([
|
||||
'name' => 'Regular Product',
|
||||
'type' => ProductType::SIMPLE,
|
||||
]);
|
||||
|
||||
$regularPrice = ProductPrice::factory()->create([
|
||||
'purchasable_id' => $regularProduct->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'unit_amount' => 1000,
|
||||
'currency' => 'USD',
|
||||
'is_default' => true,
|
||||
]);
|
||||
|
||||
// Test with empty cart
|
||||
$emptyCart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
$this->assertFalse($emptyCart->isBooking(), 'Empty cart should return false for isBooking()');
|
||||
|
||||
// Test with booking item
|
||||
$bookingCart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
$bookingCart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
$this->assertTrue($bookingCart->isBooking(), 'Cart with booking items should return true for isBooking()');
|
||||
|
||||
// Test with mixed cart
|
||||
$mixedCart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
$mixedCart->items()->create([
|
||||
'purchasable_id' => $pool->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $poolPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 2000,
|
||||
'regular_price' => 2000,
|
||||
'unit_amount' => 2000,
|
||||
]);
|
||||
$mixedCart->items()->create([
|
||||
'purchasable_id' => $regularProduct->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $regularPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 1000,
|
||||
'regular_price' => 1000,
|
||||
'unit_amount' => 1000,
|
||||
]);
|
||||
$this->assertTrue($mixedCart->isBooking(), 'Cart with mixed items should return true for isBooking() if it contains at least one booking');
|
||||
|
||||
// Test with only regular product
|
||||
$regularCart = Cart::factory()->create([
|
||||
'customer_id' => $this->user->id,
|
||||
'customer_type' => get_class($this->user),
|
||||
]);
|
||||
$regularCart->items()->create([
|
||||
'purchasable_id' => $regularProduct->id,
|
||||
'purchasable_type' => Product::class,
|
||||
'price_id' => $regularPrice->id,
|
||||
'quantity' => 1,
|
||||
'price' => 1000,
|
||||
'regular_price' => 1000,
|
||||
'unit_amount' => 1000,
|
||||
]);
|
||||
$this->assertFalse($regularCart->isBooking(), 'Cart with only regular items should return false for isBooking()');
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue