Skip to content

Commit

Permalink
[shopsys] out of stock products behavior (#3587)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitek-rostislav authored Dec 2, 2024
2 parents 2deeb93 + 38d7358 commit 905d280
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 69 deletions.
35 changes: 0 additions & 35 deletions src/Model/Cart/CartWatcherFacade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Shopsys\FrontendApiBundle\Model\Cart;

use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Shopsys\FrameworkBundle\Component\Domain\Domain;
use Shopsys\FrameworkBundle\Model\Cart\Cart;
Expand Down Expand Up @@ -51,7 +50,6 @@ public function getCheckedCartWithModifications(Cart $cart): CartWithModificatio

$this->checkRemovedProductsItems($cart);
$this->checkNotListableItems($cart);
$this->checkUnavailableStockQuantityItems($cart);
$this->checkModifiedPrices($cart);
$this->checkPromoCodeValidity($cart);

Expand Down Expand Up @@ -102,39 +100,6 @@ protected function checkNotListableItems(Cart $cart): void
}
}

/**
* @param \Shopsys\FrameworkBundle\Model\Cart\Cart $cart
*/
protected function checkUnavailableStockQuantityItems(Cart $cart): void
{
foreach ($cart->getItems() as $cartItem) {
$product = $cartItem->getProduct();

if ($product === null) {
continue;
}

$maximumOrderQuantity = $this->productAvailabilityFacade->getGroupedStockQuantityByProductAndDomainId($product, $this->domain->getId());

if ($maximumOrderQuantity === 0) {
$cart->removeItemById($cartItem->getId());
$this->cartWithModificationsResult->addNoLongerAvailableCartItemDueToQuantity($cartItem);

continue;
}

if ($cartItem->getQuantity() <= $maximumOrderQuantity) {
continue;
}

$cartItem->changeQuantity($maximumOrderQuantity);
$cartItem->changeAddedAt(new DateTime());
$this->em->persist($cartItem);

$this->cartWithModificationsResult->addCartItemWithChangedQuantity($cartItem);
}
}

/**
* @param \Shopsys\FrameworkBundle\Model\Cart\Cart $cart
*/
Expand Down
22 changes: 1 addition & 21 deletions src/Model/Cart/CartWithModificationsResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class CartWithModificationsResult
protected array $itemModifications = [
'noLongerListableCartItems' => [],
'cartItemsWithModifiedPrice' => [],
'cartItemsWithChangedQuantity' => [],
'noLongerAvailableCartItemsDueToQuantity' => [],
];

/**
Expand Down Expand Up @@ -132,22 +130,6 @@ public function addCartItemWithModifiedPrice(CartItem $cartItem): void
$this->itemModifications['cartItemsWithModifiedPrice'][] = $cartItem;
}

/**
* @param \Shopsys\FrameworkBundle\Model\Cart\Item\CartItem $cartItem
*/
public function addCartItemWithChangedQuantity(CartItem $cartItem): void
{
$this->itemModifications['cartItemsWithChangedQuantity'][] = $cartItem;
}

/**
* @param \Shopsys\FrameworkBundle\Model\Cart\Item\CartItem $cartItem
*/
public function addNoLongerAvailableCartItemDueToQuantity(CartItem $cartItem): void
{
$this->itemModifications['noLongerAvailableCartItemsDueToQuantity'][] = $cartItem;
}

