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->productSolver = $productSolver; $this->orderShopResolver = $orderShopResolver; $this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver; $this->distributionBuilder = $distributionBuilder; $this->merchantResolver = $merchantResolver; $this->creditHistoryBuilder = $creditHistoryBuilder; $this->orderShopFactory = $orderShopFactory; $this->orderProductSolver = $orderProductSolver; } public function create( SectionInterface $section, UserInterface $user = null, VisitorInterface $visitor = null ): OrderShopInterface { $orderShop = $this->orderShopFactory->create($section, $user, $visitor); $this->setOrderStatus($orderShop, OrderStatus::ALIAS_CART); $this->entityManager->create($orderShop); $this->entityManager->flush(); return $orderShop; } protected array $cacheCartCurrentBySection = []; public function createIfNotExist( SectionInterface $section, UserInterface $user = null, VisitorInterface $visitor = null, bool $cache = false ): OrderShopInterface { $cart = null; // cache $cacheIdCartCurrent = 'cart_current_' . $section->getId(); if ($cache && isset($this->cacheCartCurrentBySection[$cacheIdCartCurrent]) && $this->cacheCartCurrentBySection[$cacheIdCartCurrent]) { return $this->cacheCartCurrentBySection[$cacheIdCartCurrent]; } $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 { if ($cartUser) { $cart = $cartUser; } elseif ($cartVisitor) { if ($user && $cartVisitor && !$cartVisitor->getUser()) { $cartVisitor->setUser($user); $this->entityManager->update($cartVisitor); $this->entityManager->flush(); } $cart = $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); // cache $this->cacheCartCurrentBySection[$cacheIdCartCurrent] = $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(); $origin = $forceByAdmin ? OrderStatusHistoryModel::ORIGIN_ADMIN : OrderStatusHistoryModel::ORIGIN_USER; $orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus, $origin); $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 ): ?array { $orderProductAddedArray = []; $orderProductAdd->setOrderShop($orderShop); if ($this->orderShopSolver->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) { if ($orderProductAdd->getQuantityOrder() > 0) { $orderProductAddedArray[] = $orderProductAdd; $updated = false; $this->orderProductBuilder->init($orderProductAdd); if(is_null($orderProductAdd->getOrderProductReductionCatalog())) { // on hydrate $productFamily avec réduction $productFamily = $this->productFamilyStore->setSection($orderShop->getSection())->getOneBySlug( $orderProductAdd->getProduct()->getProductFamily()->getSlug() ); if($productFamily) { $this->orderProductBuilder->initReductionCatalog($orderShop->getSection(), $orderProductAdd, $productFamily); } } foreach ($orderShop->getOrderProducts() as $orderProduct) { if ($this->orderProductSolver->compare($orderProduct, $orderProductAdd)) { $orderProduct->setQuantityOrder( $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder() ); if ($persist) { $this->entityManager->update($orderProduct); } $updated = true; break; } } if (!$updated) { $orderShop->addOrderProduct($orderProductAdd); if ($persist) { if (isset($orderProductReductionCatalog)) { $this->entityManager->create($orderProductReductionCatalog); } // @TODO : update ou create ? $this->entityManager->persist($orderProductAdd); $this->entityManager->update($orderShop); } } if ($persist) { $this->entityManager->flush(); $this->eventDispatcher->dispatch(new CartChangeEvent($orderShop), CartChangeEvent::POST_UPDATE); } } } 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);*/ } if(count($orderProductAddedArray) == 0) { return null; } return $orderProductAddedArray; } public function merge( OrderShopInterface $orderShop1, OrderShopInterface $orderShop2, $persist = true ): OrderShopInterface { // @TODO : intégrer la gestion des OrderPackProduct dans cette méthode // TODO essayer de comprendre pourquoi on doit faire un refresh ici $this->entityManager->refresh($orderShop1); $this->entityManager->refresh($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, bool $editable = false): OrderShopInterface { $orderPaymentFactory = new OrderPaymentFactory(); $orderPayment = $orderPaymentFactory->create($orderShop, $meanPayment, $amount, $editable); $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 = OrderStatus::ALIAS_PAID; } else { $nextStatus = OrderStatus::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) ); $orderShop->setStatMarginDeliveryWithReductions( $this->priceSolver->getMarginDeliveryWithReductions($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()->getMerchant(), 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->orderShopResolver->isPositiveAmount($orderShop) && $this->orderShopResolver->isPositiveAmountRemainingToBePaid($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->getProduct(), $orderProduct->getQuantityOrder()); } } public function applyDeductAvailabilityProduct( OrderShopInterface $orderShop, ProductInterface $product, float $quantityOrder, float $quantityProduct = null ): void { switch ($product->getProductFamily()->getBehaviorCountStock()) { case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE : //Disponibilité par unité de référence $oldAvailability = $this->productSolver->getAvailableQuantityInherited($product); $newAvailability = $oldAvailability - ($quantityOrder * ($this->productSolver->getQuantityInherited( $product ) / $this->productSolver->getUnitInherited($product)->getCoefficient())); $productFamily = $product->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($product); $newAvailability = $oldAvailability - $quantityOrder; $productFamily = $product->getProductFamily(); $productFamily->setAvailableQuantity($newAvailability); $productFamily->setUpdatedBy($orderShop->getUser()); $this->entityManager->update($productFamily); break; case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT : $oldAvailability = $this->productSolver->getAvailableQuantityInherited($product); $newAvailability = $oldAvailability - $quantityOrder; $product->setAvailableQuantity($newAvailability); $product->setUpdatedBy($orderShop->getUser()); $this->entityManager->update($product); break; } $this->entityManager->flush(); } public function updatePriceByProductFamily(ProductFamilyInterface $productFamily, SectionInterface $section) { $countOrderProductUpdated = 0; foreach ($productFamily->getProducts() as $product) { $orderProducts = $this->orderProductStore->resetContext()->setSection( $section )->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) { $this->entityManager->flush(); } return $countOrderProductUpdated; } //Semble ne jamais être utilisé //TODO : à supprimer si pas d'erreur arpès 1/01/2025 // 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) // ); // $orderShop->setStatMarginDeliveryWithReductions( // $this->priceSolver->getMarginDeliveryWithReductions($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->distributionBuilder); $productsSalesStatistic->populateProperties($this->orderShopStore->resetContext()->setSection($section)); return $productsSalesStatistic->getAsArray(); } public function delete(OrderShopInterface $orderShop) { // delete OrderProduct foreach($orderShop->getOrderProducts() as $orderProduct) { $this->entityManager->delete($orderProduct); } // delete OrderPackProduct foreach($orderShop->getOrderPackProducts() as $orderPackProduct) { $this->entityManager->delete($orderPackProduct); } // delete OrderPayment foreach($orderShop->getOrderPayments() as $orderPayment) { $this->entityManager->delete($orderPayment); } // delete OrderReductionCarts foreach($orderShop->getOrderReductionCarts() as $orderReductionCart) { $this->entityManager->delete($orderReductionCart); } // delete OrderReductionCredits foreach($orderShop->getOrderReductionCredits() as $orderReductionCredit) { $this->entityManager->delete($orderReductionCredit); } // delete OrderStatusHistory foreach($orderShop->getOrderStatusHistories() as $orderStatusHistory) { $this->entityManager->delete($orderStatusHistory); } // delete OrderShop $this->entityManager->delete($orderShop); $this->entityManager->flush(); } }