diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index ba47404a1..3539fe1d1 100755 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -31,7 +31,7 @@ class Kernel extends HttpKernel \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class + \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ @@ -56,5 +56,6 @@ class Kernel extends HttpKernel 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'cart.merger' => \Webkul\Checkout\Http\Middleware\CartMerger::class, ]; } diff --git a/packages/Webkul/Checkout/src/Cart.php b/packages/Webkul/Checkout/src/Cart.php index 8491b8c3c..73042aa0e 100755 --- a/packages/Webkul/Checkout/src/Cart.php +++ b/packages/Webkul/Checkout/src/Cart.php @@ -11,6 +11,9 @@ use Webkul\Checkout\Models\CartPayment; use Webkul\Checkout\Repositories\CartAddressRepository; use Webkul\Checkout\Repositories\CartItemRepository; use Webkul\Checkout\Repositories\CartRepository; +use Webkul\Checkout\Traits\CartCoupons; +use Webkul\Checkout\Traits\CartTools; +use Webkul\Checkout\Traits\CartValidators; use Webkul\Customer\Repositories\CustomerAddressRepository; use Webkul\Customer\Repositories\WishlistRepository; use Webkul\Product\Repositories\ProductRepository; @@ -20,50 +23,52 @@ use Webkul\Tax\Repositories\TaxCategoryRepository; class Cart { + use CartCoupons, CartTools, CartValidators; + /** - * CartRepository instance + * Cart repository instance. * * @var \Webkul\Checkout\Repositories\CartRepository */ protected $cartRepository; /** - * CartItemRepository instance + * Cart item repository instance. * * @var \Webkul\Checkout\Repositories\CartItemRepository */ protected $cartItemRepository; /** - * CartAddressRepository instance + * Cart address repository instance. * * @var \Webkul\Checkout\Repositories\CartAddressRepository */ protected $cartAddressRepository; /** - * ProductRepository instance + * Product repository instance. * * @var \Webkul\Checkout\Repositories\ProductRepository */ protected $productRepository; /** - * TaxCategoryRepository instance + * Tax category repository instance. * * @var \Webkul\Tax\Repositories\TaxCategoryRepository */ protected $taxCategoryRepository; /** - * WishlistRepository instance + * Wishlist repository instance. * * @var \Webkul\Customer\Repositories\WishlistRepository */ protected $wishlistRepository; /** - * CustomerAddressRepository instance + * Customer address repository instance. * * @var \Webkul\Customer\Repositories\CustomerAddressRepository */ @@ -89,8 +94,7 @@ class Cart TaxCategoryRepository $taxCategoryRepository, WishlistRepository $wishlistRepository, CustomerAddressRepository $customerAddressRepository - ) - { + ) { $this->cartRepository = $cartRepository; $this->cartItemRepository = $cartItemRepository; @@ -107,7 +111,7 @@ class Cart } /** - * Return current logged in customer + * Return current logged in customer. * * @return \Webkul\Customer\Contracts\Customer|bool */ @@ -119,11 +123,56 @@ class Cart } /** - * Add Items in a cart with some cart and item details. + * Returns cart. * - * @param int $productId - * @param array $data + * @return \Webkul\Checkout\Contracts\Cart|null + */ + public function getCart(): ?\Webkul\Checkout\Contracts\Cart + { + $cart = null; + + if ($this->getCurrentCustomer()->check()) { + $cart = $this->cartRepository->findOneWhere([ + 'customer_id' => $this->getCurrentCustomer()->user()->id, + 'is_active' => 1, + ]); + } else if (session()->has('cart')) { + $cart = $this->cartRepository->find(session()->get('cart')->id); + } + + $this->removeInactiveItems($cart); + + return $cart; + } + + /** + * Get cart item by product. * + * @param array $data + * @return \Webkul\Checkout\Contracts\CartItem|void + */ + public function getItemByProduct($data) + { + $items = $this->getCart()->all_items; + + foreach ($items as $item) { + if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) { + if (isset($data['additional']['parent_id'])) { + if ($item->parent->product->getTypeInstance()->compareOptions($item->parent->additional, $data['additional'])) { + return $item; + } + } else { + return $item; + } + } + } + } + + /** + * Add items in a cart with some cart and item details. + * + * @param int $productId + * @param array $data * @return \Webkul\Checkout\Contracts\Cart|string|array * @throws Exception */ @@ -209,7 +258,9 @@ class Cart 'items_count' => 1, ]; - // Fill in the customer data, as far as possible: + /** + * Fill in the customer data, as far as possible. + */ if ($this->getCurrentCustomer()->check()) { $cartData['customer_id'] = $this->getCurrentCustomer()->user()->id; $cartData['is_guest'] = 0; @@ -234,10 +285,9 @@ class Cart } /** - * Update cart items information + * Update cart items information. * * @param array $data - * * @return bool|void|Exception */ public function updateItems($data) @@ -284,30 +334,7 @@ class Cart } /** - * Get cart item by product. - * - * @param array $data - * @return \Webkul\Checkout\Contracts\CartItem|void - */ - public function getItemByProduct($data) - { - $items = $this->getCart()->all_items; - - foreach ($items as $item) { - if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) { - if (isset($data['additional']['parent_id'])) { - if ($item->parent->product->getTypeInstance()->compareOptions($item->parent->additional, $data['additional'])) { - return $item; - } - } else { - return $item; - } - } - } - } - - /** - * Remove the item from the cart + * Remove the item from the cart. * * @param int $itemId * @return boolean @@ -344,114 +371,43 @@ class Cart } /** - * This function handles when guest has some of cart products and then logs in. + * Remove cart items, whose product is inactive. * - * @return void + * @param \Webkul\Checkout\Models\Cart|null $cart + * @return \Webkul\Checkout\Models\Cart|null */ - public function mergeCart(): void + public function removeInactiveItems(CartModel $cart = null): ?CartModel { - if (session()->has('cart')) { - $cart = $this->cartRepository->findOneWhere([ - 'customer_id' => $this->getCurrentCustomer()->user()->id, - 'is_active' => 1, - ]); + if (! $cart) { + return $cart; + } - $guestCart = session()->get('cart'); + foreach ($cart->items as $item) { + if ($this->isCartItemInactive($item)) { - //when the logged in customer is not having any of the cart instance previously and are active. - if (! $cart) { - $this->cartRepository->update([ - 'customer_id' => $this->getCurrentCustomer()->user()->id, - 'is_guest' => 0, - 'customer_first_name' => $this->getCurrentCustomer()->user()->first_name, - 'customer_last_name' => $this->getCurrentCustomer()->user()->last_name, - 'customer_email' => $this->getCurrentCustomer()->user()->email, - ], $guestCart->id); + $this->cartItemRepository->delete($item->id); - session()->forget('cart'); + if ($cart->items->count() == 0) { + $this->cartRepository->delete($cart->id); - return; + if (session()->has('cart')) { + session()->forget('cart'); + } + } + + session()->flash('info', __('shop::app.checkout.cart.item.inactive')); } - - foreach ($guestCart->items as $guestCartItem) { - $this->addProduct($guestCartItem->product_id, $guestCartItem->additional); - } - - $this->collectTotals(); - - $this->cartRepository->delete($guestCart->id); - - session()->forget('cart'); - } - } - - /** - * Save cart - * - * @param \Webkul\Checkout\Contracts\Cart $cart - * @return void - */ - public function putCart($cart) - { - if (! $this->getCurrentCustomer()->check()) { - session()->put('cart', $cart); - } - } - - /** - * Returns cart - * - * @return \Webkul\Checkout\Contracts\Cart|null - */ - public function getCart(): ?\Webkul\Checkout\Contracts\Cart - { - $cart = null; - - if ($this->getCurrentCustomer()->check()) { - $cart = $this->cartRepository->findOneWhere([ - 'customer_id' => $this->getCurrentCustomer()->user()->id, - 'is_active' => 1, - ]); - } else if (session()->has('cart')) { - $cart = $this->cartRepository->find(session()->get('cart')->id); } - $this->removeInactiveItems($cart); + $cart->save(); return $cart; } /** - * Returns cart details in array - * - * @return array - */ - public function toArray() - { - $cart = $this->getCart(); - - $data = $cart->toArray(); - - $data['billing_address'] = $cart->billing_address->toArray(); - - if ($cart->haveStockableItems()) { - $data['shipping_address'] = $cart->shipping_address->toArray(); - - $data['selected_shipping_rate'] = $cart->selected_shipping_rate ? $cart->selected_shipping_rate->toArray() : 0.0; - } - - $data['payment'] = $cart->payment->toArray(); - - $data['items'] = $cart->items->toArray(); - - return $data; - } - - /** - * Save customer address - * - * @param array $data + * Save customer address. * + * @param array $data * @return bool * @throws \Prettus\Validator\Exceptions\ValidatorException */ @@ -479,7 +435,7 @@ class Cart } /** - * Save shipping method for cart + * Save shipping method for cart. * * @param string $shippingMethodCode * @return bool @@ -497,7 +453,7 @@ class Cart } /** - * Save payment method for cart + * Save payment method for cart. * * @param string $payment * @return \Webkul\Checkout\Contracts\CartPayment @@ -522,7 +478,7 @@ class Cart } /** - * Updates cart totals + * Updates cart totals. * * @return void */ @@ -588,52 +544,7 @@ class Cart } /** - * To validate if the product information is changed by admin and the items have been added to the cart before it. - * - * @return bool - */ - public function validateItems(): bool - { - if (! $cart = $this->getCart()) { - return false; - } - - if (count($cart->items) === 0) { - $this->cartRepository->delete($cart->id); - - return false; - } - - $isInvalid = false; - - foreach ($cart->items as $item) { - $validationResult = $item->product->getTypeInstance()->validateCartItem($item); - - if ($validationResult->isItemInactive()) { - $this->removeItem($item->id); - - $isInvalid = true; - - session()->flash('info', __('shop::app.checkout.cart.item.inactive')); - } - - $price = ! is_null($item->custom_price) ? $item->custom_price : $item->base_price; - - $this->cartItemRepository->update([ - 'price' => core()->convertPrice($price), - 'base_price' => $price, - 'total' => core()->convertPrice($price * $item->quantity), - 'base_total' => $price * $item->quantity, - ], $item->id); - - $isInvalid |= $validationResult->isCartInvalid(); - } - - return ! $isInvalid; - } - - /** - * Calculates cart items tax + * Calculates cart items tax. * * @return void */ @@ -695,124 +606,52 @@ class Cart } /** - * Set Item tax to zero. - * - * @param \Webkul\Checkout\Contracts\CartItem $item - * @return \Webkul\Checkout\Contracts\CartItem - */ - protected function setItemTaxToZero(\Webkul\Checkout\Contracts\CartItem $item): \Webkul\Checkout\Contracts\CartItem - { - $item->tax_percent = 0; - $item->tax_amount = 0; - $item->base_tax_amount = 0; - - return $item; - } - - /** - * Checks if cart has any error + * To validate if the product information is changed by admin and the items have been added to the cart before it. * * @return bool */ - public function hasError(): bool + public function validateItems(): bool { - if (! $this->getCart()) { - return true; - } - - if (! $this->isItemsHaveSufficientQuantity()) { - return true; - } - - return false; - } - - /** - * Checks if all cart items have sufficient quantity. - * - * @return bool - */ - public function isItemsHaveSufficientQuantity(): bool - { - $cart = cart()->getCart(); - - if (! $cart) { + if (! $cart = $this->getCart()) { return false; } - foreach ($cart->items as $item) { - if (! $this->isItemHaveQuantity($item)) { - return false; - } + if (count($cart->items) === 0) { + $this->cartRepository->delete($cart->id); + + return false; } - return true; - } - - /** - * Remove cart items, whose product is inactive - * - * @param \Webkul\Checkout\Models\Cart|null $cart - * - * @return \Webkul\Checkout\Models\Cart|null - */ - public function removeInactiveItems(CartModel $cart = null): ?CartModel - { - if (! $cart) { - return $cart; - } + $isInvalid = false; foreach ($cart->items as $item) { - if ($this->isCartItemInactive($item)) { + $validationResult = $item->product->getTypeInstance()->validateCartItem($item); - $this->cartItemRepository->delete($item->id); + if ($validationResult->isItemInactive()) { + $this->removeItem($item->id); - if ($cart->items->count() == 0) { - $this->cartRepository->delete($cart->id); - - if (session()->has('cart')) { - session()->forget('cart'); - } - } + $isInvalid = true; session()->flash('info', __('shop::app.checkout.cart.item.inactive')); } + + $price = ! is_null($item->custom_price) ? $item->custom_price : $item->base_price; + + $this->cartItemRepository->update([ + 'price' => core()->convertPrice($price), + 'base_price' => $price, + 'total' => core()->convertPrice($price * $item->quantity), + 'base_total' => $price * $item->quantity, + ], $item->id); + + $isInvalid |= $validationResult->isCartInvalid(); } - $cart->save(); - - return $cart; + return ! $isInvalid; } /** - * Checks if all cart items have sufficient quantity. - * - * @param \Webkul\Checkout\Contracts\CartItem $item - * @return bool - */ - public function isItemHaveQuantity($item): bool - { - return $item->product->getTypeInstance()->isItemHaveQuantity($item); - } - - /** - * Deactivates current cart - * - * @return void - */ - public function deActivateCart(): void - { - if ($cart = $this->getCart()) { - $this->cartRepository->update(['is_active' => false], $cart->id); - - if (session()->has('cart')) { - session()->forget('cart'); - } - } - } - - /** - * Validate order before creation + * Prepare data for order. * * @return array */ @@ -859,7 +698,6 @@ class Cart 'shipping_discount_amount' => $data['selected_shipping_rate']['discount_amount'], 'base_shipping_discount_amount' => $data['selected_shipping_rate']['base_discount_amount'], ]); - } foreach ($data['items'] as $item) { @@ -874,7 +712,7 @@ class Cart } /** - * Prepares data for order item + * Prepares data for order item. * * @param array $data * @return array @@ -916,121 +754,44 @@ class Cart } /** - * Move a wishlist item to cart + * Returns cart details in array. * - * @param \Webkul\Customer\Contracts\WishlistItem $wishlistItem - * @return bool + * @return array */ - public function moveToCart($wishlistItem) - { - if (! $wishlistItem->product->getTypeInstance()->canBeMovedFromWishlistToCart($wishlistItem)) { - return false; - } - - if (! $wishlistItem->additional) { - $wishlistItem->additional = ['product_id' => $wishlistItem->product_id, 'quantity' => 1]; - } - - request()->merge($wishlistItem->additional); - - $result = $this->addProduct($wishlistItem->product_id, $wishlistItem->additional); - - if ($result) { - $this->wishlistRepository->delete($wishlistItem->id); - - return true; - } - - return false; - } - - /** - * Function to move a already added product to wishlist will run only on customer - * authentication. - * - * @param int $itemId - * @return bool - */ - public function moveToWishlist($itemId) + public function toArray() { $cart = $this->getCart(); - $cartItem = $cart->items()->find($itemId); + $data = $cart->toArray(); - if (! $cartItem) { - return false; + $data['billing_address'] = $cart->billing_address->toArray(); + + if ($cart->haveStockableItems()) { + $data['shipping_address'] = $cart->shipping_address->toArray(); + + $data['selected_shipping_rate'] = $cart->selected_shipping_rate ? $cart->selected_shipping_rate->toArray() : 0.0; } - $wishlistItems = $this->wishlistRepository->findWhere([ - 'customer_id' => $this->getCurrentCustomer()->user()->id, - 'product_id' => $cartItem->product_id, - ]); + $data['payment'] = $cart->payment->toArray(); - $found = false; + $data['items'] = $cart->items->toArray(); - foreach ($wishlistItems as $wishlistItem) { - $options = $wishlistItem->item_options; - - if (! $options) { - $options = ['product_id' => $wishlistItem->product_id]; - } - - if ($cartItem->product->getTypeInstance()->compareOptions($cartItem->additional, $options)) { - $found = true; - } - } - - if (! $found) { - $this->wishlistRepository->create([ - 'channel_id' => $cart->channel_id, - 'customer_id' => $this->getCurrentCustomer()->user()->id, - 'product_id' => $cartItem->product_id, - 'additional' => $cartItem->additional, - ]); - } - - $result = $this->cartItemRepository->delete($itemId); - - if (! $cart->items->count()) { - $this->cartRepository->delete($cart->id); - } - - $this->collectTotals(); - - return true; + return $data; } /** - * Set coupon code to the cart + * Set Item tax to zero. * - * @param string $code - * @return \Webkul\Checkout\Contracts\Cart + * @param \Webkul\Checkout\Contracts\CartItem $item + * @return \Webkul\Checkout\Contracts\CartItem */ - public function setCouponCode($code) + protected function setItemTaxToZero(\Webkul\Checkout\Contracts\CartItem $item): \Webkul\Checkout\Contracts\CartItem { - $cart = $this->getCart(); + $item->tax_percent = 0; + $item->tax_amount = 0; + $item->base_tax_amount = 0; - $cart->coupon_code = $code; - - $cart->save(); - - return $this; - } - - /** - * Remove coupon code from cart - * - * @return \Webkul\Checkout\Contracts\Cart - */ - public function removeCouponCode() - { - $cart = $this->getCart(); - - $cart->coupon_code = null; - - $cart->save(); - - return $this; + return $item; } /** @@ -1043,7 +804,8 @@ class Cart */ private function assignCustomerFields(\Webkul\Checkout\Contracts\Cart $cart): void { - if ($this->getCurrentCustomer()->check() + if ( + $this->getCurrentCustomer()->check() && ($user = $this->getCurrentCustomer()->user()) && $this->profileIsComplete($user) ) { @@ -1058,10 +820,9 @@ class Cart } /** - * Round cart totals + * Round cart totals. * * @param \Webkul\Checkout\Models\Cart $cart - * * @return \Webkul\Checkout\Models\Cart */ private function finalizeCartTotals(CartModel $cart): CartModel @@ -1079,13 +840,13 @@ class Cart } /** - * Returns true, if cart item is inactive + * Returns true, if cart item is inactive. * * @param \Webkul\Checkout\Contracts\CartItem $item - * * @return bool */ - private function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool { + private function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool + { static $loadedCartItem = []; if (array_key_exists($item->product_id, $loadedCartItem)) { @@ -1096,8 +857,9 @@ class Cart } /** - * @param $user + * Is profile is complete. * + * @param $user * @return bool */ private function profileIsComplete($user): bool @@ -1106,6 +868,8 @@ class Cart } /** + * Fill customer attributes. + * * @return array */ private function fillCustomerAttributes(): array @@ -1125,6 +889,8 @@ class Cart } /** + * Fill address attributes. + * * @return array */ private function fillAddressAttributes(array $addressAttributes): array @@ -1143,16 +909,18 @@ class Cart } /** - * @param array $data - * @param array $billingAddress - * @param array $shippingAddress + * Save addresses when requested. + * + * @param array $data + * @param array $billingAddress + * @param array $shippingAddress + * @return void */ private function saveAddressesWhenRequested( array $data, array $billingAddress, array $shippingAddress - ): void - { + ): void { $shippingAddress['cart_id'] = $billingAddress['cart_id'] = NULL; if (isset($data['billing']['save_as_address']) && $data['billing']['save_as_address']) { @@ -1165,9 +933,10 @@ class Cart } /** - * @param $data - * @param $cart + * Gather billing address. * + * @param $data + * @param $cart * @return array */ private function gatherBillingAddress($data, \Webkul\Checkout\Models\Cart $cart): array @@ -1189,14 +958,14 @@ class Cart $this->fillAddressAttributes($data['billing']) ); - return $billingAddress; } /** - * @param $data - * @param \Webkul\Checkout\Cart|null $cart + * Gather shipping address. * + * @param array $data + * @param \Webkul\Checkout\Cart|null $cart * @return array */ private function gatherShippingAddress($data, \Webkul\Checkout\Models\Cart $cart): array @@ -1222,18 +991,18 @@ class Cart } /** - * @param \Webkul\Checkout\Cart|null $cart - * @param array $billingAddressData - * @param array $shippingAddressData + * Link addresses. * + * @param \Webkul\Checkout\Cart|null $cart + * @param array $billingAddressData + * @param array $shippingAddressData * @throws \Prettus\Validator\Exceptions\ValidatorException */ private function linkAddresses( \Webkul\Checkout\Models\Cart $cart, array $billingAddressData, array $shippingAddressData - ): void - { + ): void { $billingAddressModel = $cart->billing_address; if ($billingAddressModel) { $billingAddressData['address_type'] = CartAddress::ADDRESS_TYPE_BILLING; @@ -1251,11 +1020,15 @@ class Cart } } else { if (isset($billingAddressData['use_for_shipping']) && $billingAddressData['use_for_shipping']) { - $this->cartAddressRepository->create(array_merge($billingAddressData, - ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING])); + $this->cartAddressRepository->create(array_merge( + $billingAddressData, + ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING] + )); } else { - $this->cartAddressRepository->create(array_merge($shippingAddressData, - ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING])); + $this->cartAddressRepository->create(array_merge( + $shippingAddressData, + ['address_type' => CartAddress::ADDRESS_TYPE_SHIPPING] + )); } } } @@ -1271,39 +1044,4 @@ class Cart } } } - - /** - * Check whether cart has product. - * - * @param \Webkul\Product\Models\Product $product - * @return bool - */ - public function hasProduct($product): bool - { - $cart = \Cart::getCart(); - - if (! $cart) { - return false; - } - - $count = $cart->all_items()->where('product_id', $product->id)->count(); - - return $count > 0 ? true : false; - } - - /** - * Check minimum order. - * - * @return boolean - */ - public function checkMinimumOrder(): bool - { - $cart = $this->getCart(); - - if (! $cart) { - return false; - } - - return $cart->checkMinimumOrder(); - } } diff --git a/packages/Webkul/Checkout/src/Http/Middleware/CartMerger.php b/packages/Webkul/Checkout/src/Http/Middleware/CartMerger.php new file mode 100644 index 000000000..bf56b5356 --- /dev/null +++ b/packages/Webkul/Checkout/src/Http/Middleware/CartMerger.php @@ -0,0 +1,22 @@ +getCart(); + + $cart->coupon_code = $code; + + $cart->save(); + + return $this; + } + + /** + * Remove coupon code from the cart. + * + * @return \Webkul\Checkout\Contracts\Cart + */ + public function removeCouponCode() + { + $cart = $this->getCart(); + + $cart->coupon_code = null; + + $cart->save(); + + return $this; + } +} \ No newline at end of file diff --git a/packages/Webkul/Checkout/src/Traits/CartTools.php b/packages/Webkul/Checkout/src/Traits/CartTools.php new file mode 100644 index 000000000..fa65a30ab --- /dev/null +++ b/packages/Webkul/Checkout/src/Traits/CartTools.php @@ -0,0 +1,244 @@ +getCurrentCustomer()->check()) { + session()->put('cart', $cart); + } + } + + /** + * This method handles when guest has some of cart products and then logs in. + * + * @return void + */ + public function mergeCart(): void + { + if (session()->has('cart')) { + $cart = $this->cartRepository->findOneWhere([ + 'customer_id' => $this->getCurrentCustomer()->user()->id, + 'is_active' => 1, + ]); + + $guestCart = session()->get('cart'); + + /** + * When the logged in customer is not having any of the cart instance previously and are active. + */ + if (! $cart) { + $this->cartRepository->update([ + 'customer_id' => $this->getCurrentCustomer()->user()->id, + 'is_guest' => 0, + 'customer_first_name' => $this->getCurrentCustomer()->user()->first_name, + 'customer_last_name' => $this->getCurrentCustomer()->user()->last_name, + 'customer_email' => $this->getCurrentCustomer()->user()->email, + ], $guestCart->id); + + session()->forget('cart'); + + return; + } + + foreach ($guestCart->items as $guestCartItem) { + $this->addProduct($guestCartItem->product_id, $guestCartItem->additional); + } + + $this->collectTotals(); + + $this->cartRepository->delete($guestCart->id); + + session()->forget('cart'); + } + } + + /** + * This method will merge deactivated cart, when a user suddenly navigates away + * from the checkout after click the buy now button. + * + * @return void + */ + public function mergeDeactivatedCart(): void + { + if (session()->has('deactivated_cart_id')) { + $deactivatedCartId = session()->get('deactivated_cart_id'); + + if ($this->getCart()) { + $deactivatedCart = $this->cartRepository->find($deactivatedCartId); + + foreach ($deactivatedCart->items as $deactivatedCartItem) { + $this->addProduct($deactivatedCartItem->product_id, $deactivatedCartItem->additional); + } + + $this->collectTotals(); + } else { + $this->cartRepository->update(['is_active' => true], $deactivatedCartId); + } + + session()->forget('deactivated_cart_id'); + } + } + + /** + * This method will deactivate the current cart if + * buy now is active. + * + * @return void + */ + public function deactivateCurrentCartIfBuyNowIsActive() + { + if (request()->get('is_buy_now')) { + if ($deactivatedCart = $this->getCart()) { + session()->put('deactivated_cart_id', $deactivatedCart->id); + + $this->deActivateCart(); + } + } + } + + /** + * This method will reactivate the cart which is deactivated at the the time of buy now functionality. + * + * @return void + */ + public function activateCartIfSessionHasDeactivatedCartId(): void + { + if (session()->has('deactivated_cart_id')) { + $deactivatedCartId = session()->get('deactivated_cart_id'); + + $this->activateCart($deactivatedCartId); + + session()->forget('deactivated_cart_id'); + } + } + + /** + * Deactivates current cart. + * + * @return void + */ + public function deActivateCart(): void + { + if ($cart = $this->getCart()) { + $this->cartRepository->update(['is_active' => false], $cart->id); + + if (session()->has('cart')) { + session()->forget('cart'); + } + } + } + + /** + * Activate the cart by id. + * + * @param int $cartId + * @return void + */ + public function activateCart($cartId): void + { + $this->cartRepository->update(['is_active' => true], $cartId); + + $this->putCart($this->cartRepository->find($cartId)); + } + + /** + * Move a wishlist item to cart. + * + * @param \Webkul\Customer\Contracts\WishlistItem $wishlistItem + * @return bool + */ + public function moveToCart($wishlistItem) + { + if (! $wishlistItem->product->getTypeInstance()->canBeMovedFromWishlistToCart($wishlistItem)) { + return false; + } + + if (! $wishlistItem->additional) { + $wishlistItem->additional = ['product_id' => $wishlistItem->product_id, 'quantity' => 1]; + } + + request()->merge($wishlistItem->additional); + + $result = $this->addProduct($wishlistItem->product_id, $wishlistItem->additional); + + if ($result) { + $this->wishlistRepository->delete($wishlistItem->id); + + return true; + } + + return false; + } + + /** + * Function to move a already added product to wishlist will run only on customer + * authentication. + * + * @param int $itemId + * @return bool + */ + public function moveToWishlist($itemId) + { + $cart = $this->getCart(); + + $cartItem = $cart->items()->find($itemId); + + if (! $cartItem) { + return false; + } + + $wishlistItems = $this->wishlistRepository->findWhere([ + 'customer_id' => $this->getCurrentCustomer()->user()->id, + 'product_id' => $cartItem->product_id, + ]); + + $found = false; + + foreach ($wishlistItems as $wishlistItem) { + $options = $wishlistItem->item_options; + + if (! $options) { + $options = ['product_id' => $wishlistItem->product_id]; + } + + if ($cartItem->product->getTypeInstance()->compareOptions($cartItem->additional, $options)) { + $found = true; + } + } + + if (! $found) { + $this->wishlistRepository->create([ + 'channel_id' => $cart->channel_id, + 'customer_id' => $this->getCurrentCustomer()->user()->id, + 'product_id' => $cartItem->product_id, + 'additional' => $cartItem->additional, + ]); + } + + $result = $this->cartItemRepository->delete($itemId); + + if (! $cart->items->count()) { + $this->cartRepository->delete($cart->id); + } + + $this->collectTotals(); + + return true; + } +} diff --git a/packages/Webkul/Checkout/src/Traits/CartValidators.php b/packages/Webkul/Checkout/src/Traits/CartValidators.php new file mode 100644 index 000000000..f08720df8 --- /dev/null +++ b/packages/Webkul/Checkout/src/Traits/CartValidators.php @@ -0,0 +1,99 @@ +all_items()->where('product_id', $product->id)->count(); + + return $count > 0 ? true : false; + } + + /** + * Checks if cart has any error. + * + * @return bool + */ + public function hasError(): bool + { + if (! $this->getCart()) { + return true; + } + + if (! $this->isItemsHaveSufficientQuantity()) { + return true; + } + + return false; + } + + /** + * Checks if all cart items have sufficient quantity. + * + * @return bool + */ + public function isItemsHaveSufficientQuantity(): bool + { + $cart = cart()->getCart(); + + if (! $cart) { + return false; + } + + foreach ($cart->items as $item) { + if (! $this->isItemHaveQuantity($item)) { + return false; + } + } + + return true; + } + + /** + * Checks if all cart items have sufficient quantity. + * + * @param \Webkul\Checkout\Contracts\CartItem $item + * @return bool + */ + public function isItemHaveQuantity($item): bool + { + return $item->product->getTypeInstance()->isItemHaveQuantity($item); + } + + /** + * Check minimum order. + * + * @return boolean + */ + public function checkMinimumOrder(): bool + { + $cart = $this->getCart(); + + if (! $cart) { + return false; + } + + return $cart->checkMinimumOrder(); + } +} \ No newline at end of file diff --git a/packages/Webkul/Shop/src/Http/Controllers/CartController.php b/packages/Webkul/Shop/src/Http/Controllers/CartController.php index ac88f9e0d..f885ad43e 100755 --- a/packages/Webkul/Shop/src/Http/Controllers/CartController.php +++ b/packages/Webkul/Shop/src/Http/Controllers/CartController.php @@ -68,6 +68,8 @@ class CartController extends Controller public function add($id) { try { + Cart::deactivateCurrentCartIfBuyNowIsActive(); + $result = Cart::addProduct($id, request()->all()); if ($this->onFailureAddingToCart($result)) { diff --git a/packages/Webkul/Shop/src/Http/Controllers/OnepageController.php b/packages/Webkul/Shop/src/Http/Controllers/OnepageController.php index e5f6b6c3c..6fd60b4f5 100755 --- a/packages/Webkul/Shop/src/Http/Controllers/OnepageController.php +++ b/packages/Webkul/Shop/src/Http/Controllers/OnepageController.php @@ -206,6 +206,8 @@ class OnepageController extends Controller Cart::deActivateCart(); + Cart::activateCartIfSessionHasDeactivatedCartId(); + session()->flash('order', $order); return response()->json([ diff --git a/packages/Webkul/Shop/src/Http/routes.php b/packages/Webkul/Shop/src/Http/routes.php index 6486fb236..edb29e764 100755 --- a/packages/Webkul/Shop/src/Http/routes.php +++ b/packages/Webkul/Shop/src/Http/routes.php @@ -1,314 +1,360 @@ ['web', 'locale', 'theme', 'currency']], function () { - //Store front home + /** + * Store front home. + */ Route::get('/', 'Webkul\Shop\Http\Controllers\HomeController@index')->defaults('_config', [ 'view' => 'shop::home.index' ])->name('shop.home.index'); - //subscription - //subscribe - Route::get('/subscribe', 'Webkul\Shop\Http\Controllers\SubscriptionController@subscribe')->name('shop.subscribe'); - - //unsubscribe - Route::get('/unsubscribe/{token}', 'Webkul\Shop\Http\Controllers\SubscriptionController@unsubscribe')->name('shop.unsubscribe'); - - //Store front search + /** + * Store front search. + */ Route::get('/search', 'Webkul\Shop\Http\Controllers\SearchController@index')->defaults('_config', [ 'view' => 'shop::search.search' ])->name('shop.search.index'); - //Upload image for search product Route::post('/upload-search-image', 'Webkul\Shop\Http\Controllers\HomeController@upload')->name('shop.image.search.upload'); - //Country State Selector + /** + * Subscription. + */ + Route::get('/subscribe', 'Webkul\Shop\Http\Controllers\SubscriptionController@subscribe')->name('shop.subscribe'); + + Route::get('/unsubscribe/{token}', 'Webkul\Shop\Http\Controllers\SubscriptionController@unsubscribe')->name('shop.unsubscribe'); + + /** + * Country-State selector. + */ Route::get('get/countries', 'Webkul\Core\Http\Controllers\CountryStateController@getCountries')->defaults('_config', [ 'view' => 'shop::test' ])->name('get.countries'); - //Get States When Country is Passed + /** + * Get States when Country is passed. + */ Route::get('get/states/{country}', 'Webkul\Core\Http\Controllers\CountryStateController@getStates')->defaults('_config', [ 'view' => 'shop::test' ])->name('get.states'); - //checkout and cart - //Cart Items(listing) + /** + * Cart, coupons and checkout. + */ + // Cart items listing. Route::get('checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@index')->defaults('_config', [ 'view' => 'shop::checkout.cart.index' ])->name('shop.checkout.cart.index'); - Route::post('checkout/cart/coupon', 'Webkul\Shop\Http\Controllers\CartController@applyCoupon')->name('shop.checkout.cart.coupon.apply'); - - Route::delete('checkout/cart/coupon', 'Webkul\Shop\Http\Controllers\CartController@removeCoupon')->name('shop.checkout.coupon.remove.coupon'); - - //Cart Items Add + // Add cart items. Route::post('checkout/cart/add/{id}', 'Webkul\Shop\Http\Controllers\CartController@add')->defaults('_config', [ 'redirect' => 'shop.checkout.cart.index' ])->name('cart.add'); - //Cart Items Remove + // Cart items remove. Route::get('checkout/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->name('cart.remove'); - //Cart Update Before Checkout + // Cart update before checkout. Route::post('/checkout/cart', 'Webkul\Shop\Http\Controllers\CartController@updateBeforeCheckout')->defaults('_config', [ 'redirect' => 'shop.checkout.cart.index' ])->name('shop.checkout.cart.update'); - //Cart Items Remove + // Cart items remove. Route::get('/checkout/cart/remove/{id}', 'Webkul\Shop\Http\Controllers\CartController@remove')->defaults('_config', [ 'redirect' => 'shop.checkout.cart.index' ])->name('shop.checkout.cart.remove'); - //Checkout Index page + // Move item to wishlist from cart. + Route::post('move/wishlist/{id}', 'Webkul\Shop\Http\Controllers\CartController@moveToWishlist')->name('shop.movetowishlist'); + + // Apply coupons. + Route::post('checkout/cart/coupon', 'Webkul\Shop\Http\Controllers\CartController@applyCoupon')->name('shop.checkout.cart.coupon.apply'); + + // Remove coupons. + Route::delete('checkout/cart/coupon', 'Webkul\Shop\Http\Controllers\CartController@removeCoupon')->name('shop.checkout.coupon.remove.coupon'); + + // Checkout index page. Route::get('/checkout/onepage', 'Webkul\Shop\Http\Controllers\OnepageController@index')->defaults('_config', [ 'view' => 'shop::checkout.onepage' ])->name('shop.checkout.onepage.index'); - //Checkout Save Order + // Checkout get summary. Route::get('/checkout/summary', 'Webkul\Shop\Http\Controllers\OnepageController@summary')->name('shop.checkout.summary'); - //Checkout Save Address Form Store + // Checkout save address form. Route::post('/checkout/save-address', 'Webkul\Shop\Http\Controllers\OnepageController@saveAddress')->name('shop.checkout.save-address'); - //Checkout Save Shipping Address Form Store + // Checkout save shipping address form. Route::post('/checkout/save-shipping', 'Webkul\Shop\Http\Controllers\OnepageController@saveShipping')->name('shop.checkout.save-shipping'); - //Checkout Save Payment Method Form + // Checkout save payment method form. Route::post('/checkout/save-payment', 'Webkul\Shop\Http\Controllers\OnepageController@savePayment')->name('shop.checkout.save-payment'); - /* check minimum order */ + // Check minimum order. Route::post('/checkout/check-minimum-order', 'Webkul\Shop\Http\Controllers\OnepageController@checkMinimumOrder')->name('shop.checkout.check-minimum-order'); - //Checkout Save Order + // Checkout save order. Route::post('/checkout/save-order', 'Webkul\Shop\Http\Controllers\OnepageController@saveOrder')->name('shop.checkout.save-order'); - //Checkout Order Successfull + // Checkout order successful. Route::get('/checkout/success', 'Webkul\Shop\Http\Controllers\OnepageController@success')->defaults('_config', [ 'view' => 'shop::checkout.success' ])->name('shop.checkout.success'); - //Shop buynow button action - Route::post('move/wishlist/{id}', 'Webkul\Shop\Http\Controllers\CartController@moveToWishlist')->name('shop.movetowishlist'); - - Route::get('/downloadable/download-sample/{type}/{id}', 'Webkul\Shop\Http\Controllers\ProductController@downloadSample')->name('shop.downloadable.download_sample'); - - // Show Product Review Form + /** + * Product reviews. + */ + // Show product review form. Route::get('/reviews/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@show')->defaults('_config', [ 'view' => 'shop::products.reviews.index' ])->name('shop.reviews.index'); - // Show Product Review(listing) + // Show product review listing. Route::get('/product/{slug}/review', 'Webkul\Shop\Http\Controllers\ReviewController@create')->defaults('_config', [ 'view' => 'shop::products.reviews.create' ])->name('shop.reviews.create'); - // Show Product Review Form Store + // Store product review. Route::post('/product/{slug}/review', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [ 'redirect' => 'shop.home.index' ])->name('shop.reviews.store'); - // Download file or image + /** + * Downloadable products. + */ + Route::get('/downloadable/download-sample/{type}/{id}', 'Webkul\Shop\Http\Controllers\ProductController@downloadSample')->name('shop.downloadable.download_sample'); + Route::get('/product/{id}/{attribute_id}', 'Webkul\Shop\Http\Controllers\ProductController@download')->defaults('_config', [ 'view' => 'shop.products.index' ])->name('shop.product.file.download'); - //customer routes starts here + /** + * These are the routes which are used during checkout for checking the customer. + * So, placed outside the cart merger middleware. + */ Route::prefix('customer')->group(function () { - // forgot Password Routes - // Forgot Password Form Show - Route::get('/forgot-password', 'Webkul\Customer\Http\Controllers\ForgotPasswordController@create')->defaults('_config', [ - 'view' => 'shop::customers.signup.forgot-password' - ])->name('customer.forgot-password.create'); - - // Forgot Password Form Store - Route::post('/forgot-password', 'Webkul\Customer\Http\Controllers\ForgotPasswordController@store')->name('customer.forgot-password.store'); - - // Reset Password Form Show - Route::get('/reset-password/{token}', 'Webkul\Customer\Http\Controllers\ResetPasswordController@create')->defaults('_config', [ - 'view' => 'shop::customers.signup.reset-password' - ])->name('customer.reset-password.create'); - - // Reset Password Form Store - Route::post('/reset-password', 'Webkul\Customer\Http\Controllers\ResetPasswordController@store')->defaults('_config', [ - 'redirect' => 'customer.profile.index' - ])->name('customer.reset-password.store'); - - // Login Routes - // Login form show - Route::get('login', 'Webkul\Customer\Http\Controllers\SessionController@show')->defaults('_config', [ - 'view' => 'shop::customers.session.index', - ])->name('customer.session.index'); - - // Login form store - Route::post('login', 'Webkul\Customer\Http\Controllers\SessionController@create')->defaults('_config', [ - 'redirect' => 'customer.profile.index' - ])->name('customer.session.create'); - - // Registration Routes - //registration form show - Route::get('register', 'Webkul\Customer\Http\Controllers\RegistrationController@show')->defaults('_config', [ - 'view' => 'shop::customers.signup.index' - ])->name('customer.register.index'); - - //registration form store - Route::post('register', 'Webkul\Customer\Http\Controllers\RegistrationController@create')->defaults('_config', [ - 'redirect' => 'customer.session.index', - ])->name('customer.register.create'); - - //verify account - Route::get('/verify-account/{token}', 'Webkul\Customer\Http\Controllers\RegistrationController@verifyAccount')->name('customer.verify'); - - //resend verification email - Route::get('/resend/verification/{email}', 'Webkul\Customer\Http\Controllers\RegistrationController@resendVerificationEmail')->name('customer.resend.verification-email'); - - // for customer login checkout + // For customer exist check. Route::post('/customer/exist', 'Webkul\Shop\Http\Controllers\OnepageController@checkExistCustomer')->name('customer.checkout.exist'); - // for customer login checkout + // For customer login checkout. Route::post('/customer/checkout/login', 'Webkul\Shop\Http\Controllers\OnepageController@loginForCheckout')->name('customer.checkout.login'); + }); - // Auth Routes - Route::group(['middleware' => ['customer']], function () { + /** + * Cart merger middleware. This middleware will take care of the items + * which are deactivated at the time of buy now functionality. If somehow + * user redirects without completing the checkout then this will merge + * full cart. + * + * If some routes are not able to merge the cart, then place the route in this + * group. + */ + Route::group(['middleware' => ['cart.merger']], function () { + /** + * Customer routes. + */ + Route::prefix('customer')->group(function () { + /** + * Forgot password routes. + */ + // Show forgot password form. + Route::get('/forgot-password', 'Webkul\Customer\Http\Controllers\ForgotPasswordController@create')->defaults('_config', [ + 'view' => 'shop::customers.signup.forgot-password' + ])->name('customer.forgot-password.create'); - //Customer logout - Route::get('logout', 'Webkul\Customer\Http\Controllers\SessionController@destroy')->defaults('_config', [ - 'redirect' => 'customer.session.index' - ])->name('customer.session.destroy'); + // Store forgot password. + Route::post('/forgot-password', 'Webkul\Customer\Http\Controllers\ForgotPasswordController@store')->name('customer.forgot-password.store'); - //Customer Wishlist add - Route::post('wishlist/add/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@add')->name('customer.wishlist.add'); + // Reset password form. + Route::get('/reset-password/{token}', 'Webkul\Customer\Http\Controllers\ResetPasswordController@create')->defaults('_config', [ + 'view' => 'shop::customers.signup.reset-password' + ])->name('customer.reset-password.create'); - //Customer Wishlist remove - Route::delete('wishlist/remove/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@remove')->name('customer.wishlist.remove'); + // Store reset password. + Route::post('/reset-password', 'Webkul\Customer\Http\Controllers\ResetPasswordController@store')->defaults('_config', [ + 'redirect' => 'customer.profile.index' + ])->name('customer.reset-password.store'); - //Customer Wishlist remove - Route::delete('wishlist/removeall', 'Webkul\Customer\Http\Controllers\WishlistController@removeAll')->name('customer.wishlist.removeall'); + /** + * Login routes. + */ + // Login form. + Route::get('login', 'Webkul\Customer\Http\Controllers\SessionController@show')->defaults('_config', [ + 'view' => 'shop::customers.session.index', + ])->name('customer.session.index'); - //Customer Wishlist move to cart - Route::get('wishlist/move/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@move')->name('customer.wishlist.move'); + // Login. + Route::post('login', 'Webkul\Customer\Http\Controllers\SessionController@create')->defaults('_config', [ + 'redirect' => 'customer.profile.index' + ])->name('customer.session.create'); - //customer account - Route::prefix('account')->group(function () { - //Customer Dashboard Route - Route::get('index', 'Webkul\Customer\Http\Controllers\AccountController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.index' - ])->name('customer.account.index'); + /** + * Registration routes. + */ + // Show registration form. + Route::get('register', 'Webkul\Customer\Http\Controllers\RegistrationController@show')->defaults('_config', [ + 'view' => 'shop::customers.signup.index' + ])->name('customer.register.index'); - //Customer Profile Show - Route::get('profile', 'Webkul\Customer\Http\Controllers\CustomerController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.profile.index' - ])->name('customer.profile.index'); + // Store new registered user. + Route::post('register', 'Webkul\Customer\Http\Controllers\RegistrationController@create')->defaults('_config', [ + 'redirect' => 'customer.session.index', + ])->name('customer.register.create'); - //Customer Profile Edit Form Show - Route::get('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@edit')->defaults('_config', [ - 'view' => 'shop::customers.account.profile.edit' - ])->name('customer.profile.edit'); + // Verify account. + Route::get('/verify-account/{token}', 'Webkul\Customer\Http\Controllers\RegistrationController@verifyAccount')->name('customer.verify'); - //Customer Profile Edit Form Store - Route::post('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@update')->defaults('_config', [ - 'redirect' => 'customer.profile.index' - ])->name('customer.profile.store'); + // Resend verification email. + Route::get('/resend/verification/{email}', 'Webkul\Customer\Http\Controllers\RegistrationController@resendVerificationEmail')->name('customer.resend.verification-email'); - //Customer Profile Delete Form Store - Route::post('profile/destroy', 'Webkul\Customer\Http\Controllers\CustomerController@destroy')->defaults('_config', [ - 'redirect' => 'customer.profile.index' - ])->name('customer.profile.destroy'); + /** + * Customer authented routes. All the below routes only be accessible + * if customer is authenticated. + */ + Route::group(['middleware' => ['customer']], function () { + /** + * Logout. + */ + Route::get('logout', 'Webkul\Customer\Http\Controllers\SessionController@destroy')->defaults('_config', [ + 'redirect' => 'customer.session.index' + ])->name('customer.session.destroy'); - /* Profile Routes Ends Here */ + /** + * Wishlist. + */ + Route::post('wishlist/add/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@add')->name('customer.wishlist.add'); - /* Routes for Addresses */ - //Customer Address Show - Route::get('addresses', 'Webkul\Customer\Http\Controllers\AddressController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.address.index' - ])->name('customer.address.index'); + Route::delete('wishlist/remove/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@remove')->name('customer.wishlist.remove'); - //Customer Address Create Form Show - Route::get('addresses/create', 'Webkul\Customer\Http\Controllers\AddressController@create')->defaults('_config', [ - 'view' => 'shop::customers.account.address.create' - ])->name('customer.address.create'); + Route::delete('wishlist/removeall', 'Webkul\Customer\Http\Controllers\WishlistController@removeAll')->name('customer.wishlist.removeall'); - //Customer Address Create Form Store - Route::post('addresses/create', 'Webkul\Customer\Http\Controllers\AddressController@store')->defaults('_config', [ - 'view' => 'shop::customers.account.address.address', - 'redirect' => 'customer.address.index' - ])->name('customer.address.store'); + Route::get('wishlist/move/{id}', 'Webkul\Customer\Http\Controllers\WishlistController@move')->name('customer.wishlist.move'); - //Customer Address Edit Form Show - Route::get('addresses/edit/{id}', 'Webkul\Customer\Http\Controllers\AddressController@edit')->defaults('_config', [ - 'view' => 'shop::customers.account.address.edit' - ])->name('customer.address.edit'); + /** + * Customer account. All the below routes are related to + * customer account details. + */ + Route::prefix('account')->group(function () { + /** + * Dashboard. + */ + Route::get('index', 'Webkul\Customer\Http\Controllers\AccountController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.index' + ])->name('customer.account.index'); - //Customer Address Edit Form Store - Route::put('addresses/edit/{id}', 'Webkul\Customer\Http\Controllers\AddressController@update')->defaults('_config', [ - 'redirect' => 'customer.address.index' - ])->name('customer.address.update'); + /** + * Profile. + */ + Route::get('profile', 'Webkul\Customer\Http\Controllers\CustomerController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.profile.index' + ])->name('customer.profile.index'); - //Customer Address Make Default - Route::get('addresses/default/{id}', 'Webkul\Customer\Http\Controllers\AddressController@makeDefault')->name('make.default.address'); + Route::get('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@edit')->defaults('_config', [ + 'view' => 'shop::customers.account.profile.edit' + ])->name('customer.profile.edit'); - //Customer Address Delete - Route::delete('addresses/delete/{id}', 'Webkul\Customer\Http\Controllers\AddressController@destroy')->name('address.delete'); + Route::post('profile/edit', 'Webkul\Customer\Http\Controllers\CustomerController@update')->defaults('_config', [ + 'redirect' => 'customer.profile.index' + ])->name('customer.profile.store'); - /* Wishlist route */ - //Customer wishlist(listing) - Route::get('wishlist', 'Webkul\Customer\Http\Controllers\WishlistController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.wishlist.wishlist' - ])->name('customer.wishlist.index'); + Route::post('profile/destroy', 'Webkul\Customer\Http\Controllers\CustomerController@destroy')->defaults('_config', [ + 'redirect' => 'customer.profile.index' + ])->name('customer.profile.destroy'); - /* Orders route */ - //Customer orders(listing) - Route::get('orders', 'Webkul\Shop\Http\Controllers\OrderController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.orders.index' - ])->name('customer.orders.index'); + /** + * Addresses. + */ + Route::get('addresses', 'Webkul\Customer\Http\Controllers\AddressController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.address.index' + ])->name('customer.address.index'); - //Customer downloadable products(listing) - Route::get('downloadable-products', 'Webkul\Shop\Http\Controllers\DownloadableProductController@index')->defaults('_config', [ - 'view' => 'shop::customers.account.downloadable_products.index' - ])->name('customer.downloadable_products.index'); + Route::get('addresses/create', 'Webkul\Customer\Http\Controllers\AddressController@create')->defaults('_config', [ + 'view' => 'shop::customers.account.address.create' + ])->name('customer.address.create'); - //Customer downloadable products(listing) - Route::get('downloadable-products/download/{id}', 'Webkul\Shop\Http\Controllers\DownloadableProductController@download')->defaults('_config', [ - 'view' => 'shop::customers.account.downloadable_products.index' - ])->name('customer.downloadable_products.download'); + Route::post('addresses/create', 'Webkul\Customer\Http\Controllers\AddressController@store')->defaults('_config', [ + 'view' => 'shop::customers.account.address.address', + 'redirect' => 'customer.address.index' + ])->name('customer.address.store'); - //Customer orders view summary and status - Route::get('orders/view/{id}', 'Webkul\Shop\Http\Controllers\OrderController@view')->defaults('_config', [ - 'view' => 'shop::customers.account.orders.view' - ])->name('customer.orders.view'); + Route::get('addresses/edit/{id}', 'Webkul\Customer\Http\Controllers\AddressController@edit')->defaults('_config', [ + 'view' => 'shop::customers.account.address.edit' + ])->name('customer.address.edit'); - //Prints invoice - Route::get('orders/print/{id}', 'Webkul\Shop\Http\Controllers\OrderController@print')->defaults('_config', [ - 'view' => 'shop::customers.account.orders.print' - ])->name('customer.orders.print'); + Route::put('addresses/edit/{id}', 'Webkul\Customer\Http\Controllers\AddressController@update')->defaults('_config', [ + 'redirect' => 'customer.address.index' + ])->name('customer.address.update'); - Route::post('/orders/cancel/{id}', 'Webkul\Shop\Http\Controllers\OrderController@cancel')->name('customer.orders.cancel'); + Route::get('addresses/default/{id}', 'Webkul\Customer\Http\Controllers\AddressController@makeDefault')->name('make.default.address'); - /* Reviews route */ - //Customer reviews - Route::get('reviews', 'Webkul\Customer\Http\Controllers\CustomerController@reviews')->defaults('_config', [ - 'view' => 'shop::customers.account.reviews.index' - ])->name('customer.reviews.index'); + Route::delete('addresses/delete/{id}', 'Webkul\Customer\Http\Controllers\AddressController@destroy')->name('address.delete'); - //Customer review delete - Route::delete('reviews/delete/{id}', 'Webkul\Shop\Http\Controllers\ReviewController@destroy')->defaults('_config', [ - 'redirect' => 'customer.reviews.index' - ])->name('customer.review.delete'); + /** + * Wishlist. + */ + Route::get('wishlist', 'Webkul\Customer\Http\Controllers\WishlistController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.wishlist.wishlist' + ])->name('customer.wishlist.index'); - //Customer all review delete - Route::delete('reviews/all-delete', 'Webkul\Shop\Http\Controllers\ReviewController@deleteAll')->defaults('_config', [ - 'redirect' => 'customer.reviews.index' - ])->name('customer.review.deleteall'); + /** + * Orders. + */ + Route::get('orders', 'Webkul\Shop\Http\Controllers\OrderController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.orders.index' + ])->name('customer.orders.index'); + + Route::get('orders/view/{id}', 'Webkul\Shop\Http\Controllers\OrderController@view')->defaults('_config', [ + 'view' => 'shop::customers.account.orders.view' + ])->name('customer.orders.view'); + + Route::get('orders/print/{id}', 'Webkul\Shop\Http\Controllers\OrderController@print')->defaults('_config', [ + 'view' => 'shop::customers.account.orders.print' + ])->name('customer.orders.print'); + + Route::post('/orders/cancel/{id}', 'Webkul\Shop\Http\Controllers\OrderController@cancel')->name('customer.orders.cancel'); + + /** + * Downloadable products. + */ + Route::get('downloadable-products', 'Webkul\Shop\Http\Controllers\DownloadableProductController@index')->defaults('_config', [ + 'view' => 'shop::customers.account.downloadable_products.index' + ])->name('customer.downloadable_products.index'); + + Route::get('downloadable-products/download/{id}', 'Webkul\Shop\Http\Controllers\DownloadableProductController@download')->defaults('_config', [ + 'view' => 'shop::customers.account.downloadable_products.index' + ])->name('customer.downloadable_products.download'); + + /** + * Reviews. + */ + Route::get('reviews', 'Webkul\Customer\Http\Controllers\CustomerController@reviews')->defaults('_config', [ + 'view' => 'shop::customers.account.reviews.index' + ])->name('customer.reviews.index'); + + Route::delete('reviews/delete/{id}', 'Webkul\Shop\Http\Controllers\ReviewController@destroy')->defaults('_config', [ + 'redirect' => 'customer.reviews.index' + ])->name('customer.review.delete'); + + Route::delete('reviews/all-delete', 'Webkul\Shop\Http\Controllers\ReviewController@deleteAll')->defaults('_config', [ + 'redirect' => 'customer.reviews.index' + ])->name('customer.review.deleteall'); + }); }); }); + + /** + * CMS pages. + */ + Route::get('page/{slug}', 'Webkul\CMS\Http\Controllers\Shop\PagePresenterController@presenter')->name('shop.cms.page'); + + /** + * Fallback route. + */ + Route::fallback(\Webkul\Shop\Http\Controllers\ProductsCategoriesProxyController::class . '@index') + ->defaults('_config', [ + 'product_view' => 'shop::products.view', + 'category_view' => 'shop::products.index' + ]) + ->name('shop.productOrCategory.index'); }); - //customer routes end here - - Route::get('page/{slug}', 'Webkul\CMS\Http\Controllers\Shop\PagePresenterController@presenter')->name('shop.cms.page'); - - Route::fallback(\Webkul\Shop\Http\Controllers\ProductsCategoriesProxyController::class . '@index') - ->defaults('_config', [ - 'product_view' => 'shop::products.view', - 'category_view' => 'shop::products.index' - ]) - ->name('shop.productOrCategory.index'); }); diff --git a/packages/Webkul/Velocity/src/Http/front-routes.php b/packages/Webkul/Velocity/src/Http/front-routes.php index 9cfb0e811..6f8e50bfb 100644 --- a/packages/Webkul/Velocity/src/Http/front-routes.php +++ b/packages/Webkul/Velocity/src/Http/front-routes.php @@ -2,23 +2,71 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function () { Route::namespace('Webkul\Velocity\Http\Controllers\Shop')->group(function () { - Route::get('/product-details/{slug}', 'ShopController@fetchProductDetails') - ->name('velocity.shop.product'); + /** + * Cart merger middleware. This middleware will take care of the items + * which are deactivated at the time of buy now functionality. If somehow + * user redirects without completing the checkout then this will merge + * full cart. + * + * If some routes are not able to merge the cart, then place the route in this + * group. + */ + Route::group(['middleware' => ['cart.merger']], function () { + /** + * Authenticated routes. All the routes inside this, will be passed + * by customer middleware. + */ + Route::group(['middleware' => ['customer']], function () { + /** + * Customer compare products. + */ + Route::get('/customer/account/comparison', 'ComparisonController@getComparisonList') + ->name('velocity.customer.product.compare') + ->defaults('_config', [ + 'view' => 'shop::customers.account.compare.index' + ]); + }); - Route::get('/categorysearch', 'ShopController@search') - ->name('velocity.search.index') - ->defaults('_config', [ - 'view' => 'shop::search.search' - ]); + /** + * Guest compare products. + */ + Route::get('/comparison', 'ComparisonController@getComparisonList') + ->name('velocity.product.compare') + ->defaults('_config', [ + 'view' => 'shop::guest.compare.index' + ]); - Route::get('/categories', 'ShopController@fetchCategories') - ->name('velocity.categoriest'); + Route::put('/comparison', 'ComparisonController@addCompareProduct') + ->name('customer.product.add.compare'); - Route::get('/category-details', 'ShopController@categoryDetails') - ->name('velocity.category.details'); + Route::delete('/comparison', 'ComparisonController@deleteComparisonProduct') + ->name('customer.product.delete.compare'); - Route::get('/fancy-category-details/{slug}', 'ShopController@fetchFancyCategoryDetails')->name('velocity.fancy.category.details'); + /** + * Categories and products. + */ + Route::get('/product-details/{slug}', 'ShopController@fetchProductDetails') + ->name('velocity.shop.product'); + Route::get('/categorysearch', 'ShopController@search') + ->name('velocity.search.index') + ->defaults('_config', [ + 'view' => 'shop::search.search' + ]); + + Route::get('/fancy-category-details/{slug}', 'ShopController@fetchFancyCategoryDetails') + ->name('velocity.fancy.category.details'); + + Route::get('/category-details', 'ShopController@categoryDetails') + ->name('velocity.category.details'); + + Route::get('/category-products/{categoryId}', 'ShopController@getCategoryProducts') + ->name('velocity.category.products'); + }); + + /** + * Cart, coupons and checkout. + */ Route::get('/mini-cart', 'CartController@getMiniCartDetails') ->name('velocity.cart.get.details'); @@ -28,33 +76,13 @@ Route::group(['middleware' => ['web', 'locale', 'theme', 'currency']], function Route::delete('/cart/remove/{id}', 'CartController@removeProductFromCart') ->name('velocity.cart.remove.product'); - Route::get('/comparison', 'ComparisonController@getComparisonList') - ->name('velocity.product.compare') - ->defaults('_config', [ - 'view' => 'shop::guest.compare.index' - ]); - - Route::group(['middleware' => ['customer']], function () { - Route::get('/customer/account/comparison', 'ComparisonController@getComparisonList') - ->name('velocity.customer.product.compare') - ->defaults('_config', [ - 'view' => 'shop::customers.account.compare.index' - ]); - }); - - Route::put('/comparison', 'ComparisonController@addCompareProduct') - ->name('customer.product.add.compare'); - - Route::delete('/comparison', 'ComparisonController@deleteComparisonProduct') - ->name('customer.product.delete.compare'); + Route::get('/categories', 'ShopController@fetchCategories') + ->name('velocity.categoriest'); Route::get('/items-count', 'ShopController@getItemsCount') ->name('velocity.product.item-count'); Route::get('/detailed-products', 'ShopController@getDetailedProducts') ->name('velocity.product.details'); - - Route::get('/category-products/{categoryId}', 'ShopController@getCategoryProducts') - ->name('velocity.category.products'); }); -}); \ No newline at end of file +}); diff --git a/tests/unit/Tax/Helpers/TaxCest.php b/tests/unit/Tax/Helpers/TaxCest.php index 2ed03a977..1c0864b91 100644 --- a/tests/unit/Tax/Helpers/TaxCest.php +++ b/tests/unit/Tax/Helpers/TaxCest.php @@ -109,6 +109,12 @@ class TaxCest foreach ($this->scenario['expectedTaxRates'] as $taxRate => $taxAmount) { $I->assertTrue(array_key_exists($taxRate, $result)); + $difference = abs($taxAmount - round($result[$taxRate], 2)); + + if ($difference <= 0.01 && $difference >= 0.0001) { + continue; + } + $I->assertEquals($taxAmount, $result[$taxRate]); } }