function it_recognizes_a_subject_as_eligible_if_nth_order_is_equal_with_configured(CustomerInterface $customer, OrderInterface $subject, OrderRepositoryInterface $ordersRepository) { $subject->getCustomer()->willReturn($customer); $customer->getId()->willReturn(1); $ordersRepository->countByCustomer($customer)->willReturn(9); $this->isEligible($subject, ['nth' => 10])->shouldReturn(true); }
public function cancel() { $expiredUnpaidOrders = $this->orderRepository->findOrdersUnpaidSince(new \DateTime('-' . $this->expirationPeriod)); foreach ($expiredUnpaidOrders as $expiredUnpaidOrder) { $this->cancelOrder($expiredUnpaidOrder); } }
/** * {@inheritdoc} */ public function isEligible(PromotionSubjectInterface $promotionSubject, PromotionInterface $promotion) { if (!$promotion->isCouponBased()) { throw new UnsupportedPromotionException('Only coupon based promotions can be evaluated by this checker.'); } if (!$promotionSubject instanceof OrderInterface) { return false; } $coupon = $promotionSubject->getPromotionCoupon(); if (!$coupon instanceof CouponInterface) { return false; } if ($promotion !== $coupon->getPromotion()) { return false; } $couponUsageLimit = $coupon->getPerCustomerUsageLimit(); if (0 === $couponUsageLimit) { return true; } $customer = $promotionSubject->getCustomer(); if (null === $customer) { return false; } $placedOrdersNumber = $this->orderRepository->countByCustomerAndCoupon($customer, $coupon); // <= because we need to include the cart orders as well return $placedOrdersNumber <= $couponUsageLimit; }
function it_throws_exception_if_no_cart_can_be_provided(ChannelInterface $channel, ChannelContextInterface $channelContext, CustomerContextInterface $customerContext, CustomerInterface $customer, OrderRepositoryInterface $orderRepository) { $channelContext->getChannel()->willReturn($channel); $customerContext->getCustomer()->willReturn($customer); $orderRepository->findLatestCartByChannelAndCustomer($channel, $customer)->willReturn(null); $this->shouldThrow(new CartNotFoundException('Sylius was not able to find the cart for currently logged in user.'))->during('getCart', []); }
function it_throws_runtime_exception_if_cannot_find_last_order_for_given_customer(SharedStorageInterface $sharedStorage, OrderRepositoryInterface $orderRepository, UserInterface $user, CustomerInterface $customer) { $sharedStorage->get('user')->willReturn($user); $user->getCustomer()->willReturn($customer); $orderRepository->findByCustomer($customer)->willReturn([]); $this->shouldThrow(\RuntimeException::class)->during('iTryToPayAgain'); }
function it_returns_true_if_promotion_coupon_has_not_reached_its_per_customer_usage_limit(OrderRepositoryInterface $orderRepository, OrderInterface $promotionSubject, CorePromotionCouponInterface $promotionCoupon, CustomerInterface $customer) { $promotionSubject->getCustomer()->willReturn($customer); $promotionCoupon->getPerCustomerUsageLimit()->willReturn(42); $orderRepository->countByCustomerAndCoupon($customer, $promotionCoupon)->willReturn(41); $this->isEligible($promotionSubject, $promotionCoupon)->shouldReturn(true); }
/** * {@inheritdoc} */ public function release(\DateTime $expiresAt) { $orders = $this->repository->findExpired($expiresAt); foreach ($orders as $order) { $this->factory->get($order, OrderTransitions::GRAPH)->apply(OrderTransitions::SYLIUS_RELEASE, true); } $this->manager->flush(); }
function it_obtains_order_and_customer_statistics_from_the_repositories(OrderRepositoryInterface $orderRepository, CustomerRepositoryInterface $customerRepository) { $expectedStats = new DashboardStatistics(450, 2, 6); $orderRepository->getTotalSales()->willReturn(450); $orderRepository->count()->willReturn(2); $customerRepository->count()->willReturn(6); $this->getStatistics()->shouldBeLike($expectedStats); }
function it_obtains_order_and_customer_statistics_by_given_channel(OrderRepositoryInterface $orderRepository, CustomerRepositoryInterface $customerRepository, ChannelInterface $channel) { $expectedStats = new DashboardStatistics(450, 2, 6); $orderRepository->getTotalSalesForChannel($channel)->willReturn(450); $orderRepository->countByChannel($channel)->willReturn(2); $customerRepository->count()->willReturn(6); $this->getStatisticsForChannel($channel)->shouldBeLike($expectedStats); }
/** * @Transform /^this order made by "([^"]+)"$/ */ public function getOrderByCustomer($email) { $customer = $this->customerRepository->findOneBy(['email' => $email]); Assert::notNull($customer, sprintf('Cannot find customer with email %s.', $email)); $orders = $this->orderRepository->findByCustomer($customer); Assert::notEmpty($orders); return end($orders); }
function it_cancels_unpaid_orders(Factory $stateMachineFactory, OrderInterface $firstOrder, OrderInterface $secondOrder, OrderRepositoryInterface $orderRepository, StateMachineInterface $firstOrderStateMachine, StateMachineInterface $secondOrderStateMachine) { $orderRepository->findOrdersUnpaidSince(Argument::type(\DateTime::class))->willReturn([$firstOrder, $secondOrder]); $stateMachineFactory->get($firstOrder, 'sylius_order')->willReturn($firstOrderStateMachine); $stateMachineFactory->get($secondOrder, 'sylius_order')->willReturn($secondOrderStateMachine); $firstOrderStateMachine->apply(OrderTransitions::TRANSITION_CANCEL)->shouldBeCalled(); $secondOrderStateMachine->apply(OrderTransitions::TRANSITION_CANCEL)->shouldBeCalled(); $this->cancel(); }
/** * {@inheritdoc} */ public function isEligible(PromotionSubjectInterface $subject, array $configuration) { if (!$subject instanceof OrderInterface) { throw new UnsupportedTypeException($subject, 'Sylius\\Component\\Core\\Model\\OrderInterface'); } if (null === ($customer = $subject->getCustomer())) { return false; } return $this->orderRepository->countByCustomerAndPaymentState($customer, PaymentInterface::STATE_COMPLETED) === $configuration['nth'] - 1; }
function it_throws_cart_not_found_exception_and_removes_id_from_session_when_cart_was_not_found(SessionInterface $session, OrderRepositoryInterface $orderRepository, ChannelContextInterface $channelContext, ChannelInterface $channel) { $channelContext->getChannel()->willReturn($channel); $channel->getCode()->willReturn('Poland'); $session->has('session_key_name.Poland')->willReturn(true); $session->get('session_key_name.Poland')->willReturn(12345); $orderRepository->findCartByChannel(12345, $channel)->willReturn(null); $session->remove('session_key_name.Poland')->shouldBeCalled(); $this->shouldThrow(CartNotFoundException::class)->during('getCart'); }
function it_returns_false_if_subject_coupon_is_eligible_to_promotion_and_number_of_usages_is_bigger_than_coupon_usage_limit(OrderRepositoryInterface $orderRepository, OrderInterface $subject, PromotionInterface $promotion, CouponInterface $coupon, CustomerInterface $customer) { $subject->getPromotionCoupon()->willReturn($coupon); $promotion->isCouponBased()->willReturn(true); $subject->getCustomer()->willReturn($customer); $coupon->getPromotion()->willReturn($promotion); $coupon->getPerCustomerUsageLimit()->willReturn(5); $orderRepository->countByCustomerAndCoupon($customer, $coupon)->willReturn(6); $this->isEligible($subject, $promotion)->shouldReturn(false); }
private function isCouponEligible(CouponInterface $coupon, PromotionInterface $promotion, CustomerInterface $customer) { $countPlacedOrders = $this->subjectRepository->countByCustomerAndCoupon($customer, $coupon); // <= because we need to include the cart orders as well if ($countPlacedOrders <= $coupon->getPerCustomerUsageLimit()) { $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_ELIGIBLE, new GenericEvent($promotion)); return true; } return false; }
/** * @param CouponInterface $coupon * @param CustomerInterface|null $customer * * @return bool */ private function isCouponEligibleToLimit(CouponInterface $coupon, CustomerInterface $customer = null) { $couponUsageLimit = $coupon->getPerCustomerUsageLimit(); if (0 === $couponUsageLimit) { return true; } if (null === $customer) { return false; } $placedOrdersNumber = $this->orderRepository->countByCustomerAndCoupon($customer, $coupon); // <= because we need to include the cart orders as well return $placedOrdersNumber <= $couponUsageLimit; }
function it_creates_customers_order(CustomerInterface $customer, ChannelInterface $channel, CurrencyInterface $currency, FactoryInterface $orderFactory, OrderInterface $order, OrderRepositoryInterface $orderRepository, SharedStorageInterface $sharedStorage) { $sharedStorage->get('channel')->willReturn($channel); $sharedStorage->get('currency')->willReturn($currency); $orderFactory->createNew()->willReturn($order); $order->setCustomer($customer)->shouldBeCalled(); $order->setChannel($channel)->shouldBeCalled(); $order->setCurrency($currency)->shouldBeCalled(); $order->setNumber('#00000022')->shouldBeCalled(); $orderRepository->add($order)->shouldBeCalled(); $sharedStorage->set('order', $order)->shouldBeCalled(); $this->theCustomerPlacedAnOrder($customer, '#00000022'); }
/** * {@inheritdoc} */ public function isEligible(PromotionSubjectInterface $subject, array $configuration) { if (!$subject instanceof OrderInterface) { throw new UnsupportedTypeException($subject, OrderInterface::class); } if (!isset($configuration['nth']) || !is_int($configuration['nth'])) { return false; } $customer = $subject->getCustomer(); if (null === $customer) { return false; } return $this->orderRepository->countByCustomerAndPaymentState($customer, PaymentInterface::STATE_COMPLETED) === $configuration['nth'] - 1; }
/** * {@inheritdoc} */ public function purge() { $orders = $this->repository->findExpired($this->expiresAt); foreach ($orders as $order) { // Check if order has any on-hold inventory units. $hasOnHoldInventoryUnits = $order->getInventoryUnits()->exists(function ($key, InventoryUnitInterface $inventoryUnit) { return InventoryUnitInterface::STATE_ONHOLD === $inventoryUnit->getInventoryState(); }); if (!$hasOnHoldInventoryUnits) { $this->purgeOrder($order); } } $this->manager->flush(); }
/** * {@inheritdoc} */ public function getCart() { try { $channel = $this->channelContext->getChannel(); } catch (ChannelNotFoundException $exception) { throw new CartNotFoundException('Sylius was not able to find the cart, as there is no current channel.'); } $customer = $this->customerContext->getCustomer(); if (null === $customer) { throw new CartNotFoundException('Sylius was not able to find the cart, as there is no logged in user.'); } $cart = $this->orderRepository->findLatestCartByChannelAndCustomer($channel, $customer); if (null === $cart) { throw new CartNotFoundException('Sylius was not able to find the cart for currently logged in user.'); } return $cart; }
/** * {@inheritdoc} */ public function getCart() { try { $channel = $this->channelContext->getChannel(); } catch (ChannelNotFoundException $exception) { throw new CartNotFoundException($exception); } if (!$this->session->has(sprintf('%s.%s', $this->sessionKeyName, $channel->getCode()))) { throw new CartNotFoundException('Sylius was not able to find the cart in session'); } $cart = $this->orderRepository->findCartByIdAndChannel($this->session->get(sprintf('%s.%s', $this->sessionKeyName, $channel->getCode())), $channel); if (null === $cart) { $this->session->remove(sprintf('%s.%s', $this->sessionKeyName, $channel->getCode())); throw new CartNotFoundException('Sylius was not able to find the cart in session'); } return $cart; }
/** * {@inheritdoc} */ public function isEligible(PromotionSubjectInterface $subject, array $configuration) { if (!$subject instanceof OrderInterface) { throw new UnsupportedTypeException($subject, OrderInterface::class); } if (!isset($configuration['nth']) || !is_int($configuration['nth'])) { return false; } $customer = $subject->getCustomer(); if (null === $customer) { return false; } //eligible if it is first order of guest and the promotion is on first order if (null === $customer->getId()) { return 1 === $configuration['nth']; } return $this->orderRepository->countByCustomer($customer) === $configuration['nth'] - 1; }
/** * @return OrderInterface * * @throws \RuntimeException */ private function getLastOrder() { $customer = $this->sharedStorage->get('user')->getCustomer(); $orders = $this->orderRepository->findByCustomer($customer); $lastOrder = end($orders); if (false === $lastOrder) { throw new \RuntimeException(sprintf('There is no last order for %s', $customer->getFullName())); } return $lastOrder; }
/** * {@inheritdoc} */ public function isEligible(PromotionSubjectInterface $promotionSubject, PromotionCouponInterface $promotionCoupon) { if (!$promotionSubject instanceof OrderInterface) { return true; } if (!$promotionCoupon instanceof CorePromotionCouponInterface) { return true; } $perCustomerUsageLimit = $promotionCoupon->getPerCustomerUsageLimit(); if ($perCustomerUsageLimit === null) { return true; } $customer = $promotionSubject->getCustomer(); if ($customer === null) { return true; } $placedOrdersNumber = $this->orderRepository->countByCustomerAndCoupon($customer, $promotionCoupon); return $placedOrdersNumber < $perCustomerUsageLimit; }
/** * @Given /^(I) have already placed an order (\d+) times$/ */ public function iHaveAlreadyPlacedOrderNthTimes(UserInterface $user, $numberOfOrders) { $customer = $user->getCustomer(); for ($i = 0; $i < $numberOfOrders; $i++) { $order = $this->createOrder($customer, '#00000' . $i); $order->setPaymentState(PaymentInterface::STATE_COMPLETED); $order->setCompletedAt(new \DateTime()); $this->orderRepository->add($order); } }
function it_dispatches_event_and_returns_false_if_subject_coupon_is_eligible_to_promotion_and_number_of_usages_is_bigger_than_coupon_usage_limit(CouponInterface $coupon, CustomerInterface $customer, EventDispatcherInterface $eventDispatcher, OrderInterface $subject, OrderRepositoryInterface $orderRepository, PromotionInterface $promotion) { $subject->getPromotionCoupon()->willReturn($coupon); $coupon->getPromotion()->willReturn($promotion); $subject->getCustomer()->willReturn($customer); $coupon->getPerCustomerUsageLimit()->willReturn(5); $orderRepository->countByCustomerAndCoupon($customer, $coupon)->willReturn(6); $eventDispatcher->dispatch(SyliusPromotionEvents::COUPON_NOT_ELIGIBLE, Argument::type(GenericEvent::class))->shouldBeCalled(); $this->isEligible($subject, $promotion)->shouldReturn(false); }
/** * @Given the customer :customer placed an order :orderNumber */ public function theCustomerPlacedAnOrder(CustomerInterface $customer, $orderNumber) { /** @var OrderInterface $order */ $order = $this->orderFactory->createNew(); $order->setCustomer($customer); $order->setNumber($orderNumber); $order->setChannel($this->sharedStorage->get('channel')); $order->setCurrency($this->sharedStorage->get('currency')); $this->sharedStorage->set('order', $order); $this->orderRepository->add($order); }
/** * @Given :numberOfCustomers customers have placed :numberOfOrders orders for total of :total mostly :product product * @Given then :numberOfCustomers more customers have placed :numberOfOrders orders for total of :total mostly :product product */ public function customersHavePlacedOrdersForTotalOfMostlyProduct($numberOfCustomers, $numberOfOrders, $total, ProductInterface $product) { $customers = $this->generateCustomers($numberOfCustomers); $sampleProductVariant = $product->getVariants()->first(); $total = $this->getPriceFromString($total); for ($i = 0; $i < $numberOfOrders; $i++) { $order = $this->createOrder($customers[rand(0, $numberOfCustomers - 1)], '#' . uniqid(), $product->getChannels()->first()); $order->setState(OrderInterface::STATE_NEW); $this->applyPaymentTransitionOnOrder($order, PaymentTransitions::TRANSITION_COMPLETE); $price = $i === $numberOfOrders - 1 ? $total : rand(1, $total); $total -= $price; $item = $this->orderItemFactory->createNew(); $item->setVariant($sampleProductVariant); $item->setUnitPrice($price); $this->itemQuantityModifier->modify($item, 1); $order->addItem($item); $this->orderRepository->add($order); } }
/** * @Given :numberOfCustomers customers have placed :numberOfOrders orders for total of :total * @Given then :numberOfCustomers more customers have placed :numberOfOrders orders for total of :total */ public function customersHavePlacedOrdersForTotalOf($numberOfCustomers, $numberOfOrders, $total) { $customers = $this->generateCustomers($numberOfCustomers); $sampleProductVariant = $this->sharedStorage->get('variant'); $total = $this->getPriceFromString($total); for ($i = 0; $i < $numberOfOrders; $i++) { $order = $this->createOrder($customers[rand(0, $numberOfCustomers - 1)], '#' . uniqid()); $order->setPaymentState(PaymentInterface::STATE_COMPLETED); $order->setCompletedAt(new \DateTime()); $price = $i === $numberOfOrders - 1 ? $total : rand(1, $total); $total -= $price; $item = $this->orderItemFactory->createNew(); $item->setVariant($sampleProductVariant); $item->setUnitPrice($price); $this->itemQuantityModifier->modify($item, 1); $order->addItem($item); $this->orderRepository->add($order); } }
/** * @Given :numberOfCustomers customers have placed :numberOfOrders orders for total of :total * @Given then :numberOfCustomers more customers have placed :numberOfOrders orders for total of :total */ public function customersHavePlacedOrdersForTotalOf($numberOfCustomers, $numberOfOrders, $total) { $customers = $this->generateCustomers($numberOfCustomers); $sampleProductVariant = $this->sharedStorage->get('variant'); $total = $this->getPriceFromString($total); for ($i = 0; $i < $numberOfOrders; $i++) { $order = $this->createOrder($customers[rand(0, $numberOfCustomers - 1)], '#' . uniqid()); $order->setState(OrderInterface::STATE_NEW); // Temporary, we should use checkout to place these orders. $this->applyPaymentTransitionOnOrder($order, PaymentTransitions::TRANSITION_COMPLETE); $price = $i === $numberOfOrders - 1 ? $total : rand(1, $total); $total -= $price; $item = $this->orderItemFactory->createNew(); $item->setVariant($sampleProductVariant); $item->setUnitPrice($price); $this->itemQuantityModifier->modify($item, 1); $order->addItem($item); $this->orderRepository->add($order); } }