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;
}
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 {
$cart = $this->orderShopStore->getOneCartCurrent(
[
'section' => $section,
'user' => $user,
'visitor' => $visitor
]
);
if (!$cart) {
$cart = $this->create($section, $user, $visitor);
}
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()->compare(
$orderProductAdd->getOrderProductReductionCatalog()
)) {
$orderProduct->setQuantityOrder(
$orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder()
);
if ($persist) {
$this->entityManager->persist($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 = $orderShop1->hasOrderProductAlreadyInCart($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 ($this->orderSh->isPaid($orderShop)) {
$nextStatus = OrderStatusModel::ALIAS_PAID;
} else {
$nextStatus = OrderStatusModel::ALIAS_PARTIAL_PAYMENT;
}
if ($orderShop->getOrderStatus()->getAlias() != $nextStatus) {
$orderShop = $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();
}
}
public function initCycleNumber(OrderShopInterface $orderShop): void
{
$cycleNumber = null;
$deliveryDate = $orderShop->getDeliveryDate();
switch ($orderShop->getSection()->getCycle()) {
case SectionModel::CYCLE_DAY:
$cycleNumber = $deliveryDate->format('z');
break;
case SectionModel::CYCLE_WEEK:
$cycleNumber = $deliveryDate->format('W');
break;
}
$orderShop->setCycleNumber($cycleNumber);
}
public function createDocumentInvoice(OrderShopInterface $orderShop): DocumentInterface
{
$documentFactory = new DocumentFactory();
$document = $documentFactory->create(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->orderShopStore->isPositiveAmount($orderShop)
&& $this->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 = $orderProduct->getProduct()->getAvailableQuantityInherited();
$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 = $orderProduct->getProduct()->getAvailableQuantityInherited();
$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);
$productsSalesStatistic->init($section, $this->orderShopSolver, $this->openingResolver);
$productsSalesStatistic->populateProperties($this->orderShopStore);
return $productsSalesStatistic->getAsArray();
}
}