function it_should_not_add_violation_if_stock_is_sufficient(PropertyAccessor $propertyAccessor, InventoryUnitInterface $inventoryUnit, StockableInterface $stockable, AvailabilityCheckerInterface $availabilityChecker) { $propertyAccessor->getValue($inventoryUnit, 'stockable')->willReturn($stockable); $propertyAccessor->getValue($inventoryUnit, 'quantity')->willReturn(1); $availabilityChecker->isStockSufficient($stockable, 1)->willReturn(true); $constraint = new InStock(); $this->validate($inventoryUnit, $constraint); }
/** * @param AddToCartCommandInterface $addCartItemCommand * * {@inheritDoc} */ public function validate($addCartItemCommand, Constraint $constraint) { Assert::isInstanceOf($addCartItemCommand, AddToCartCommandInterface::class); Assert::isInstanceOf($constraint, CartItemAvailability::class); /** @var OrderItemInterface $cartItem */ $cartItem = $addCartItemCommand->getCartItem(); $isStockSufficient = $this->availabilityChecker->isStockSufficient($cartItem->getVariant(), $cartItem->getQuantity() + $this->getExistingCartItemQuantityFromCart($addCartItemCommand->getCart(), $cartItem)); if (!$isStockSufficient) { $this->context->addViolation($constraint->message, ['%itemName%' => $cartItem->getVariant()->getInventoryName()]); } }
/** * {@inheritdoc} */ public function decrease($inventoryUnits) { if (!is_array($inventoryUnits) && !$inventoryUnits instanceof Collection) { throw new \InvalidArgumentException('Inventory units value must be array or instance of "Doctrine\\Common\\Collections\\Collection".'); } $quantity = count($inventoryUnits); if ($quantity < 1) { throw new \InvalidArgumentException('Quantity of units must be greater than 0.'); } if ($inventoryUnits instanceof Collection) { $stockable = $inventoryUnits->first()->getStockable(); } else { $stockable = $inventoryUnits[0]->getStockable(); } if (!$this->availabilityChecker->isStockSufficient($stockable, $quantity)) { throw new InsufficientStockException($stockable, $quantity); } $this->eventDispatcher->dispatch(SyliusStockableEvents::PRE_DECREASE, new GenericEvent($stockable)); $this->backordersHandler->processBackorders($inventoryUnits); $onHand = $stockable->getOnHand(); foreach ($inventoryUnits as $inventoryUnit) { if (InventoryUnitInterface::STATE_SOLD === $inventoryUnit->getInventoryState()) { --$onHand; } } $stockable->setOnHand($onHand); $this->eventDispatcher->dispatch(SyliusStockableEvents::POST_DECREASE, new GenericEvent($stockable)); }
/** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { /** @var InStock $constraint */ Assert::isInstanceOf($constraint, InStock::class); $stockable = $this->accessor->getValue($value, $constraint->stockablePath); if (null === $stockable) { return; } $quantity = $this->accessor->getValue($value, $constraint->quantityPath); if (null === $quantity) { return; } if (!$this->availabilityChecker->isStockSufficient($stockable, $quantity)) { $this->context->addViolation($constraint->message, ['%stockable%' => $stockable->getInventoryName()]); } }
/** * {@inheritdoc} */ public function resolve(CartItemInterface $item, $data) { $id = $this->resolveItemIdentifier($data); $channel = $this->channelContext->getChannel(); if (!($product = $this->productRepository->findOneBy(['id' => $id, 'channels' => $channel]))) { throw new ItemResolvingException('Requested product was not found.'); } if ($this->restrictedZoneChecker->isRestricted($product)) { throw new ItemResolvingException('Selected item is not available in your country.'); } // We use forms to easily set the quantity and pick variant but you can do here whatever is required to create the item. $form = $this->formFactory->create('sylius_cart_item', $item, ['product' => $product]); $form->submit($data); // If our product has no variants, we simply set the master variant of it. if (null === $item->getVariant() && !$product->hasVariants()) { $item->setVariant($product->getMasterVariant()); } if (null === $item->getVariant() && $product->hasVariants()) { throw new ItemResolvingException('Please select variant'); } $variant = $item->getVariant(); // If all is ok with form, quantity and other stuff, simply return the item. if (!$form->isValid() || null === $variant) { throw new ItemResolvingException('Submitted form is invalid.'); } $cart = $this->cartProvider->getCart(); $quantity = $item->getQuantity(); $context = ['quantity' => $quantity]; if (null !== ($customer = $cart->getCustomer())) { $context['groups'] = $customer->getGroups()->toArray(); } $item->setUnitPrice($this->priceCalculator->calculate($variant, $context)); foreach ($cart->getItems() as $cartItem) { if ($cartItem->equals($item)) { $quantity += $cartItem->getQuantity(); break; } } if (!$this->availabilityChecker->isStockSufficient($variant, $quantity)) { throw new ItemResolvingException('Selected item is out of stock.'); } return $item; }
/** * Check whether stock is sufficient for given * stockable and quantity. * * @param StockableInterface $stockable * @param integer $quantity * * @return Boolean */ public function isStockSufficient(StockableInterface $stockable, $quantity) { return $this->checker->isStockSufficient($stockable, $quantity); }
function it_delegates_the_stock_sufficiency_checking_to_the_checker(AvailabilityCheckerInterface $checker, StockableInterface $stockable) { $checker->isStockSufficient($stockable, 3)->shouldBeCalled()->willReturn(false); $this->isStockSufficient($stockable, 3)->shouldReturn(false); }
function it_does_not_add_violation_if_total_quantity_of_cart_items_do_not_exceed_available_quantity(ExecutionContextInterface $executionContext, AvailabilityCheckerInterface $availabilityChecker, AddToCartCommandInterface $addCartItemCommand, OrderInterface $order, OrderItemInterface $orderItem, OrderItemInterface $existingOrderItem, ProductVariantInterface $productVariant) { $addCartItemCommand->getCart()->willReturn($order); $addCartItemCommand->getCartItem()->willReturn($orderItem); $orderItem->getVariant()->willReturn($productVariant); $orderItem->getQuantity()->willReturn(10); $existingOrderItem->equals($orderItem)->willReturn(true); $order->getItems()->willReturn([$existingOrderItem]); $existingOrderItem->getQuantity()->willReturn(10); $availabilityChecker->isStockSufficient($productVariant, 20)->willReturn(true); $executionContext->addViolation(Argument::any(), Argument::any())->shouldNotBeCalled(); $cartItemAvailabilityConstraint = new CartItemAvailability(); $cartItemAvailabilityConstraint->message = 'Insufficient stock'; $this->validate($addCartItemCommand, $cartItemAvailabilityConstraint); }