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;
$this->flashBagTranslator = $flashBagTranslator;
}
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;
}
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();
$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->setSection($orderShop->getSection())->getOneBySlug(
$orderProductAdd->getProduct()->getProductFamily()->getSlug()
);
if ($productFamily) {
$reductionCatalog = $productFamily->getReductionCatalog();
if ($reductionCatalog && $reductionCatalog->getStatus()) {
$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)
&& $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 : update ou create ?
$this->entityManager->persist($orderProductAdd);
$this->entityManager->update($orderShop);
}
$return = true;
}
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);*/
$return = false;
}
return $return;
}
public function merge(
OrderShopInterface $orderShop1,
OrderShopInterface $orderShop2,
$persist = true
): OrderShopInterface {
//TODO essayer de comprendre prk on doit faire un refresh ici ???
$this->entityManager->refresh($orderShop1);
$this->entityManager->refresh($orderShop2);
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()->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);
}
}
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)
{
$debug = '';
foreach ($this->merchantResolver->getCurrent()->getSections() as $section) {
// @TODO : faire la vérification isOpenSale depuis la méthode appelante
if (!$this->openingResolver->isOpenSale($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->flashBagTranslator->add(
'success',
'orderProductUpdated',
'OrderShop',
//array('%count%' => $countOrderProductUpdated)
['%count' => $debug]
);
$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->distributionBuilder, $this->openingResolver);
$productsSalesStatistic->populateProperties($this->orderShopStore);
return $productsSalesStatistic->getAsArray();
}
}