Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgergo committed May 28, 2021
1 parent 1ca8d8a commit ec749da
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 62 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"ext-gd": "*",
"ext-exif": "*",
"php": "^7.4 || ^8.0",
"laravel/framework": "^8.40",
"laravel/framework": "^8.43",
"inertiajs/inertia-laravel": "^0.3.6"
},
"require-dev": {
Expand Down
25 changes: 12 additions & 13 deletions src/Cart/CookieDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,21 @@ class CookieDriver extends Driver
*/
protected function resolve(Request $request): Cart
{
$user = $request->user();

$cart = Cart::proxy()
return Cart::proxy()
->newQuery()
->firstOrCreate(['id' => $request->cookie('cart_id')])
->setRelation('user', $user)
->loadMissing(['items', 'items.buyable']);

if ($user && $cart->user_id !== $user->id) {
Cart::proxy()->newQuery()->where('user_id', $user->id)->delete();
->firstOrNew(['id' => $request->cookie('cart_id')]);
}

$cart->user()->associate($user)->save();
}
/**
* The callback after the cart instance is resolved.
*
* @param \Illuminate\Http\Request $request
* @return \Bazar\Models\Cart
*/
protected function resolved(Request $request, Cart $cart): void
{
parent::resolved($request, $cart);

Cookie::queue('cart_id', $cart->id, $this->config['expiration'] ?? 4320);

return $cart;
}
}
35 changes: 26 additions & 9 deletions src/Cart/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ public function __construct(array $config = [])
*/
abstract protected function resolve(Request $request): Cart;

/**
* The callback after the cart instance is resolved.
*
* @param \Illuminate\Http\Request $request
* @return \Bazar\Models\Cart
*/
protected function resolved(Request $request, Cart $cart): void
{
if (! $cart->exists || ($request->user() && $cart->user_id !== $request->user()->id)) {
$cart->user()->associate($request->user())->save();
}

$cart->loadMissing(['items', 'items.buyable']);
}

/**
* Get the cart model.
*
Expand All @@ -58,19 +73,21 @@ public function getModel(): Cart
{
if (is_null($this->cart)) {
$this->cart = App::call(function (Request $request): Cart {
return tap($this->resolve($request), function (Cart $cart): void {
if (! $cart->wasRecentlyCreated && ! $cart->locked && $cart->currency !== Bazar::getCurrency()) {
$cart->setAttribute('currency', Bazar::getCurrency());
$cart->syncItems();
$cart->shipping->calculateCost(false);
$cart->shipping->calculateTax();
$cart->calculateDiscount();
}
return tap($this->resolve($request), function (Cart $cart) use ($request): void {
$this->resolved($request, $cart);
});
});
}

return $this->cart;
return tap($this->cart, static function (Cart $cart): void {
if (! $cart->locked && $cart->currency !== Bazar::getCurrency()) {
$cart->setAttribute('currency', Bazar::getCurrency());
$cart->syncItems();
$cart->shipping->calculateCost(false);
$cart->shipping->calculateTax();
$cart->calculateDiscount();
}
});
}

/**
Expand Down
25 changes: 12 additions & 13 deletions src/Cart/SessionDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,21 @@ class SessionDriver extends Driver
*/
protected function resolve(Request $request): Cart
{
$user = $request->user();

$cart = Cart::proxy()
return Cart::proxy()
->newQuery()
->firstOrCreate(['id' => $request->session()->get('cart_id')])
->setRelation('user', $user)
->loadMissing(['items', 'items.buyable']);

if ($user && $cart->user_id !== $user->id) {
Cart::proxy()->newQuery()->where('user_id', $user->id)->delete();
->firstOrNew(['id' => $request->session()->get('cart_id')]);
}

$cart->user()->associate($user)->save();
}
/**
* The callback after the cart instance is resolved.
*
* @param \Illuminate\Http\Request $request
* @return \Bazar\Models\Cart
*/
protected function resolved(Request $request, Cart $cart): void
{
parent::resolved($request, $cart);

$request->session()->put('cart_id', $cart->id);

return $cart;
}
}
14 changes: 12 additions & 2 deletions src/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,23 @@ protected static function newFactory(): ?UserFactory
}

/**
* Get the cart for the user.
* Get the active cart for the user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function cart(): HasOne
{
return $this->hasOne(Cart::getProxiedClass());
return $this->hasOne(Cart::getProxiedClass())->latestOfMany();
}

/**
* Get the carts for the user.
*
* @return \Illuminate\Database\Eloquent\Relations\v
*/
public function carts(): HasMany
{
return $this->hasMany(Cart::getProxiedClass());
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/Models/Variant.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Bazar\Concerns\InteractsWithItemables;
use Bazar\Concerns\InteractsWithProxy;
use Bazar\Concerns\InteractsWithStock;
use Bazar\Contracts\Buyable;
use Bazar\Contracts\Itemable;
use Bazar\Contracts\Models\Variant as Contract;
use Bazar\Database\Factories\VariantFactory;
Expand Down
57 changes: 34 additions & 23 deletions tests/Feature/CartManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Bazar\Tests\Feature;

use Bazar\Bazar;
use Bazar\Cart\CookieDriver;
use Bazar\Cart\Manager;
use Bazar\Cart\SessionDriver;
Expand All @@ -25,18 +26,20 @@ public function setUp(): void
parent::setUp();

$this->manager = $this->app->make(Manager::class);
$this->product = Product::factory()->create(['prices' => ['usd' => ['default' => 100]]]);
$this->product = Product::factory()->create([
'prices' => ['usd' => ['default' => 100], 'eur' => ['default' => 2000]],
]);
$this->variant = $this->product->variants()->save(Variant::factory()->make([
'variation' => ['Size' => 'S'],
'prices' => ['usd' => ['default' => 150]],
'prices' => ['usd' => ['default' => 150], 'eur' => ['default' => 2500]],
]));

$this->manager->addItem($this->product, 2, ['Size' => 'L']);
$this->manager->addItem($this->product, 1, ['Size' => 'S']);
}

