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();
}
}