refactoring of validateCartItem methods of product types

This commit is contained in:
Steffen Mahler 2020-07-04 15:20:59 +02:00
parent 492ad97b6c
commit a44fa7445d
16 changed files with 373 additions and 158 deletions

View File

@ -12,12 +12,15 @@ use Webkul\BookingProduct\Repositories\BookingProductEventTicketRepository;
use Webkul\BookingProduct\Repositories\BookingProductRentalSlotRepository;
use Webkul\BookingProduct\Repositories\BookingProductTableSlotRepository;
use Webkul\BookingProduct\Repositories\BookingRepository;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Checkout\Models\CartItem;
class Booking
{
/**
* BookingProductRepository
*
*
* @return \Webkul\BookingProduct\Repositories\BookingProductRepository
*/
protected $bookingProductRepository;
@ -29,7 +32,7 @@ class Booking
/**
* BookingRepository
*
*
* @return \Webkul\BookingProduct\Repositories\BookingRepository
*/
protected $bookingRepository;
@ -93,7 +96,7 @@ class Booking
* @param string $type
* @return array
*/
public function getTypeHepler($type)
public function getTypeHelper($type)
{
return $this->typeHelpers[$type];
}
@ -316,10 +319,10 @@ class Booking
if ($qty && $currentTime <= $from) {
$slots[] = [
'from' => $from->format('h:i A'),
'to' => $to->format('h:i A'),
'timestamp' => $from->getTimestamp() . '-' . $to->getTimestamp(),
'qty' => $qty,
'from' => $from->format('h:i A'),
'to' => $to->format('h:i A'),
'timestamp' => $from->getTimestamp() . '-' . $to->getTimestamp(),
'qty' => $qty,
];
}
} else {
@ -368,7 +371,7 @@ class Booking
public function isSlotExpired($cartItem)
{
$bookingProduct = $this->bookingProductRepository->findOneByField('product_id', $cartItem['product_id']);
$typeHelper = app($this->typeHelpers[$bookingProduct->type]);
$slots = $typeHelper->getSlotsByDate($bookingProduct, $cartItem['additional']['booking']['date']);
@ -432,7 +435,7 @@ class Booking
'option_label' => Carbon::createFromTimeString($bookingProduct->available_to)->format('d F, Y'),
]
];
break;
case 'rental':
@ -465,7 +468,7 @@ class Booking
];
break;
case 'table':
$timestamps = explode('-', $data['booking']['slot']);
@ -490,7 +493,7 @@ class Booking
}
break;
default:
$timestamps = explode('-', $data['booking']['slot']);
@ -529,12 +532,20 @@ class Booking
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return void
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if ($this->isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -544,5 +555,24 @@ class Booking
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
/**
* Returns true, if cart item is inactive
*
* @param \Webkul\Checkout\Contracts\CartItem $item
*
* @return bool
*/
public function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool
{
if ($item->product->status === 0) {
return true;
}
return false;
}
}

View File