/** @test */
public function it_can_be_resolved_via_facade()
public function a_manager_can_be_resolved_via_facade()
{
$this->mock(Manager::class, function ($mock) {
return $mock->shouldReceive('getModel')
Expand All @@ -48,14 +51,14 @@ public function it_can_be_resolved_via_facade()
}

/** @test */
public function it_has_cookie_driver()
public function a_manager_has_cookie_driver()
{
$this->assertInstanceOf(CookieDriver::class, $this->manager->driver('cookie'));
$this->assertInstanceOf(Cart::class, $this->manager->driver('cookie')->getModel());
}

/** @test */
public function it_has_session_driver()
public function a_manager_has_session_driver()
{
$this->session([]);

Expand All @@ -66,24 +69,20 @@ public function it_has_session_driver()
}

/** @test */
public function it_can_add_products()
public function a_manager_can_add_products()
{
$this->manager->addItem($this->product, 2, ['Size' => 'L']);

$this->assertEquals(5, $this->manager->count());
$this->assertEquals(2, $this->manager->getItems()->count());

$product = $this->manager->getModel()->findItem([
'buyable_id' => $this->product->id,
'buyable_type' => Product::class,
'properties' => ['Size' => 'L'],
]);
$this->assertEquals(100, $product->price);
$this->assertEquals(4, $product->quantity);

$variant = $this->manager->getModel()->findItem([
'buyable_id' => $this->variant->id,
'buyable_type' => Variant::class,
'properties' => ['Size' => 'S'],
]);

Expand All @@ -92,10 +91,9 @@ public function it_can_add_products()
}

/** @test */
public function it_can_remove_items()
public function a_manager_can_remove_items()
{
$item = $this->manager->getModel()->findItem([
'product_id' => $this->product->id,
'properties' => ['Size' => 'L'],
]);
$this->manager->removeItem($item->id);
Expand All @@ -109,10 +107,9 @@ public function it_can_remove_items()
}

/** @test */
public function it_can_update_items()
public function a_manager_can_update_items()
{
$item = $this->manager->getModel()->findItem([
'product_id' => $this->product->id,
'properties' => ['Size' => 'L'],
]);
$this->manager->updateItem($item->id, ['quantity' => 10]);
Expand All @@ -130,67 +127,67 @@ public function it_can_update_items()
}

/** @test */
public function it_can_be_emptied()
public function a_manager_can_be_emptied()
{
$this->assertTrue($this->manager->isNotEmpty());
$this->manager->empty();
$this->assertTrue($this->manager->isEmpty());
}

/** @test */
public function it_has_shipping()
public function a_manager_has_shipping()
{
$this->assertInstanceOf(Shipping::class, $this->manager->getShipping());
}

/** @test */
public function it_updates_shipping()
public function a_manager_updates_shipping()
{
$this->manager->updateShipping(['first_name' => 'Test'], 'local-pickup');

$this->assertSame('Test', $this->manager->getShipping()->address->first_name);
}

/** @test */
public function it_has_billing()
public function a_manager_has_billing()
{
$this->assertInstanceOf(Address::class, $this->manager->getBilling());
}

/** @test */
public function it_updates_billing()
public function a_manager_updates_billing()
{
$this->manager->updateBilling(['first_name' => 'Test']);

$this->assertSame('Test', $this->manager->getBilling()->first_name);
}

/** @test */
public function it_has_getTotal()
public function a_manager_has_getTotal()
{
$this->assertEquals(
$this->manager->getModel()->total, $this->manager->getTotal()
);
}

/** @test */
public function it_has_calculates_tax()
public function a_manager_has_calculates_tax()
{
$this->assertEquals(
$this->manager->getModel()->tax, $this->manager->calculateTax()
);
}

/** @test */
public function it_has_calculates_discount()
public function a_manager_has_calculates_discount()
{
$this->assertEquals(
$this->manager->getModel()->discount, $this->manager->calculateDiscount()
);
}

/** @test */
public function it_can_checkout()
public function a_manager_can_checkout()
{
Event::fake([CheckoutProcessing::class, CheckoutProcessed::class]);

Expand All @@ -199,4 +196,18 @@ public function it_can_checkout()
Event::assertDispatched(CheckoutProcessing::class);
Event::assertDispatched(CheckoutProcessed::class);
}

/** @test */
public function a_manager_can_sync_items()
{
$this->assertEquals(350, $this->manager->getTotal());

Bazar::setCurrency('eur');

$this->assertEquals(6500, $this->manager->getTotal());

Bazar::setCurrency('usd');

$this->assertEquals(350, $this->manager->getTotal());
}
}

0 comments on commit ec749da

Please sign in to comment.