entityManager = $entityManager; $this->orderShopStore = $orderShopStore; $this->orderShopSolver = $orderShopSolver; $this->orderStatusStore = $orderStatusStore; $this->orderProductStore = $orderProductStore; $this->productFamilyStore = $productFamilyStore; $this->orderProductBuilder = $orderProductBuilder; $this->documentBuilder = $documentBuilder; $this->priceSolver = $priceSolver; $this->eventDispatcher = $eventDispatcher; $this->flashBag = $flashBag; $this->openingResolver = $openingResolver; $this->productSolver = $productSolver; $this->orderShopResolver = $orderShopResolver; $this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver; $this->distributionBuilder = $distributionBuilder; $this->merchantResolver = $merchantResolver; $this->creditHistoryBuilder = $creditHistoryBuilder; } public function create( SectionInterface $section, UserInterface $user = null, VisitorInterface $visitor = null ): OrderShopInterface { $orderShopFactory = new OrderShopFactory(); $orderShop = $orderShopFactory->create($section, $user, $visitor); $this->setOrderStatus($orderShop, OrderStatusModel::ALIAS_CART); $this->entityManager->create($orderShop); $this->entityManager->flush(); return $orderShop; } public function createIfNotExist( SectionInterface $section, UserInterface $user = null, VisitorInterface $visitor = null ): OrderShopInterface { $this->orderShopStore->setSection($section); $cartUser = $this->orderShopStore->getOneCartCurrent($user); $cartVisitor = $this->orderShopStore->getOneCartCurrent(null, $visitor); if ($cartUser && $cartVisitor && $cartUser->getId() != $cartVisitor->getId()) { $cart = $this->merge($cartUser, $cartVisitor); } else { $cart = $cartUser ?: $cartVisitor; } if (!$cart) { $cart = $this->create($section, $user, $visitor); } // @TODO : obligé de faire ça sinon le panier ne se met pas à jour quand on ajoute des produits. Pourquoi ? $this->entityManager->refresh($cart); return $cart; } public function setOrderStatus( OrderShopInterface $orderShop, string $alias, bool $forceByAdmin = false ): OrderShopInterface { $orderStatus = $this->orderStatusStore->getOneByAlias($alias); if ($orderStatus) { if ($orderShop->getOrderStatus() === null || $orderShop->getOrderStatus()->getNextStatusAllowed()->contains($orderStatus)) { $this->applyChangeOrderStatus($orderShop, $orderStatus, $forceByAdmin); } } else { throw new \ErrorException('La statut demandé n\'existe pas.'); } return $orderShop; } public function applyChangeOrderStatus( OrderShopInterface $orderShop, OrderStatusInterface $orderStatus, bool $forceByAdmin = false ): void { $this->eventDispatcher->dispatch( new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin), OrderShopChangeStatusEvent::PRE_CHANGE_STATUS ); $orderShop->setOrderStatusProtected($orderStatus); $orderStatusHistoryFactory = new OrderStatusHistoryFactory(); $orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus); $orderShop->addOrderStatusHistory($orderStatusHistory); $this->eventDispatcher->dispatch( new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin), OrderShopChangeStatusEvent::POST_CHANGE_STATUS ); } public function addOrderProduct( OrderShopInterface $orderShop, OrderProductInterface $orderProductAdd, bool $persist = true ): bool { $return = false; if ($this->orderShopSolver->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) { if ($orderProductAdd->getQuantityOrder() > 0) { $updated = false; $this->orderProductBuilder->init($orderProductAdd); $productFamily = $this->productFamilyStore->getOneBySlug( $orderProductAdd->getProduct()->getProductFamily()->getSlug() ); if ($productFamily) { $reductionCatalog = $productFamily->getReductionCatalog(); if ($reductionCatalog) { $orderProductReductionCatalogFactory = new OrderProductReductionCatalogFactory(); $orderProductReductionCatalog = $orderProductReductionCatalogFactory->create( $reductionCatalog->getTitle(), $reductionCatalog->getValue(), $reductionCatalog->getUnit(), $reductionCatalog->getBehaviorTaxRate() ); $orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog); } } foreach ($orderShop->getOrderProducts() as $orderProduct) { if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId() && $orderProduct->getRedelivery() == $orderProductAdd->getRedelivery() && (string)$this->priceSolver->getPrice($orderProduct) == (string)$this->priceSolver->getPrice($orderProductAdd) && $orderProduct->getOrderProductReductionCatalog() && $orderProductAdd->getOrderProductReductionCatalog() && $this->orderProductReductionCatalogSolver->compare( $orderProduct->getOrderProductReductionCatalog(), $orderProductAdd->getOrderProductReductionCatalog() )) { $orderProduct->setQuantityOrder( $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder() ); if ($persist) { $this->entityManager->update($orderProduct); } $updated = true; $return = true; break; } } if (!$updated) { $orderShop->addOrderProduct($orderProductAdd); if ($persist) { if (isset($orderProductReductionCatalog)) { $this->entityManager->create($orderProductReductionCatalog); } //TODO est-ce un update ou un create ??? $this->entityManager->persist($orderProductAdd); $this->entityManager->update($orderShop); } $return = true; } if ($persist) { $this->entityManager->flush(); } // @TODO : dispatch event cart change //$this->eventCartChange($orderShop); } } else { // @TODO : retourner le message d'erreur et faire le addFlash dans le contrôleur /*$availableQuantity = $orderProductAdd->getProduct()->getAvailableQuantityInherited(); $textError = "Le produit " . $orderProductAdd->getTitleOrderShop( ) . " n'est pas disponible"; if ($availableQuantity !== false && $availableQuantity > 0) { $unit = ''; if ($orderProductAdd->getProduct()->getProductFamily()->getBehaviorCountStock( ) == ProductFamily::BEHAVIOR_COUNT_STOCK_BY_MEASURE) { $unit = $orderProductAdd->getProduct()->getUnitInherited()->getUnitReference()->getUnit(); } $textError .= ' dans cette quantité '; $user = $this->security->getUser(); if ($user && $user->hasRole('ROLE_USER')) { $textError .= '
' . $availableQuantity . $unit . ' disponible(s) dont ' . $this->getQuantityOrderByProduct( $orderShop, $orderProductAdd->getProduct() ) . $unit . ' déjà dans votre panier.'; } } $this->utils->addFlash('error', $textError);*/ } return $return; } public function merge( OrderShopInterface $orderShop1, OrderShopInterface $orderShop2, $persist = true ): OrderShopInterface { if ($orderShop1 && $orderShop2) { foreach ($orderShop2->getOrderProducts() as $orderProduct) { $orderProductAlreadyInCart = $this->orderShopSolver->hasOrderProductAlreadyInCart($orderShop1, $orderProduct); if ($orderProductAlreadyInCart) { if ($orderProduct->getQuantityOrder() > $orderProductAlreadyInCart->getQuantityOrder()) { $orderShop1->removeOrderProduct($orderProductAlreadyInCart); $this->addOrderProduct($orderShop1, $orderProduct); } } else { $this->addOrderProduct($orderShop1, $orderProduct); } if ($persist) { $this->entityManager->delete($orderProduct); } } if ($persist) { $this->entityManager->delete($orderShop2); $this->entityManager->update($orderShop1); $this->entityManager->flush(); } return $orderShop1; } } public function addPayment(OrderShopInterface $orderShop, string $meanPayment, float $amount): OrderShopInterface { $orderPaymentFactory = new OrderPaymentFactory(); $orderPayment = $orderPaymentFactory->create($orderShop, $meanPayment, $amount); $orderShop->addOrderPayment($orderPayment); if($meanPayment == OrderPaymentModel::MEAN_PAYMENT_CREDIT) { $this->creditHistoryBuilder->create(CreditHistoryModel::TYPE_DEBIT, $this->merchantResolver->getUserMerchant(), [ 'orderPayment' => $orderPayment ]); } if ($this->orderShopResolver->isPaid($orderShop)) { $nextStatus = OrderStatusModel::ALIAS_PAID; } else { $nextStatus = OrderStatusModel::ALIAS_PARTIAL_PAYMENT; } if ($orderShop->getOrderStatus()->getAlias() != $nextStatus) { $this->changeOrderStatus($orderShop, $nextStatus); } $this->entityManager->create($orderPayment); $this->entityManager->update($orderShop); $this->entityManager->flush(); return $orderShop; } public function initStatsInfo(OrderShopInterface $orderShop, $flush = true) { $orderShop->setStatTotal($this->priceSolver->getTotal($orderShop)); $orderShop->setStatTotalWithTax($this->priceSolver->getTotalWithTax($orderShop)); $orderShop->setStatTotalOrderProductsWithReductions( $this->priceSolver->getTotalOrderProductsWithReductions($orderShop) ); $orderShop->setStatTotalOrderProductsWithTaxAndReductions( $this->priceSolver->getTotalOrderProductsWithTaxAndReductions($orderShop) ); $orderShop->setStatMarginOrderProductsWithReductions( $this->priceSolver->getMarginOrderProductsWithReductions($orderShop) ); $orderShop->setStatDeliveryPriceWithReduction($this->priceSolver->getDeliveryPriceWithReduction($orderShop)); $orderShop->setStatDeliveryPriceWithTaxAndReduction( $this->priceSolver->getDeliveryPriceWithTaxAndReduction($orderShop) ); $this->entityManager->persist($orderShop); if ($flush) { $this->entityManager->flush(); } } //initCycleNumber public function initDistribution(OrderShopInterface $orderShop): void { $distribution = $this->distributionBuilder->guessDistributionByDeliveryDate( $orderShop->getDeliveryDate(), $orderShop->getSection() ); $orderShop->setDistribution($distribution); } public function createDocumentInvoice(OrderShopInterface $orderShop): DocumentInterface { $documentFactory = new DocumentFactory(); $document = $documentFactory->create($orderShop->getSection(), DocumentModel::TYPE_INVOICE); $this->documentBuilder->initFromOrderShop($document, $orderShop); return $document; } public function addReductionCart( OrderShopInterface $orderShop, ReductionCartInterface $reductionCart ): ?OrderReductionCartInterface { $orderReductionCartFactory = new OrderReductionCartFactory(); $orderReductionCart = $orderReductionCartFactory->create($orderShop, $reductionCart); $orderShop->addOrderReductionCart($orderReductionCart); if ($this->orderShopResolver->isPositiveAmount($orderShop) && $this->orderShopResolver->isPositiveAmountRemainingToBePaid($orderShop)) { $this->entityManager->create($orderReductionCart); $this->entityManager->flush(); return $orderReductionCart; } else { //TODO vérifier ce case ! Avec le null en valeur de retour $orderShop->removeOrderReductionCart($orderReductionCart); return null; } } // createOrderReductionCredit public function addReductionCredit( OrderShopInterface $orderShop, ReductionCreditInterface $reductionCredit ): ?OrderReductionCreditInterface { $orderReductionCreditFactory = new OrderReductionCreditFactory(); $orderReductionCredit = $orderReductionCreditFactory->create($orderShop, $reductionCredit); $orderShop->addOrderReductionCredit($orderReductionCredit); if ($this->isOrderShopPositiveAmount($orderShop) && $this->isOrderShopPositiveAmountRemainingToBePaid($orderShop)) { $this->entityManager->create($orderReductionCredit); $this->entityManager->flush(); return $orderReductionCredit; } else { $orderShop->removeOrderReductionCredit($orderReductionCredit); return null; } } public function deductAvailabilityProduct(OrderShopInterface $orderShop): void { foreach ($orderShop->getOrderProducts() as $orderProduct) { $this->applyDeductAvailabilityProduct($orderShop, $orderProduct); } } public function applyDeductAvailabilityProduct( OrderShopInterface $orderShop, OrderProductInterface $orderProduct ): void { switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) { case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE : //Disponibilité par unité de référence $oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct()); $newAvailability = $oldAvailability - ($orderProduct->getQuantityOrder( ) * ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient())); $productFamily = $orderProduct->getProduct()->getProductFamily(); $productFamily->setAvailableQuantity($newAvailability); $productFamily->setUpdatedBy($orderShop->getUser()); $this->entityManager->update($productFamily); break; case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY : $oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct()); $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder(); $productFamily = $orderProduct->getProduct()->getProductFamily(); $productFamily->setAvailableQuantity($newAvailability); $productFamily->setUpdatedBy($orderShop->getUser()); $this->entityManager->update($productFamily); break; case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT : $oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct()); $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder(); $product = $orderProduct->getProduct(); $product->setAvailableQuantity($newAvailability); $product->setUpdatedBy($orderShop->getUser()); $this->entityManager->update($product); break; } $this->entityManager->flush(); } public function updatePriceByProductFamily(ProductFamilyInterface $productFamily) { // @TODO : faire la vérification isOpenSale depuis la méthode appelante if (!$this->openingResolver->isOpenSale( $productFamily->getSection(), null, OpeningResolver::OPENING_CONTEXT_BACKEND )) { $countOrderProductUpdated = 0; foreach ($productFamily->getProducts() as $product) { $orderProducts = $this->orderProductStore->getInCartsByProduct($product); foreach ($orderProducts as $orderProduct) { $quantityOrder = $orderProduct->getQuantityOrder(); $orderShop = $orderProduct->getOrderShop(); $orderShop->removeOrderProduct($orderProduct); $this->entityManager->delete($orderProduct); $this->entityManager->flush(); $this->entityManager->refresh($orderShop); $orderProductFactory = new OrderProductFactory(); $addOrderProduct = $orderProductFactory->create($product, $quantityOrder); $this->addOrderProduct($orderShop, $addOrderProduct); $countOrderProductUpdated++; } } if ($countOrderProductUpdated) { // @TODO : faire le add flash dans le controller /*$this->utils->addFlash( 'success', 'success.OrderShop.orderProductUpdated', array(), array('%count%' => $countOrderProductUpdated) );*/ $this->entityManager->flush(); } return $countOrderProductUpdated; } } public function setStatsInfo(OrderShopInterface $orderShop, $flush = true) { $orderShop->setStatTotal($this->priceSolver->getTotal($orderShop)); $orderShop->setStatTotalWithTax($this->priceSolver->getTotalWithTax($orderShop)); $orderShop->setStatTotalOrderProductsWithReductions( $this->priceSolver->getTotalOrderProductsWithReductions($orderShop) ); $orderShop->setStatTotalOrderProductsWithTaxAndReductions( $this->priceSolver->getTotalOrderProductsWithTaxAndReductions($orderShop) ); $orderShop->setStatMarginOrderProductsWithReductions( $this->priceSolver->getMarginOrderProductsWithReductions($orderShop) ); $orderShop->setStatDeliveryPriceWithReduction($this->priceSolver->getDeliveryPriceWithReduction($orderShop)); $orderShop->setStatDeliveryPriceWithTaxAndReduction( $this->priceSolver->getDeliveryPriceWithTaxAndReduction($orderShop) ); $this->entityManager->update($orderShop); if ($flush) { $this->entityManager->flush(); } } public function setHasReach(int $reachStep, OrderShopInterface $orderShop) { if ($orderShop->getHasReach() === null || $orderShop->getHasReach() < $reachStep) { $orderShop->setHasReach($reachStep); $this->entityManager->persist($orderShop); $this->entityManager->flush($orderShop); } } public function initComplementaryOrderShop(OrderShopInterface $orderShop, OrderShopInterface $mainOrderShop): void { $orderShop->setMainOrderShop($mainOrderShop); $orderShop->setDeliveryPrice(0); if ($mainOrderShop->getDeliveryAddress()) { $this->initDeliveryAddress($orderShop, $mainOrderShop->getDeliveryAddress()); } $orderShop->setInvoiceAddress($mainOrderShop->getInvoiceAddress()); } // setDeliveryAddress public function initDeliveryAddress(OrderShopInterface $orderShop, AddressInterface $address = null): void { $orderShop->setDeliveryAddress($address); $orderShop->setDeliveryInfos($address ? $address->getDeliveryInfos() : null); } // resetOrderShopInfos public function reset(OrderShopInterface $orderShop) { $this->initDeliveryAddress($orderShop, null); $orderShop->setMainOrderShop(null); $orderShop->setDeliveryPrice(null); $orderShop->setInvoiceAddress(null); $orderShop->setDeclineComplementaryOrderShop(false); } public function getProductsSalesStatistic(SectionInterface $section, $entity, $nbWeek = 2) { $productsSalesStatistic = new ProductsSalesStatistic( $this->entityManager, $entity, $nbWeek, $this->productSolver ); $productsSalesStatistic->init($section, $this->orderShopSolver, $this->openingResolver); $productsSalesStatistic->populateProperties($this->orderShopStore); return $productsSalesStatistic->getAsArray(); } }