@ -5,6 +5,8 @@ namespace Webkul\BookingProduct\Helpers;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Webkul\Checkout\Facades\Cart;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Checkout\Models\CartItem;
class EventTicket extends Booking
{
@ -131,8 +133,16 @@ class EventTicket extends Booking
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return float
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if (parent::isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
$bookingProduct = $this->bookingProductRepository->findOneByField('product_id', $item->product_id);
@ -140,9 +150,9 @@ class EventTicket extends Booking
$ticket = $bookingProduct->event_tickets()->find($item->additional['booking']['ticket_id']);
if (! $ticket) {
Cart::removeItem($item->id);
$result->itemIsInactive();
return true;
return $result;
}
if ($this->isInSale($ticket)) {
@ -152,7 +162,7 @@ class EventTicket extends Booking
}
if ($price === $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -162,6 +172,9 @@ class EventTicket extends Booking
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
/**

View File

@ -5,6 +5,8 @@ namespace Webkul\BookingProduct\Helpers;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Webkul\Checkout\Facades\Cart;
use Webkul\Checkout\Models\CartItem;
use Webkul\Product\Datatypes\CartItemValidationResult;
class RentalSlot extends Booking
{
@ -159,7 +161,7 @@ class RentalSlot extends Booking
return $isExpired;
} else {
$currentTime = Carbon::now();
$requestedFromDate = Carbon::createFromTimeString($cartItem['additional']['booking']['date_from'] . " 00:00:00");
$requestedToDate = Carbon::createFromTimeString($cartItem['additional']['booking']['date_to'] . " 23:59:59");
@ -222,8 +224,16 @@ class RentalSlot extends Booking
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return void|null
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if (parent::isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
$bookingProduct = $this->bookingProductRepository->findOneByField('product_id', $item->product_id);
@ -234,11 +244,11 @@ class RentalSlot extends Booking
if (! isset($item->additional['booking']['date_from'])
|| ! isset($item->additional['booking']['date_to'])
) {
Cart::removeItem($item->id);
$result->itemIsInactive();
return true;
return $result;
}
$from = Carbon::createFromTimeString($item->additional['booking']['date_from'] . " 00:00:00");
$to = Carbon::createFromTimeString($item->additional['booking']['date_to'] . " 24:00:00");
@ -247,9 +257,9 @@ class RentalSlot extends Booking
if (! isset($item->additional['booking']['slot']['from'])
|| ! isset($item->additional['booking']['slot']['to'])
) {
Cart::removeItem($item->id);
$result->itemIsInactive();
return true;
return $result;
}
$from = Carbon::createFromTimestamp($item->additional['booking']['slot']['from']);
@ -259,7 +269,7 @@ class RentalSlot extends Booking
}
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -269,5 +279,8 @@ class RentalSlot extends Booking
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
}

View File

@ -4,6 +4,7 @@ namespace Webkul\BookingProduct\Type;
use Illuminate\Support\Arr;
use Webkul\Attribute\Repositories\AttributeRepository;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductAttributeValueRepository;
use Webkul\Product\Repositories\ProductInventoryRepository;
@ -13,6 +14,7 @@ use Webkul\BookingProduct\Repositories\BookingProductRepository;
use Webkul\BookingProduct\Helpers\Booking as BookingHelper;
use Webkul\Product\Type\Virtual;
use Carbon\Carbon;
use Webkul\Checkout\Models\CartItem;
class Booking extends Virtual
{
@ -133,7 +135,7 @@ class Booking extends Virtual
if (! $bookingProduct) {
return false;
}
if (in_array($bookingProduct->type, ['default', 'rental', 'table'])) {
return true;
}
@ -149,7 +151,7 @@ class Booking extends Virtual
{
$bookingProduct = $this->getBookingProduct($this->product->id);
return app($this->bookingHelper->getTypeHepler($bookingProduct->type))->isItemHaveQuantity($cartItem);
return app($this->bookingHelper->getTypeHelper($bookingProduct->type))->isItemHaveQuantity($cartItem);
}
/**
@ -171,7 +173,7 @@ class Booking extends Virtual
if ($bookingProduct->type == 'event') {
if (Carbon::now() > $bookingProduct->available_from && Carbon::now() > $bookingProduct->available_to) {
return trans('shop::app.checkout.cart.event.expired');
}
}
$filtered = Arr::where($data['booking']['qty'], function ($qty, $key) {
return $qty != 0;
@ -197,14 +199,14 @@ class Booking extends Virtual
if (is_string($cartProducts)) {
return $cartProducts;
}
$products = array_merge($products, $cartProducts);
}
} else {
$products = parent::prepareForCart($data);
}
$typeHelper = app($this->bookingHelper->getTypeHepler($bookingProduct->type));
$typeHelper = app($this->bookingHelper->getTypeHelper($bookingProduct->type));
if (! $typeHelper->isSlotAvailable($products)) {
return trans('shop::app.checkout.cart.quantity.inventory_warning');
@ -250,17 +252,26 @@ class Booking extends Virtual
/**
* Validate cart item product price
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return float
* @param \Webkul\Checkout\Models\CartItem $item
*
* @return \Webkul\Product\Datatypes\CartItemValidationResult
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if (parent::isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$bookingProduct = $this->getBookingProduct($item->product_id);
if (! $bookingProduct) {
return;
return $result;
}
return app($this->bookingHelper->getTypeHepler($bookingProduct->type))->validateCartItem($item);
return app($this->bookingHelper->getTypeHelper($bookingProduct->type))->validateCartItem($item);
}
}

View File

@ -571,16 +571,14 @@ class Cart
*
* @return void
*/
public function collectTotals()
public function collectTotals(): void
{
$validated = $this->validateItems();
if (! $validated) {
return false;
if (! $this->validateItems()) {
return;
}
if (! $cart = $this->getCart()) {
return false;
return;
}
Event::dispatch('checkout.cart.collect.totals.before', $cart);
@ -637,37 +635,42 @@ class Cart
*
* @return bool
*/
public function validateItems()
public function validateItems(): bool
{
$result = false;
if (! $cart = $this->getCart()) {
return;
return false;
}
if (count($cart->items) == 0) {
$this->cartRepository->delete($cart->id);
return false;
} else {
foreach ($cart->items as $item) {
$response = $item->product->getTypeInstance()->validateCartItem($item);
// ToDo: refactoring of all validateCartItem functions, at the moment they return nothing
if ($response) {
return;
}
}
$price = ! is_null($item->custom_price) ? $item->custom_price : $item->base_price;
foreach ($cart->items as $item) {
$validationResult = $item->product->getTypeInstance()->validateCartItem($item);
$this->cartItemRepository->update([
'price' => core()->convertPrice($price),
'base_price' => $price,
'total' => core()->convertPrice($price * $item->quantity),
'base_total' => $price * $item->quantity,
], $item->id);
if ($validationResult->isItemInactive()) {
$this->removeItem($item->id);
session()->flash('info', __('shop::app.checkout.cart.item.inactive'));
}
return true;
$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);
$result |= $validationResult->isCartDirty();
}
return $result;
}
/**
@ -1131,15 +1134,7 @@ class Cart
* @return bool
*/
private function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool {
if ($item->product->status === 0) {
return true;
}
if ($item->product->type === 'configurable' && $item->child && $item->child->product->status === 0) {
return true;
}
return false;
return $item->product->getTypeInstance()->isCartItemInactive($item);
}
/**

View File

@ -0,0 +1,39 @@
<?php
namespace Webkul\Product\Datatypes;
class CartItemValidationResult
{
/** @var bool $cartIsDirty */
private $cartIsDirty = false;
/** @var bool $itemIsInactive */
private $itemIsInactive = false;
/**
* @return bool
*/
public function isCartDirty(): bool
{
return $this->cartIsDirty;
}
/**
* @return bool
*/
public function isItemInactive(): bool
{
return $this->itemIsInactive;
}
public function itemIsInactive(): void
{
$this->itemIsInactive = true;
$this->cartIsDirty = true;
}
public function cartIsDirty(): void
{
$this->cartIsDirty = true;
}
}

View File

@ -3,8 +3,8 @@
namespace Webkul\Product\Type;
use Illuminate\Support\Facades\Storage;
use phpDocumentor\Reflection\Types\Boolean;
use Webkul\Attribute\Repositories\AttributeRepository;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductAttributeValueRepository;
use Webkul\Product\Repositories\ProductInventoryRepository;
@ -12,6 +12,7 @@ use Webkul\Product\Repositories\ProductImageRepository;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Product\Helpers\ProductImage;
use Webkul\Checkout\Facades\Cart;
use Webkul\Checkout\Models\CartItem;
abstract class AbstractType
{
@ -54,7 +55,7 @@ abstract class AbstractType
* Product Image helper instance
*
* @var \Webkul\Product\Helpers\ProductImage
*/
*/
protected $productImageHelper;
/**
@ -121,12 +122,13 @@ abstract class AbstractType
/**
* Create a new product type instance.
*
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @param \Webkul\Product\Repositories\ProductAttributeValueRepository $attributeValueRepository
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @param \Webkul\Product\Repositories\ProductAttributeValueRepository $attributeValueRepository
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
*
* @return void
*/
public function __construct(
@ -136,8 +138,7 @@ abstract class AbstractType
ProductInventoryRepository $productInventoryRepository,
ProductImageRepository $productImageRepository,
ProductImage $productImageHelper
)
{
) {
$this->attributeRepository = $attributeRepository;
$this->productRepository = $productRepository;
@ -152,7 +153,8 @@ abstract class AbstractType
}
/**
* @param array $data
* @param array $data
*
* @return \Webkul\Product\Contracts\Product
*/
public function create(array $data)
@ -161,9 +163,10 @@ abstract class AbstractType
}
/**
* @param array $data
* @param int $id
* @param string $attribute
* @param array $data
* @param int $id
* @param string $attribute
*
* @return \Webkul\Product\Contracts\Product
*/
public function update(array $data, $id, $attribute = "id")
@ -179,7 +182,7 @@ abstract class AbstractType
$data[$attribute->code] = isset($data[$attribute->code]) && $data[$attribute->code] ? 1 : 0;
}
if (! isset($data[$attribute->code])) {
if (!isset($data[$attribute->code])) {
continue;
}
@ -197,8 +200,8 @@ abstract class AbstractType
if ($attribute->type == 'image' || $attribute->type == 'file') {
$data[$attribute->code] = gettype($data[$attribute->code]) == 'object'
? request()->file($attribute->code)->store('product/' . $product->id)
: NULL;
? request()->file($attribute->code)->store('product/' . $product->id)
: null;
}
$attributeValue = $this->attributeValueRepository->findOneWhere([
@ -208,7 +211,7 @@ abstract class AbstractType
'locale' => $attribute->value_per_locale ? $data['locale'] : null,
]);
if (! $attributeValue) {
if (!$attributeValue) {
$this->attributeValueRepository->create([
'product_id' => $product->id,
'attribute_id' => $attribute->id,
@ -218,8 +221,8 @@ abstract class AbstractType
]);
} else {
$this->attributeValueRepository->update([
ProductAttributeValue::$attributeTypeFields[$attribute->type] => $data[$attribute->code]
], $attributeValue->id
ProductAttributeValue::$attributeTypeFields[$attribute->type] => $data[$attribute->code],
], $attributeValue->id
);
if ($attribute->type == 'image' || $attribute->type == 'file') {
@ -231,7 +234,7 @@ abstract class AbstractType
$route = request()->route() ? request()->route()->getName() : "";
if ($route != 'admin.catalog.products.massupdate') {
if (! isset($data['categories'])) {
if (!isset($data['categories'])) {
$data['categories'] = [];
}
@ -247,7 +250,8 @@ abstract class AbstractType
$this->productImageRepository->uploadImages($data, $product);
app('Webkul\Product\Repositories\ProductCustomerGroupPriceRepository')->saveCustomerGroupPrices($data, $product);
app('Webkul\Product\Repositories\ProductCustomerGroupPriceRepository')->saveCustomerGroupPrices($data,
$product);
}
return $product;
@ -256,7 +260,8 @@ abstract class AbstractType
/**
* Specify type instance product
*
* @param \Webkul\Product\Contracts\Product $product
* @param \Webkul\Product\Contracts\Product $product
*
* @return \Webkul\Product\Type\AbstractType
*/
public function setProduct($product)
@ -293,7 +298,7 @@ abstract class AbstractType
*/
public function isSaleable()
{
if (! $this->product->status) {
if (!$this->product->status) {
return false;
}
@ -341,7 +346,8 @@ abstract class AbstractType
}
/**
* @param int $qty
* @param int $qty
*
* @return bool
*/
public function haveSufficientQuantity($qty)
@ -360,7 +366,8 @@ abstract class AbstractType
}
/**
* @param \Webkul\Checkout\Contracts\CartItem $cartItem
* @param \Webkul\Checkout\Contracts\CartItem $cartItem
*
* @return bool
*/
public function isItemHaveQuantity($cartItem)
@ -376,9 +383,9 @@ abstract class AbstractType
$total = 0;
$channelInventorySourceIds = core()->getCurrentChannel()
->inventory_sources()
->where('status', 1)
->pluck('id');
->inventory_sources()
->where('status', 1)
->pluck('id');
foreach ($this->product->inventories as $inventory) {
if (is_numeric($index = $channelInventorySourceIds->search($inventory->inventory_source_id))) {
@ -387,8 +394,8 @@ abstract class AbstractType
}
$orderedInventory = $this->product->ordered_inventories()
->where('channel_id', core()->getCurrentChannel()->id)
->first();
->where('channel_id', core()->getCurrentChannel()->id)
->first();
if ($orderedInventory) {
$total -= $orderedInventory->qty;
@ -400,7 +407,8 @@ abstract class AbstractType
/**
* Return true if item can be moved to cart from wishlist
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @param \Webkul\Checkout\Contracts\CartItem $item
*
* @return bool
*/
public function canBeMovedFromWishlistToCart($item)
@ -411,18 +419,21 @@ abstract class AbstractType
/**
* Retrieve product attributes
*
* @param \Webkul\Attribute\Contracts\Group $group
* @param bool $skipSuperAttribute
* @param \Webkul\Attribute\Contracts\Group $group
* @param bool $skipSuperAttribute
*
* @return \Illuminate\Support\Collection
*/
public function getEditableAttributes($group = null, $skipSuperAttribute = true)
{
if ($skipSuperAttribute) {
$this->skipAttributes = array_merge($this->product->super_attributes->pluck('code')->toArray(), $this->skipAttributes);
$this->skipAttributes = array_merge($this->product->super_attributes->pluck('code')->toArray(),
$this->skipAttributes);
}
if (! $group) {
return $this->product->attribute_family->custom_attributes()->whereNotIn('attributes.code', $this->skipAttributes)->get();
if (!$group) {
return $this->product->attribute_family->custom_attributes()->whereNotIn('attributes.code',
$this->skipAttributes)->get();
}
return $group->custom_attributes()->whereNotIn('code', $this->skipAttributes)->get();
@ -451,7 +462,8 @@ abstract class AbstractType
/**
* Get product minimal price
*
* @param int $qty
* @param int $qty
*
* @return float
*/
public function getMinimalPrice($qty = null)
@ -476,7 +488,8 @@ abstract class AbstractType
/**
* Get product minimal price
*
* @param int $qty
* @param int $qty
*
* @return float
*/
public function getFinalPrice($qty = null)
@ -487,7 +500,8 @@ abstract class AbstractType
/**
* Returns the product's minimal price
*
* @param int $qty
* @param int $qty
*
* @return float
*/
public function getSpecialPrice($qty = null)
@ -496,7 +510,8 @@ abstract class AbstractType
}
/**
* @param int $qty
* @param int $qty
*
* @return bool
*/
public function haveSpecialPrice($qty = null)
@ -505,8 +520,8 @@ abstract class AbstractType
$rulePrice = app('Webkul\CatalogRule\Helpers\CatalogRuleProductPrice')->getRulePrice($this->product);
if ((is_null($this->product->special_price) || ! (float) $this->product->special_price)
&& ! $rulePrice
if ((is_null($this->product->special_price) || !(float)$this->product->special_price)
&& !$rulePrice
&& $customerGroupPrice == $this->product->price
) {
return false;
@ -514,7 +529,7 @@ abstract class AbstractType
$haveSpecialPrice = false;
if (! (float) $this->product->special_price) {
if (!(float)$this->product->special_price) {
if ($rulePrice && $rulePrice->price < $this->product->price) {
$this->product->special_price = $rulePrice->price;
@ -526,7 +541,8 @@ abstract class AbstractType
$haveSpecialPrice = true;
} else {
if (core()->isChannelDateInInterval($this->product->special_price_from, $this->product->special_price_to)) {
if (core()->isChannelDateInInterval($this->product->special_price_from,
$this->product->special_price_to)) {
$haveSpecialPrice = true;
} elseif ($rulePrice) {
$this->product->special_price = $rulePrice->price;
@ -570,11 +586,11 @@ abstract class AbstractType
$customerGroupPrices = $product->customer_group_prices()->where(function ($query) use ($customerGroupId) {
$query->where('customer_group_id', $customerGroupId)
->orWhereNull('customer_group_id');
}
->orWhereNull('customer_group_id');
}
)->get();
if (! $customerGroupPrices->count()) {
if (!$customerGroupPrices->count()) {
return $product->price;
}
@ -635,7 +651,7 @@ abstract class AbstractType
'final_price' => [
'price' => core()->convertPrice($this->getMinimalPrice()),
'formated_price' => core()->currency($this->getMinimalPrice()),
]
],
];
}
@ -660,7 +676,8 @@ abstract class AbstractType
/**
* Add product. Returns error message if can't prepare product.
*
* @param array $data
* @param array $data
*
* @return array
*/
public function prepareForCart($data)
@ -669,7 +686,7 @@ abstract class AbstractType
$data = $this->getQtyRequest($data);
if (! $this->haveSufficientQuantity($data['quantity'])) {
if (!$this->haveSufficientQuantity($data['quantity'])) {
return trans('shop::app.checkout.cart.quantity.inventory_warning');
}
@ -690,7 +707,7 @@ abstract class AbstractType
'base_total_weight' => ($this->product->weight ?? 0) * $data['quantity'],
'type' => $this->product->type,
'additional' => $this->getAdditionalOptions($data),
]
],
];
return $products;
@ -699,7 +716,8 @@ abstract class AbstractType
/**
* Get request quantity
*
* @param array $data
* @param array $data
*
* @return array
*/
public function getQtyRequest($data)
@ -713,8 +731,9 @@ abstract class AbstractType
/**
*
* @param array $options1
* @param array $options2
* @param array $options1
* @param array $options2
*
* @return bool
*/
public function compareOptions($options1, $options2)
@ -728,9 +747,9 @@ abstract class AbstractType
} else {
return false;
}
} elseif (isset($options1['parent_id']) && ! isset($options2['parent_id'])) {
} elseif (isset($options1['parent_id']) && !isset($options2['parent_id'])) {
return false;
} elseif (isset($options2['parent_id']) && ! isset($options1['parent_id'])) {
} elseif (isset($options2['parent_id']) && !isset($options1['parent_id'])) {
return false;
}
}
@ -741,7 +760,8 @@ abstract class AbstractType
/**
* Returns additional information for items
*
* @param array $data
* @param array $data
*
* @return array
*/
public function getAdditionalOptions($data)
@ -752,7 +772,8 @@ abstract class AbstractType
/**
* Get actual ordered item
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @param \Webkul\Checkout\Contracts\CartItem $item
*
* @return \Webkul\Checkout\Contracts\CartItem|\Webkul\Sales\Contracts\OrderItem|\Webkul\Sales\Contracts\InvoiceItem|\Webkul\Sales\Contracts\ShipmentItem|\Webkul\Customer\Contracts\Wishlist
*/
public function getOrderedItem($item)
@ -763,7 +784,8 @@ abstract class AbstractType
/**
* Get product base image
*
* @param \Webkul\Customer\Contracts\CartItem|\Webkul\Checkout\Contracts\CartItem $item
* @param \Webkul\Customer\Contracts\CartItem|\Webkul\Checkout\Contracts\CartItem $item
*
* @return array
*/
public function getBaseImage($item)
@ -772,17 +794,26 @@ abstract class AbstractType
}
/**
* Validate cart item product price
* Validate cart item product price and other things
*
* @param \Webkul\Customer\Contracts\CartItem $item
* @return void
* @param \Webkul\Checkout\Models\CartItem $item
*
* @return \Webkul\Product\Datatypes\CartItemValidationResult
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if ($this->isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -792,6 +823,9 @@ abstract class AbstractType
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
//get product options
@ -799,4 +833,37 @@ abstract class AbstractType
{
return $this->productOptions;
}
/**
* Returns true, if cart item is inactive
*
* @param \Webkul\Checkout\Contracts\CartItem $item
*
* @return bool
*/
public function isCartItemInactive(\Webkul\Checkout\Contracts\CartItem $item): bool
{
if ($item->product->status === 0) {
return true;
}
switch ($item->product->type) {
case 'bundle':
foreach ($item->children as $child) {
if ($child->product->status === 0) {
return true;
}
}
break;
case 'configurable':
if ($item->child && $item->child->product->status === 0) {
return true;
}
break;
}
return false;
}
}

View File

@ -3,6 +3,7 @@
namespace Webkul\Product\Type;
use Webkul\Attribute\Repositories\AttributeRepository;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductAttributeValueRepository;
use Webkul\Product\Repositories\ProductInventoryRepository;
@ -11,6 +12,7 @@ use Webkul\Product\Repositories\ProductBundleOptionRepository;
use Webkul\Product\Repositories\ProductBundleOptionProductRepository;
use Webkul\Product\Helpers\ProductImage;
use Webkul\Product\Helpers\BundleOption;
use Webkul\Checkout\Models\CartItem;
class Bundle extends AbstractType
{
@ -278,7 +280,7 @@ class Bundle extends AbstractType
if (! $bundleOptionProduct->product->getTypeInstance()->isSaleable()) {
continue;
}
if (in_array($option->type, ['multiselect', 'checkbox'])) {
if (! isset($optionPrices[$option->id][0])) {
$optionPrices[$option->id][0] = 0;
@ -315,7 +317,7 @@ class Bundle extends AbstractType
if (! $bundleOptionProduct->product->getTypeInstance()->isSaleable()) {
continue;
}
if (in_array($option->type, ['multiselect', 'checkbox'])) {
if (! isset($optionPrices[$option->id][0])) {
$optionPrices[$option->id][0] = 0;
@ -634,15 +636,23 @@ class Bundle extends AbstractType
}
/**
* Validate cart item product price
* Validate cart item product price and other things
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return void
* @param \Webkul\Checkout\Models\CartItem $item
*
* @return \Webkul\Product\Datatypes\CartItemValidationResult
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
$price = 0;
if (parent::isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
foreach ($item->children as $childItem) {
$childItem->product->getTypeInstance()->validateCartItem($childItem);
@ -650,7 +660,7 @@ class Bundle extends AbstractType
}
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -662,6 +672,9 @@ class Bundle extends AbstractType
$item->additional = $this->getAdditionalOptions($item->additional);
$item->save();
$result->cartIsDirty();
return $result;
}
/**
@ -674,4 +687,5 @@ class Bundle extends AbstractType
return $options;
}
}

View File

@ -3,9 +3,11 @@
namespace Webkul\Product\Type;
use Webkul\Customer\Contracts\CartItem;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Product\Models\ProductFlat;
use Illuminate\Support\Str;
use Webkul\Checkout\Models\CartItem;
class Configurable extends AbstractType
{
@ -539,18 +541,28 @@ class Configurable extends AbstractType
/**
* Validate cart item product price
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @param \Webkul\Product\Type\CartItem $item
*
* @return \Webkul\Product\Datatypes\CartItemValidationResult
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
if (! $item || ! $item->child) {
return;
$result = new CartItemValidationResult();
if ($this->isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
// if (! $item || ! $item->child) {
// return;
// }
$price = $item->child->product->getTypeInstance()->getFinalPrice($item->quantity);
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -560,6 +572,9 @@ class Configurable extends AbstractType
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
/**

View File

@ -3,6 +3,7 @@
namespace Webkul\Product\Type;
use Webkul\Attribute\Repositories\AttributeRepository;
use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductAttributeValueRepository;
use Webkul\Product\Repositories\ProductInventoryRepository;
@ -230,11 +231,20 @@ class Downloadable extends AbstractType
/**
* Validate cart item product price
*
* @param \Webkul\Checkout\Contracts\CartItem $item
* @return float
* @param \Webkul\Checkout\Models\CartItem $item
*
* @return \Webkul\Product\Datatypes\CartItemValidationResult
*/
public function validateCartItem($item)
public function validateCartItem(CartItem $item): CartItemValidationResult
{
$result = new CartItemValidationResult();
if (parent::isCartItemInactive($item)) {
$result->itemIsInactive();
return $result;
}
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
foreach ($item->product->downloadable_links as $link) {
@ -246,7 +256,7 @@ class Downloadable extends AbstractType
}
if ($price == $item->base_price) {
return;
return $result;
}
$item->base_price = $price;
@ -256,5 +266,8 @@ class Downloadable extends AbstractType
$item->total = core()->convertPrice($price * $item->quantity);
$item->save();
$result->cartIsDirty();
return $result;
}
}

View File

@ -464,8 +464,8 @@ return [
'success' => 'تم بنجاح إضافة العنصر إلى العربة',
'success-remove' => 'تم إزالة العنصر بنجاح من العربة',
'error-add' => 'لا يمكن إضافة العنصر إلى العربة ، رجاء حاول مرة أخرى ',
'inactive' => 'An item is inactive and was removed from cart.',
'inactive-add' => 'Inactive item cannot be added to cart.',
'inactive' => 'An item is inactive and was removed from cart',
'inactive-add' => 'Inactive item cannot be added to cart',
],
'quantity-error' => 'الكمية المطلوبة غير متوفرة',
'cart-subtotal' => 'المجموع الفرعي للمشتريات',

View File

@ -431,8 +431,8 @@ return [
'success' => 'El artículp se añadió a la cesta',
'success-remove' => 'El artículo se eliminó de la cesta',
'error-add' => 'El artículo no se puede añadir a la cesta, inténtelo más tarde',
'inactive' => 'An item is inactive and was removed from cart.',
'inactive-add' => 'Inactive item cannot be added to cart.',
'inactive' => 'An item is inactive and was removed from cart',
'inactive-add' => 'Inactive item cannot be added to cart',
],
'quantity-error' => 'La cantidad solicitada no está disponible',
'cart-subtotal' => 'Total parcial',

View File

@ -463,8 +463,8 @@ return [
'success' => 'مورد با موفقیت به سبد خرید اضافه شد',
'success-remove' => 'مورد با موفقیت از سبد خرید حذف شد',
'error-add' => 'لطفاً موردی را به سبد خرید اضافه نکرد ، لطفا بعداً دوباره امتحان کنید',
'inactive' => 'An item is inactive and was removed from cart.',
'inactive-add' => 'Inactive item cannot be added to cart.',
'inactive' => 'An item is inactive and was removed from cart',
'inactive-add' => 'Inactive item cannot be added to cart',
],
'quantity-error' => 'مقدار درخواستی در دسترس نیست',

View File

@ -425,8 +425,8 @@ return [
'success' => 'アイテムがカートに追加されました。',
'success-remove' => 'アイテムがカートから削除されました。',
'error-add' => 'アイテムをカートに追加できません。しばらくしてから再度お試し下さい。',
'inactive' => 'An item is inactive and was removed from cart.',
'inactive-add' => 'Inactive item cannot be added to cart.',
'inactive' => 'An item is inactive and was removed from cart',
'inactive-add' => 'Inactive item cannot be added to cart',
],
'quantity-error' => 'ご希望の数量の在庫が現在ございません。',
'cart-subtotal' => '小計',

View File

@ -453,8 +453,8 @@ return [
'success' => 'Item foi adicionado com sucesso ao carrinho',
'success-remove' => 'Item foi removido com sucesso do carrinho',
'error-add' => 'Item não pode ser adicionado ao carrinho, por favor, tente novamente mais tarde',
'inactive' => 'An item is inactive and was removed from cart.',
'inactive-add' => 'Inactive item cannot be added to cart.',
'inactive' => 'An item is inactive and was removed from cart',
'inactive-add' => 'Inactive item cannot be added to cart',
],
'quantity-error' => 'Quantidade solicitada não está disponível',
'cart-subtotal' => 'Subtotal do carrinho',

View File

@ -75,6 +75,8 @@ class CartCest
$I->assertFalse(cart()->hasError());
$I->comment('sP2 is inactive');
cart()->validateItems();
$I->assertEquals(3, count(cart()->getCart()->items));
$I->comment('add dP2 to cart');
@ -106,6 +108,7 @@ class CartCest
'links' => $this->downloadableProduct1->downloadable_links->pluck('id')->all(),
]);
cart()->validateItems();
$I->assertEquals(4, count(cart()->getCart()->items));
$I->comment('deactivate vP2');
@ -125,6 +128,8 @@ class CartCest
$cartItemId => 5
],
]);
// now lets check without validating cart before
$I->assertEquals(3, count(cart()->getCart()->items));
$I->assertEquals(5, cart()->getCart()->items()->find($cartItemId)->quantity);