From fe0ffca9ee85b9520260d867be0aa6f5c9b5e40b Mon Sep 17 00:00:00 2001 From: prashant-webkul Date: Fri, 28 Sep 2018 18:25:48 +0530 Subject: [PATCH] Cart Module Almost Completed --- packages/Webkul/Cart/src/Cart.php | 454 +++++++++++------- .../src/Http/Controllers/CartController.php | 22 +- packages/Webkul/Shop/src/Http/routes.php | 8 + .../Shop/src/Resources/assets/sass/app.scss | 14 +- .../views/checkout/cart/index.blade.php | 104 ++-- .../Resources/views/products/view.blade.php | 5 +- .../view/configurable-options.blade.php | 2 +- public/themes/default/assets/css/shop.css | 19 +- 8 files changed, 390 insertions(+), 238 deletions(-) diff --git a/packages/Webkul/Cart/src/Cart.php b/packages/Webkul/Cart/src/Cart.php index e1a07c11f..f481dc51f 100644 --- a/packages/Webkul/Cart/src/Cart.php +++ b/packages/Webkul/Cart/src/Cart.php @@ -82,80 +82,6 @@ class Cart { $this->product = $product; } - /** - * Create new cart instance with the current item added. - * - * @param integer $id - * @param array $data - * - * @return Response - */ - public function createNewCart($id, $data) - { - $itemData = $this->prepareItemData($id, $data); - - $cartData['channel_id'] = core()->getCurrentChannel()->id; - - // this will auto set the customer id for the cart instances if customer is authenticated - if(auth()->guard('customer')->check()) { - $cartData['customer_id'] = auth()->guard('customer')->user()->id; - - $cartData['is_guest'] = 0; - - $cartData['customer_full_name'] = auth()->guard('customer')->user()->first_name .' '. auth()->guard('customer')->user()->last_name; - } - - $cartData['is_guest'] = 1; - - $cartData['items_count'] = 1; - - $cartData['items_qty'] = $data['quantity']; - - if($cart = $this->cart->create($cartData)) { - $itemData['parent']['cart_id'] = $cart->id; - - if ($data['is_configurable'] == "true") { - //parent product entry - $itemData['parent']['additional'] = json_encode($data); - if($parent = $this->cartItem->create($itemData['parent'])) { - - $itemData['child']['parent_id'] = $parent->id; - $itemData['child']['cart_id'] = $cart->id; - if($child = $this->cartItem->create($itemData['child'])) { - session()->put('cart', $cart); - - session()->flash('success', 'Item Added To Cart Successfully'); - - return redirect()->back(); - } - } - - // $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]); - $this->collectTotals(); - - $this->collectQuantities(); - - } else if($data['is_configurable'] == "false") { - if($result = $this->cartItem->create($itemData['parent'])) { - session()->put('cart', $cart); - - session()->flash('success', 'Item Added To Cart Successfully'); - - return redirect()->back(); - } - - // $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]); - $this->collectTotals(); - - $this->collectQuantities(); - } - } - - session()->flash('error', 'Some Error Occured'); - - return redirect()->back(); - } - /** * Prepare the other data for the product to be added. * @@ -234,6 +160,129 @@ class Cart { } } + /** + * Create new cart instance with the current item added. + * + * @param integer $id + * @param array $data + * + * @return Response + */ + public function createNewCart($id, $data) + { + $itemData = $this->prepareItemData($id, $data); + + $cartData['channel_id'] = core()->getCurrentChannel()->id; + + // this will auto set the customer id for the cart instances if customer is authenticated + if(auth()->guard('customer')->check()) { + $cartData['customer_id'] = auth()->guard('customer')->user()->id; + + $cartData['is_guest'] = 0; + + $cartData['customer_full_name'] = auth()->guard('customer')->user()->first_name .' '. auth()->guard('customer')->user()->last_name; + } else { + $cartData['is_guest'] = 1; + } + + $cartData['items_count'] = 1; + + $cartData['items_qty'] = $data['quantity']; + + if($cart = $this->cart->create($cartData)) { + $itemData['parent']['cart_id'] = $cart->id; + + if ($data['is_configurable'] == "true") { + //parent product entry + $itemData['parent']['additional'] = json_encode($data); + if($parent = $this->cartItem->create($itemData['parent'])) { + + $itemData['child']['parent_id'] = $parent->id; + $itemData['child']['cart_id'] = $cart->id; + if($child = $this->cartItem->create($itemData['child'])) { + session()->put('cart', $cart); + + session()->flash('success', 'Item Added To Cart Successfully'); + + return redirect()->back(); + } + } + + // $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]); + $this->collectQuantities(); + + $this->collectTotals(); + } else if($data['is_configurable'] == "false") { + if($result = $this->cartItem->create($itemData['parent'])) { + session()->put('cart', $cart); + + session()->flash('success', 'Item Added To Cart Successfully'); + + return redirect()->back(); + } + + // $cart->update(['subtotal' => $itemData['parent']['price'], 'base_sub_total' => $itemData['parent']['price']]); + $this->collectQuantities(); + + $this->collectTotals(); + } + } + + session()->flash('error', 'Some Error Occured'); + + return redirect()->back(); + } + + /** + * Returns cart + * + * @return Mixed + */ + public function getCart() + { + if(!$cart = session()->get('cart')) + return false; + + return $this->cart->find($cart->id); + } + + /** + * Method to check if the product is available and its required quantity + * is available or not in the inventory sources. + * + * @param integer $id + * + * @return Array + */ + public function canAddOrUpdate($itemId, $quantity) + { + $item = $this->cartItem->findOneByField('id', $itemId); + + $inventories = $item->product->inventories; + + $inventory_sources = $item->product->inventory_sources; + + $totalQty = 0; + + foreach($inventory_sources as $inventory_source) { + if($inventory_source->status && $inventory_source->toArray()['pivot']['qty']) { + $totalQty = $totalQty + $inventory_source->toArray()['pivot']['qty']; + } + } + + if ($quantity < 1) { + session()->flash('warning', 'Cannot Add Or Update Lesser than 1'); + + return redirect()->back(); + } + + if($quantity < $totalQty) { + return true; + } else { + return false; + } + } + /** * Add Items in a cart with some cart and item details. * @@ -259,16 +308,24 @@ class Cart { $prevQty = $cartItem->quantity; $newQty = $data['quantity']; + $canBe = $this->canAddOrUpdate($cartItem->id, $prevQty + $newQty); + + if($canBe == false) { + session()->flash('warning', 'The requested quantity is not available, please try back later.'); + + return redirect()->back(); + } + $cartItem->update([ 'quantity' => $prevQty + $newQty, - 'total' => $parentPrice * ($prevQty + $newQty), - 'base_total' => $parentPrice * ($prevQty + $newQty) + 'total' => $cartItem->price * ($prevQty + $newQty), + 'base_total' => $cartItem->price * ($prevQty + $newQty) ]); - $this->collectTotals(); - $this->collectQuantities(); + $this->collectTotals(); + session()->flash('success', "Product Quantity Successfully Updated"); return redirect()->back(); @@ -284,16 +341,24 @@ class Cart { $prevQty = $parent->quantity; $newQty = $data['quantity']; + $canBe = $this->canAddOrUpdate($cartItem->child->id, $prevQty + $newQty); + + if($canBe == false) { + session()->flash('warning', 'The requested quantity is not available, please try back later.'); + + return redirect()->back(); + } + $parent->update([ 'quantity' => $prevQty + $newQty, 'total' => $parentPrice * ($prevQty + $newQty), 'base_total' => $parentPrice * ($prevQty + $newQty) ]); - $this->collectTotals(); - $this->collectQuantities(); + $this->collectTotals(); + session()->flash('success', "Product Quantity Successfully Updated"); return redirect()->back(); @@ -303,19 +368,23 @@ class Cart { } if($data['is_configurable'] == "true") { + $this->canAddOrUpdate($parent->child->id, $parent->quantity); + $parent = $cart->items()->create($itemData['parent']); $itemData['child']['parent_id'] = $parent->id; $cart->items()->create($itemData['child']); } else if($data['is_configurable'] == "false"){ + // $this->canAddOrUpdate($parent->id, $parent->quantity); + $parent = $cart->items()->create($itemData['parent']); } - $this->collectTotals(); - $this->collectQuantities(); + $this->collectTotals(); + session()->flash('success', 'Item Successfully Added To Cart'); return redirect()->back(); @@ -332,23 +401,96 @@ class Cart { } /** - * Use detach to remove the current product from cart tables + * Update the cart on + * cart checkout page + */ + public function update($itemIds) + { + if(session()->has('cart')) { + $cart = session()->get('cart'); + + $items = $cart->items; + + foreach($items as $item) { + foreach($itemIds['qty'] as $id => $quantity) { + if($id == $item->id) { + if($item->type == "configurable") { + $canBe = $this->canAddOrUpdate($item->child->id, $quantity); + } else { + $canBe = $this->canAddOrUpdate($id, $quantity); + } + + if($canBe == false) { + session()->flash('warning', 'The requested quantity is not available, please try back later.'); + + return redirect()->back(); + } + + $item->update(['quantity' => $quantity]); + } + } + } + + $items = $cart->items; + + session()->flash('success', 'Cart Updated Successfully'); + + return redirect()->back(); + } + } + + /** + * Remove the item from the cart * - * @param Integer $id * @return response */ - public function remove($id) + public function removeItem($itemId) { - $item = $this->cartItem->findOneByField('id', $id); + if(session()->has('cart')) { + $cart = session()->get('cart'); - dd($item); - if($item->parent_id != "null") { - $item->delete($id); - } else { - $parentItem = $item->child; + $items = $cart->items; - dd($parentItem, $item); + foreach($items as $item) { + if($item->id == $itemId) { + if($item->type == "configurable") { + $child = $item->child; + + //delete the child first + $result = $this->cartItem->delete($child->id); + if($result) + $result = $this->cartItem->delete($item->id); + + $this->collectQuantities(); + $this->collectTotals(); + } else if($item->type == "simple" && $item->parent_id == null){ + $result = $this->cartItem->delete($item->id); + + $this->collectQuantities(); + $this->collectTotals(); + } + } + } + $countItems = $this->cart->findOneByField('id', $cart->id)->items->count(); + + //delete the cart instance if no items are there + if($countItems == 0) { + $result = $this->cart->delete($cart->id); + + session()->forget('cart'); + } else { + session()->forget('cart'); + + session()->put('cart', $this->cart->findOneByField('id', $cart->id)); + } + + if ($result) { + session()->flash('sucess', 'Item Successfully Removed From Cart'); + } else { + session()->flash('error', 'Item Cannot Be Removed From Cart'); + } } + return redirect()->back(); } /** @@ -460,6 +602,28 @@ class Cart { return $cartPayment; } + /** + * Update Cart Quantities, Weight + * + * @return void + */ + public function collectQuantities() + { + if(!$cart = $this->getCart()) + return false; + + $quantities = 0; + + foreach($cart->items as $item) { + $quantities = $quantities + $item->quantity; + } + + $itemCount = $cart->items->count(); + + $cart->update(['items_count' => $itemCount, 'items_qty' => $quantities]); + + } + /** * Updates cart totals * @@ -493,27 +657,6 @@ class Cart { $cart->save(); } - /** - * Update Cart Quantities, Weight - * - * @return void - */ - public function collectQuantities() { - if(!$cart = $this->getCart()) - return false; - - $quantities = 0; - - foreach($cart->items as $item) { - $quantities = $quantities + $item->quantity; - } - - $itemCount = $cart->items->count(); - - $cart->update(['items_count' => $itemCount, 'items_qty' => $quantities]); - - } - /** * This function handles when guest has some of cart products and then logs in. * @@ -551,6 +694,14 @@ class Cart { $newQty = $guestCartItem->quantity; + $canBe = $this->canAddOrUpdate($cartItem->id, $prevQty + $newQty); + + if($canBe == false) { + session()->flash('warning', 'The requested quantity is not available, please try back later.'); + + return redirect()->back(); + } + $cartItem->update([ 'quantity' => $prevQty + $newQty, 'total' => $cartItem->price * ($prevQty + $newQty), @@ -560,7 +711,7 @@ class Cart { ]); $guestCartItems->forget($key); - $this->cartItem->delete($guestCart->id); + $this->cartItem->delete($guestCartItem->id); } } else if($guestCartItem->type == "configurable" && $cartItem->type == "configurable") { $guestCartItemChild = $guestCartItem->child; @@ -571,6 +722,14 @@ class Cart { $prevQty = $guestCartItem->quantity; $newQty = $cartItem->quantity; + $canBe = $this->canAddOrUpdate($cartItem->child->id, $prevQty + $newQty); + + if($canBe == false) { + session()->flash('warning', 'The requested quantity is not available, please try back later.'); + + return redirect()->back(); + } + $cartItem->update([ 'quantity' => $prevQty + $newQty, 'total' => $cartItem->price * ($prevQty + $newQty), @@ -585,7 +744,7 @@ class Cart { $this->cartItem->delete($guestCartItemChild->id); //then parent will get deleted - $this->cartItem->delete($guestCart->id); + $this->cartItem->delete($guestCartItem->id); } } } @@ -612,77 +771,16 @@ class Cart { //put the customer cart instance session()->put('cart', $cart); - $this->collectTotals(); - $this->collectQuantities(); + $this->collectTotals(); + return redirect()->back(); } else { return redirect()->back(); } } - /** - * Method to check if the product is available and its required quantity - * is available or not in the inventory sources. - * - * @param integer $id - * - * @return Array - */ - public function canCheckOut($productId, $quantity) - { - $items = $cart->items; - - $allProdQty = array(); - - $allProdQty1 = array(); - - $totalQty = 0; - - foreach($items as $item) { - $inventories = $item->product->inventories; - - $inventory_sources = $item->product->inventory_sources; - - $totalQty = 0; - - foreach($inventory_sources as $inventory_source) { - if($inventory_source->status!=0) { - foreach($inventories as $inventory) { - $totalQty = $totalQty + $inventory->qty; - } - - array_push($allProdQty1, $totalQty); - - $allProdQty[$item->product->id] = $totalQty; - } - } - } - - foreach ($items as $item) { - $inventories = $item->product->inventory_sources->where('status', '=', '1'); - - foreach($inventories as $inventory) { - dump($inventory->status); - } - } - dd([true, false]); - } - - /** - * Returns cart - * - * @return Mixed - */ - public function getCart() - { - if(!$cart = session()->get('cart')) - return false; - - return $this->cart->find($cart->id); - } - /** * Destroys the session * maintained for cart diff --git a/packages/Webkul/Cart/src/Http/Controllers/CartController.php b/packages/Webkul/Cart/src/Http/Controllers/CartController.php index c4f03f063..2aad9aaaa 100644 --- a/packages/Webkul/Cart/src/Http/Controllers/CartController.php +++ b/packages/Webkul/Cart/src/Http/Controllers/CartController.php @@ -105,8 +105,28 @@ class CartController extends Controller return redirect()->back(); } + /** + * Removes the item from + * the cart if it exists + * + * @param integer $itemId + */ public function remove($itemId) { - Cart::remove($itemId); + Cart::removeItem($itemId); + + return redirect()->back(); + } + + /** + * Updates the quantity of the + * items present in the cart. + * + * @return response + */ + public function updateBeforeCheckout() { + $data = request()->except('_token'); + + Cart::update($data); return redirect()->back(); } diff --git a/packages/Webkul/Shop/src/Http/routes.php b/packages/Webkul/Shop/src/Http/routes.php index e07372626..65e12566d 100644 --- a/packages/Webkul/Shop/src/Http/routes.php +++ b/packages/Webkul/Shop/src/Http/routes.php @@ -35,6 +35,14 @@ Route::group(['middleware' => ['web']], function () { Route::post('product/cart/add/{id}', 'Webkul\Cart\Http\Controllers\CartController@add')->name('cart.add'); Route::get('product/cart/remove/{id}', 'Webkul\Cart\Http\Controllers\CartController@remove')->name('cart.remove'); + + Route::post('/checkout/cart', 'Webkul\Cart\Http\Controllers\CartController@updateBeforeCheckout')->defaults('_config',[ + 'redirect' => 'shop.checkout.cart.index' + ])->name('shop.checkout.cart.update'); + + Route::get('/checkout/cart/remove/{id}', 'Webkul\Cart\Http\Controllers\CartController@remove')->defaults('_config',[ + 'redirect' => 'shop.checkout.cart.index' + ])->name('shop.checkout.cart.remove'); //Routes for product cart ends // Product Review routes diff --git a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss index e6723503e..97f608e66 100644 --- a/packages/Webkul/Shop/src/Resources/assets/sass/app.scss +++ b/packages/Webkul/Shop/src/Resources/assets/sass/app.scss @@ -17,6 +17,10 @@ body { font-family: "Montserrat", sans-serif; } +.btn.btn-primary{ + border-radius: 0px; +} + .header { margin-top: 16px; margin-bottom: 21px; @@ -1960,7 +1964,11 @@ section.cart { float: left; .misc-controls { - float: right; + width: 100%; + display: inline-flex; + align-items: center; + justify-content: space-between; + margin-top: 20px; a.link { @@ -2024,14 +2032,16 @@ section.cart { margin-right: 10px; } - div.box { + input.box { height: 38px; width: 60px; + font-size: 16px; text-align: center; line-height: 38px; border: 1px solid $border-color; border-radius: 3px; margin-right: 30px; + border-radius: 0px; } .remove { diff --git a/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php b/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php index 7065900c3..18ae5c9e1 100644 --- a/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/checkout/cart/index.blade.php @@ -19,79 +19,79 @@
+
-
- @foreach($cart->items as $item) +
+ @csrf + @foreach($cart->items as $item) - product; + product; - $productBaseImage = $productImageHelper->getProductBaseImage($product); - ?> + $productBaseImage = $productImageHelper->getProductBaseImage($product); + ?> -
-
- -
- -
- -
- {{ $product->name }} +
+
+
-
- {{ core()->currency($item->base_price) }} -
+
- @if ($product->type == 'configurable') - -
- {{-- @foreach (cart::getItemAttributeOptionDetails($item) as $key => $option) - - {{ (!$key ? '' : ' , ') . $option['attribute_name'] . ' : ' . $option['option_label'] }} - - @endforeach --}} +
+ {{ $product->name }}
- @endif -
-
{{ __('shop::app.checkout.cart.quantity') }}
-
{{ $item->quantity }}
- @if($product->type == 'configurable') - {{ __('shop::app.checkout.cart.remove') }} - @else - {{ __('shop::app.checkout.cart.remove') }} +
+ {{ core()->currency($item->base_price) }} +
+ + @if ($product->type == 'configurable') + +
+ {{-- @foreach (cart::getItemAttributeOptionDetails($item) as $key => $option) + + {{ (!$key ? '' : ' , ') . $option['attribute_name'] . ' : ' . $option['option_label'] }} + + @endforeach --}} +
@endif - {{ __('shop::app.checkout.cart.move-to-wishlist') }} + +
+
{{ __('shop::app.checkout.cart.quantity') }}
+ {{--
{{ $item->quantity }}
--}} + + @{{ errors.first('quantity') }} + {{-- @if($product->type == 'configurable') + {{ __('shop::app.checkout.cart.remove') }} + @else --}} + {{ __('shop::app.checkout.cart.remove') }} + {{-- @endif --}} + {{ __('shop::app.checkout.cart.move-to-wishlist') }} +
+
+ @endforeach +
+ - - - +
+
- @include('shop::checkout.total.summary', ['cart' => $cart]) -
-
- @else -
{{ __('shop::app.checkout.cart.empty') }}
diff --git a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php index 8ff545cc2..521d467c0 100644 --- a/packages/Webkul/Shop/src/Resources/views/products/view.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/view.blade.php @@ -35,9 +35,10 @@ {{ $product->short_description }}
-
+
- + + @{{ errors.first('quantity') }}
@if ($product->type == 'configurable') diff --git a/packages/Webkul/Shop/src/Resources/views/products/view/configurable-options.blade.php b/packages/Webkul/Shop/src/Resources/views/products/view/configurable-options.blade.php index 317e4c5ca..53e7d6939 100644 --- a/packages/Webkul/Shop/src/Resources/views/products/view/configurable-options.blade.php +++ b/packages/Webkul/Shop/src/Resources/views/products/view/configurable-options.blade.php @@ -27,7 +27,7 @@
- diff --git a/public/themes/default/assets/css/shop.css b/public/themes/default/assets/css/shop.css index c7ab7b824..18c6e0e45 100644 --- a/public/themes/default/assets/css/shop.css +++ b/public/themes/default/assets/css/shop.css @@ -81,6 +81,10 @@ body { font-family: "Montserrat", sans-serif; } +.btn.btn-primary { + border-radius: 0px; +} + .header { margin-top: 16px; margin-bottom: 21px; @@ -1983,7 +1987,16 @@ section.cart .cart-content .left-side { } section.cart .cart-content .left-side .misc-controls { - float: right; + width: 100%; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; margin-top: 20px; } @@ -2064,14 +2077,16 @@ section.cart .cart-content .right-side { margin-right: 10px; } -.cart-item-list .item .item-details .misc div.box { +.cart-item-list .item .item-details .misc input.box { height: 38px; width: 60px; + font-size: 16px; text-align: center; line-height: 38px; border: 1px solid #E8E8E8; border-radius: 3px; margin-right: 30px; + border-radius: 0px; } .cart-item-list .item .item-details .misc .remove {