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', []);
 }
Example #5
0
 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);
 }
Example #7
0
 /**
  * {@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);
 }
Example #10
0
 /**
  * @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();
 }
Example #12
0
 /**
  * {@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');
 }
Example #18
0
 /**
  * {@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;
 }
Example #19
0
 /**
  * {@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;
 }
Example #23
0
 /**
  * @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;
 }
Example #25
0
 /**
  * @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);
 }
Example #27
0
 /**
  * @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);
 }
Example #28
0
 /**
  * @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);
     }
 }
Example #29
0
 /**
  * @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);
     }
 }
Example #30
0
 /**
  * @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);
     }
 }