public function setCartHasRemovedProducts(): void
{
$this->cartModifications['someProductWasRemovedFromEshop'] = true;
Expand Down Expand Up @@ -390,9 +372,7 @@ protected function isPromoCodeInCartValid(): bool
protected function isSomeCartItemModified(): bool
{
return count($this->itemModifications['noLongerListableCartItems']) > 0
|| count($this->itemModifications['cartItemsWithModifiedPrice']) > 0
|| count($this->itemModifications['cartItemsWithChangedQuantity']) > 0
|| count($this->itemModifications['noLongerAvailableCartItemsDueToQuantity']) > 0;
|| count($this->itemModifications['cartItemsWithModifiedPrice']) > 0;
}

/**
Expand Down
9 changes: 1 addition & 8 deletions src/Model/Mutation/Cart/CartMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,14 @@ public function addOrderItemsToCartMutation(
}

$notAddedProducts = [];
$addProductResults = [];

foreach ($order->getProductItems() as $orderItem) {
if ($orderItem->getProduct() === null) {
continue;
}

try {
$addProductResults[] = $this->cartApiFacade->addProductByUuidToCart($orderItem->getProduct()->getUuid(), $orderItem->getQuantity(), false, $cart);
$this->cartApiFacade->addProductByUuidToCart($orderItem->getProduct()->getUuid(), $orderItem->getQuantity(), false, $cart);
} catch (InvalidCartItemUserError) {
$notAddedProducts[] = $orderItem->getProduct();
}
Expand All @@ -134,12 +133,6 @@ public function addOrderItemsToCartMutation(
$cartWithModificationsResult = $this->cartWatcherFacade->getCheckedCartWithModifications($cart);
$cartWithModificationsResult->addProductsNotAddedByMultipleAddition($notAddedProducts);

foreach ($addProductResults as $addProductResult) {
if ($addProductResult->getNotOnStockQuantity() > 0) {
$cartWithModificationsResult->addCartItemWithChangedQuantity($addProductResult->getCartItem());
}
}

return $cartWithModificationsResult;
}
}
51 changes: 51 additions & 0 deletions src/Model/Resolver/Products/DataMapper/ProductArrayFieldMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,55 @@ public function getProductType(array $data): string
{
return $data['product_type'];
}

/**
* @param array $data
* @return string|null
*/
public function getNamePrefix(array $data): ?string
{
return $data['name_prefix'];
}

/**
* @param array $data
* @return string|null
*/
public function getNameSuffix(array $data): ?string
{
return $data['name_suffix'];
}

/**
* @param array $data
* @return string
*/
public function getFullname(array $data): string
{
return trim(
$data['name_prefix']
. ' '
. $data['name']
. ' '
. $data['name_suffix'],
);
}

/**
* @param array $data
* @return array
*/
public function getStoreAvailabilities(array $data): array
{
return $data['store_availabilities_information'];
}

/**
* @param array $data
* @return int|null
*/
public function getAvailableStoresCount(array $data): ?int
{
return $data['available_stores_count'];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,77 @@ public function getProductType(Product $product): string
{
return $product->getProductType();
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return string|null
*/
public function getNameSuffix(Product $product): ?string
{
return $product->getNameSuffix($this->domain->getLocale());
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return string|null
*/
public function getNamePrefix(Product $product): ?string
{
return $product->getNamePrefix($this->domain->getLocale());
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return string
*/
public function getFullName(Product $product): string
{
return $product->getFullName($this->domain->getLocale());
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return int|null
*/
public function getStockQuantity(Product $product): ?int
{
return $this->productAvailabilityFacade->getGroupedStockQuantityByProductAndDomainId($product, $this->domain->getId());
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return array
*/
public function getStoreAvailabilities(Product $product): array
{
$storeAvailabilitiesInformation = $this->productAvailabilityFacade->getProductStoresAvailabilitiesInformationByDomainIdIndexedByStoreId(
$product,
$this->domain->getId(),
);

$result = [];

foreach ($storeAvailabilitiesInformation as $storeAvailabilityInformation) {
$result[] = [
'store_name' => $storeAvailabilityInformation->getStoreName(),
'store_id' => $storeAvailabilityInformation->getStoreId(),
'availability_information' => $storeAvailabilityInformation->getAvailabilityInformation(),
'availability_status' => $storeAvailabilityInformation->getAvailabilityStatus(),
];
}

return $result;
}

/**
* @param \Shopsys\FrameworkBundle\Model\Product\Product $product
* @return int|null
*/
public function getAvailableStoresCount(Product $product): ?int
{
return $this->productAvailabilityFacade->getAvailableStoresCount(
$product,
$this->domain->getId(),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
AvailabilityStatusEnumDecorator:
type: enum
decorator: true
config:
description: "Product Availability statuses"
values:
InStock:
value: '@=constant("Shopsys\\FrameworkBundle\\Model\\Product\\Availability\\AvailabilityStatusEnum::IN_STOCK")'
description: "Product availability status in stock"
OutOfStock:
value: '@=constant("Shopsys\\FrameworkBundle\\Model\\Product\\Availability\\AvailabilityStatusEnum::OUT_OF_STOCK")'
description: "Product availability status out of stock"
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,3 @@ CartItemModificationsResultDecorator:
type: "[CartItem!]!"
cartItemsWithModifiedPrice:
type: "[CartItem!]!"
cartItemsWithChangedQuantity:
type: "[CartItem!]!"
noLongerAvailableCartItemsDueToQuantity:
type: "[CartItem!]!"
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ AvailabilityDecorator:
description: "Represents an availability"
fields:
name:
type: "String"
type: "String!"
description: "Localized availability name (domain dependent)"
status:
type: "AvailabilityStatusEnum!"
description: "Availability status in a format suitable for usage in the code"
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ ProductDecorator:
name:
type: "String"
description: "Localized product name (domain dependent)"
namePrefix:
type: "String"
description: "Name prefix"
nameSuffix:
type: "String"
description: "Name suffix"
fullName:
type: "String!"
description: "The full name of the product, which consists of a prefix, name, and a suffix"
shortDescription:
type: "String"
description: "Localized product short description (domain dependent)"
Expand Down Expand Up @@ -78,3 +87,9 @@ ProductDecorator:
type: "Boolean!"
productType:
type: "ProductTypeEnum!"
availableStoresCount:
type: "Int"
description: "Number of the stores where the product is available (null for main variants)"
storeAvailabilities:
type: "[StoreAvailability!]!"
description: "List of availabilities in individual stores (empty for main variants)"
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
StoreAvailabilityDecorator:
type: object
decorator: true
config:
description: "Represents an availability in an individual store"
fields:
availabilityInformation:
type: "String!"
description: "Detailed information about availability"
availabilityStatus:
type: "AvailabilityStatusEnum!"
description: "Availability status in a format suitable for usage in the code"
store:
type: "Store"
description: "Store"

0 comments on commit 905d280

Please sign in to comment.