Browse Source

Merge branch 'develop'

master
Fabien Normand 2 years ago
parent
commit
fd99c403e6
32 changed files with 609 additions and 521 deletions
  1. +31
    -2
      Builder/Order/OrderProductBuilder.php
  2. +77
    -106
      Builder/Order/OrderShopBuilder.php
  3. +6
    -1
      Container/Reduction/ReductionCatalogContainer.php
  4. +16
    -9
      Controller/Order/CartController.php
  5. +0
    -18
      Controller/Product/ProductFamilyAdminController.php
  6. +156
    -7
      Definition/Field/Reduction/ReductionCatalogFieldDefinition.php
  7. +0
    -64
      EventSubscriber/Product/DuplicateProductfamilyEventSubscriber.php
  8. +39
    -17
      EventSubscriber/Product/UpdateProductfamilyAfterFlushEventSubscriber.php
  9. +34
    -52
      EventSubscriber/Product/UpdateProductfamilyEventSubscriber.php
  10. +1
    -0
      Factory/Reduction/ReductionCatalogFactory.php
  11. +1
    -1
      Model/Product/ProductFamilyModel.php
  12. +23
    -0
      Model/Reduction/ReductionCatalogModel.php
  13. +1
    -1
      Repository/MerchantStoreTrait.php
  14. +1
    -0
      Repository/Order/OrderShopRepositoryQuery.php
  15. +5
    -2
      Repository/Order/OrderShopStore.php
  16. +4
    -2
      Repository/Product/ProductFamilyStore.php
  17. +58
    -40
      Repository/Product/ProductRepositoryQuery.php
  18. +2
    -0
      Repository/StoreTrait.php
  19. +0
    -7
      Resources/views/admin/product/field/product_family_sales.html.twig
  20. +0
    -24
      Resources/views/admin/product/macro/product_family_macro.html.twig
  21. +0
    -94
      Resources/views/admin/product/modal/show_products_sales_statistic.html.twig
  22. +2
    -2
      Solver/Order/OrderProductReductionCatalogSolver.php
  23. +34
    -7
      Solver/Order/OrderProductSolver.php
  24. +7
    -2
      Solver/Order/OrderShopSolver.php
  25. +13
    -8
      Solver/Price/OrderProductPriceSolver.php
  26. +2
    -1
      Solver/Price/OrderShopPriceSolver.php
  27. +8
    -2
      Solver/Price/PriceSolverTrait.php
  28. +26
    -17
      Solver/Price/ProductPriceSolver.php
  29. +39
    -14
      Solver/Product/ProductFamilySolver.php
  30. +10
    -12
      Solver/Product/ProductSolver.php
  31. +1
    -1
      Solver/Ticket/TicketSolver.php
  32. +12
    -8
      Statistic/Product/ProductsSalesStatistic.php

+ 31
- 2
Builder/Order/OrderProductBuilder.php View File

namespace Lc\CaracoleBundle\Builder\Order; namespace Lc\CaracoleBundle\Builder\Order;


use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Lc\CaracoleBundle\Factory\Order\OrderProductReductionCatalogFactory;
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Section\SectionInterface;
use Lc\CaracoleBundle\Repository\Order\OrderProductStore; use Lc\CaracoleBundle\Repository\Order\OrderProductStore;
use Lc\CaracoleBundle\Resolver\Price\PriceResolver;
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore;
use Lc\CaracoleBundle\Solver\Order\OrderProductSolver; use Lc\CaracoleBundle\Solver\Order\OrderProductSolver;
use Lc\CaracoleBundle\Solver\Price\PriceSolver; use Lc\CaracoleBundle\Solver\Price\PriceSolver;
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver; use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver;
protected ProductSolver $productSolver; protected ProductSolver $productSolver;
protected ProductFamilySolver $productFamilySolver; protected ProductFamilySolver $productFamilySolver;
protected OrderProductSolver $orderProductSolver; protected OrderProductSolver $orderProductSolver;
protected OrderProductReductionCatalogFactory $orderProductReductionCatalogFactory;
protected ProductFamilyStore $productFamilyStore;


public function __construct( public function __construct(
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
OrderProductStore $orderProductStore, OrderProductStore $orderProductStore,
ProductSolver $productSolver, ProductSolver $productSolver,
OrderProductSolver $orderProductSolver, OrderProductSolver $orderProductSolver,
ProductFamilySolver $productFamilySolver
ProductFamilySolver $productFamilySolver,
OrderProductReductionCatalogFactory $orderProductReductionCatalogFactory,
ProductFamilyStore $productFamilyStore
) { ) {
$this->entityManager = $entityManager; $this->entityManager = $entityManager;
$this->priceSolver = $priceSolver; $this->priceSolver = $priceSolver;
$this->productSolver = $productSolver; $this->productSolver = $productSolver;
$this->orderProductSolver = $orderProductSolver; $this->orderProductSolver = $orderProductSolver;
$this->productFamilySolver = $productFamilySolver; $this->productFamilySolver = $productFamilySolver;
$this->orderProductReductionCatalogFactory = $orderProductReductionCatalogFactory;
$this->productFamilyStore = $productFamilyStore;
} }


public function init(OrderProductInterface $orderProduct) :OrderProductInterface public function init(OrderProductInterface $orderProduct) :OrderProductInterface


return $orderProduct; return $orderProduct;
} }

public function initReductionCatalog(SectionInterface $section, OrderProductInterface $orderProduct, ProductFamilyInterface $productFamily): OrderProductInterface
{
if(!$orderProduct->getOrderProductReductionCatalog()) {

$reductionCatalog = $productFamily->getReductionCatalog();
if ($reductionCatalog && $reductionCatalog->getStatus()) {
$orderProductReductionCatalog = $this->orderProductReductionCatalogFactory->create(
$reductionCatalog->getTitle(),
$reductionCatalog->getValue(),
$reductionCatalog->getUnit(),
$reductionCatalog->getBehaviorTaxRate()
);

$orderProduct->setOrderProductReductionCatalog($orderProductReductionCatalog);
}
}

return $orderProduct;
}
} }

+ 77
- 106
Builder/Order/OrderShopBuilder.php View File

use Lc\CaracoleBundle\Model\Order\OrderStatusModel; use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface; use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
use Lc\CaracoleBundle\Model\Section\SectionInterface; use Lc\CaracoleBundle\Model\Section\SectionInterface;
use Lc\CaracoleBundle\Repository\Order\OrderStatusStore; use Lc\CaracoleBundle\Repository\Order\OrderStatusStore;
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore; use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore;
use Lc\CaracoleBundle\Resolver\MerchantResolver; use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\CaracoleBundle\Resolver\OpeningResolver;
use Lc\CaracoleBundle\Resolver\OrderShopResolver; use Lc\CaracoleBundle\Resolver\OrderShopResolver;
use Lc\CaracoleBundle\Solver\Order\OrderProductReductionCatalogSolver; use Lc\CaracoleBundle\Solver\Order\OrderProductReductionCatalogSolver;
use Lc\CaracoleBundle\Solver\Order\OrderProductSolver;
use Lc\CaracoleBundle\Solver\Order\OrderShopSolver; use Lc\CaracoleBundle\Solver\Order\OrderShopSolver;
use Lc\CaracoleBundle\Solver\Price\PriceSolver; use Lc\CaracoleBundle\Solver\Price\PriceSolver;
use Lc\CaracoleBundle\Solver\Product\ProductSolver; use Lc\CaracoleBundle\Solver\Product\ProductSolver;
use Lc\CaracoleBundle\Statistic\Product\ProductsSalesStatistic; use Lc\CaracoleBundle\Statistic\Product\ProductsSalesStatistic;
use Lc\SovBundle\Model\User\UserInterface; use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Translation\FlashBagTranslator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;


protected DocumentBuilder $documentBuilder; protected DocumentBuilder $documentBuilder;
protected EventDispatcherInterface $eventDispatcher; protected EventDispatcherInterface $eventDispatcher;
protected FlashBagInterface $flashBag; protected FlashBagInterface $flashBag;
protected OpeningResolver $openingResolver;
protected ProductSolver $productSolver; protected ProductSolver $productSolver;
protected OrderShopResolver $orderShopResolver; protected OrderShopResolver $orderShopResolver;
protected OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver; protected OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver;
protected DistributionBuilder $distributionBuilder; protected DistributionBuilder $distributionBuilder;
protected MerchantResolver $merchantResolver; protected MerchantResolver $merchantResolver;
protected CreditHistoryBuilder $creditHistoryBuilder; protected CreditHistoryBuilder $creditHistoryBuilder;
protected FlashBagTranslator $flashBagTranslator;
protected OrderShopFactory $orderShopFactory; protected OrderShopFactory $orderShopFactory;
protected OrderProductSolver $orderProductSolver;


public function __construct( public function __construct(
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
PriceSolver $priceSolver, PriceSolver $priceSolver,
EventDispatcherInterface $eventDispatcher, EventDispatcherInterface $eventDispatcher,
FlashBagInterface $flashBag, FlashBagInterface $flashBag,
OpeningResolver $openingResolver,
ProductSolver $productSolver, ProductSolver $productSolver,
OrderShopResolver $orderShopResolver, OrderShopResolver $orderShopResolver,
OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver, OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver,
DistributionBuilder $distributionBuilder, DistributionBuilder $distributionBuilder,
MerchantResolver $merchantResolver, MerchantResolver $merchantResolver,
CreditHistoryBuilder $creditHistoryBuilder, CreditHistoryBuilder $creditHistoryBuilder,
FlashBagTranslator $flashBagTranslator,
OrderShopFactory $orderShopFactory
OrderShopFactory $orderShopFactory,
OrderProductSolver $orderProductSolver
) { ) {
$this->entityManager = $entityManager; $this->entityManager = $entityManager;
$this->orderShopStore = $orderShopStore; $this->orderShopStore = $orderShopStore;
$this->priceSolver = $priceSolver; $this->priceSolver = $priceSolver;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->flashBag = $flashBag; $this->flashBag = $flashBag;
$this->openingResolver = $openingResolver;
$this->productSolver = $productSolver; $this->productSolver = $productSolver;
$this->orderShopResolver = $orderShopResolver; $this->orderShopResolver = $orderShopResolver;
$this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver; $this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver;
$this->distributionBuilder = $distributionBuilder; $this->distributionBuilder = $distributionBuilder;
$this->merchantResolver = $merchantResolver; $this->merchantResolver = $merchantResolver;
$this->creditHistoryBuilder = $creditHistoryBuilder; $this->creditHistoryBuilder = $creditHistoryBuilder;
$this->flashBagTranslator = $flashBagTranslator;
$this->orderShopFactory = $orderShopFactory; $this->orderShopFactory = $orderShopFactory;
$this->orderProductSolver = $orderProductSolver;
} }


public function create( public function create(
): bool { ): bool {
$return = false; $return = false;


$orderProductAdd->setOrderShop($orderShop);

if ($this->orderShopSolver->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) { if ($this->orderShopSolver->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) {
if ($orderProductAdd->getQuantityOrder() > 0) { if ($orderProductAdd->getQuantityOrder() > 0) {
$updated = false; $updated = false;

$this->orderProductBuilder->init($orderProductAdd); $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);
//TODO vérifier ma modif ici
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) { 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()
)) {
if ($this->orderProductSolver->compare($orderProduct, $orderProductAdd)) {
$orderProduct->setQuantityOrder( $orderProduct->setQuantityOrder(
$orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder() $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder()
); );
OrderShopInterface $orderShop2, OrderShopInterface $orderShop2,
$persist = true $persist = true
): OrderShopInterface { ): OrderShopInterface {
//TODO essayer de comprendre prk on doit faire un refresh ici ???

// TODO essayer de comprendre pourquoi on doit faire un refresh ici
$this->entityManager->refresh($orderShop1); $this->entityManager->refresh($orderShop1);
$this->entityManager->refresh($orderShop2); $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);
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) { if ($persist) {
$this->entityManager->delete($orderShop2);
$this->entityManager->update($orderShop1);
$this->entityManager->flush();
$this->entityManager->delete($orderProduct);
} }
}


return $orderShop1;
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 public function addPayment(OrderShopInterface $orderShop, string $meanPayment, float $amount): OrderShopInterface
public function deductAvailabilityProduct(OrderShopInterface $orderShop): void public function deductAvailabilityProduct(OrderShopInterface $orderShop): void
{ {
foreach ($orderShop->getOrderProducts() as $orderProduct) { foreach ($orderShop->getOrderProducts() as $orderProduct) {
$this->applyDeductAvailabilityProduct($orderShop, $orderProduct);
$this->applyDeductAvailabilityProduct($orderShop, $orderProduct->getProduct(), $orderProduct->getQuantityOrder());
} }
} }


public function applyDeductAvailabilityProduct( public function applyDeductAvailabilityProduct(
OrderShopInterface $orderShop, OrderShopInterface $orderShop,
OrderProductInterface $orderProduct
ProductInterface $product,
int $quantityOrder
): void { ): void {
switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) {
switch ($product->getProductFamily()->getBehaviorCountStock()) {
case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE : case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE :


//Disponibilité par unité de référence //Disponibilité par unité de référence
$oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct());
$newAvailability = $oldAvailability - ($orderProduct->getQuantityOrder(
) * ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient()));
$oldAvailability = $this->productSolver->getAvailableQuantityInherited($product);
$newAvailability = $oldAvailability - ($quantityOrder * ($this->productSolver->getQuantityInherited(
$product
) / $this->productSolver->getUnitInherited($product)->getCoefficient()));


$productFamily = $orderProduct->getProduct()->getProductFamily();
$productFamily = $product->getProductFamily();
$productFamily->setAvailableQuantity($newAvailability); $productFamily->setAvailableQuantity($newAvailability);
$productFamily->setUpdatedBy($orderShop->getUser()); $productFamily->setUpdatedBy($orderShop->getUser());


break; break;
case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY : case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :


$oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct());
$newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
$oldAvailability = $this->productSolver->getAvailableQuantityInherited($product);
$newAvailability = $oldAvailability - $quantityOrder;


$productFamily = $orderProduct->getProduct()->getProductFamily();
$productFamily = $product->getProductFamily();
$productFamily->setAvailableQuantity($newAvailability); $productFamily->setAvailableQuantity($newAvailability);
$productFamily->setUpdatedBy($orderShop->getUser()); $productFamily->setUpdatedBy($orderShop->getUser());




break; break;
case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT : case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
$oldAvailability = $this->productSolver->getAvailableQuantityInherited($orderProduct->getProduct());
$newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
$oldAvailability = $this->productSolver->getAvailableQuantityInherited($product);
$newAvailability = $oldAvailability - $quantityOrder;


$product = $orderProduct->getProduct();
$product->setAvailableQuantity($newAvailability); $product->setAvailableQuantity($newAvailability);
$product->setUpdatedBy($orderShop->getUser()); $product->setUpdatedBy($orderShop->getUser());




break; break;
} }

$this->entityManager->flush(); $this->entityManager->flush();
} }



public function updatePriceByProductFamily(ProductFamilyInterface $productFamily)
public function updatePriceByProductFamily(ProductFamilyInterface $productFamily, SectionInterface $section)
{ {
$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);
$countOrderProductUpdated = 0;


foreach ($orderProducts as $orderProduct) {
$quantityOrder = $orderProduct->getQuantityOrder();
$orderShop = $orderProduct->getOrderShop();
foreach ($productFamily->getProducts() as $product) {
$orderProducts = $this->orderProductStore->resetContext()->setSection(
$section
)->getInCartsByProduct($product);


$orderShop->removeOrderProduct($orderProduct);
$this->entityManager->delete($orderProduct);
$this->entityManager->flush();
$this->entityManager->refresh($orderShop);
foreach ($orderProducts as $orderProduct) {
$quantityOrder = $orderProduct->getQuantityOrder();
$orderShop = $orderProduct->getOrderShop();


$orderProductFactory = new OrderProductFactory();
$addOrderProduct = $orderProductFactory->create($product, $quantityOrder);
$this->addOrderProduct($orderShop, $addOrderProduct);
$orderShop->removeOrderProduct($orderProduct);
$this->entityManager->delete($orderProduct);
$this->entityManager->flush();
$this->entityManager->refresh($orderShop);


$countOrderProductUpdated++;
}
}
if ($countOrderProductUpdated) {
$this->flashBagTranslator->add(
'success',
'orderProductUpdated',
'OrderShop',
//array('%count%' => $countOrderProductUpdated)
['%count' => $debug]
);
$orderProductFactory = new OrderProductFactory();
$addOrderProduct = $orderProductFactory->create($product, $quantityOrder);
$this->addOrderProduct($orderShop, $addOrderProduct);


$this->entityManager->flush();
}
return $countOrderProductUpdated;
$countOrderProductUpdated++;
} }
} }
if ($countOrderProductUpdated) {
$this->entityManager->flush();
}
return $countOrderProductUpdated;
} }





+ 6
- 1
Container/Reduction/ReductionCatalogContainer.php View File

use Lc\CaracoleBundle\Factory\Reduction\ReductionCatalogFactory; use Lc\CaracoleBundle\Factory\Reduction\ReductionCatalogFactory;
use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogRepositoryQuery; use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogRepositoryQuery;
use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogStore; use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogStore;
use Lc\CaracoleBundle\Solver\Reduction\ReductionCatalogSolver;


class ReductionCatalogContainer class ReductionCatalogContainer
{ {
$this->fieldDefinition = $fieldDefinition; $this->fieldDefinition = $fieldDefinition;
} }



public static function getEntityFqcn() public static function getEntityFqcn()
{ {
return ReductionCatalog::class; return ReductionCatalog::class;
return $this->fieldDefinition; return $this->fieldDefinition;
} }


// public function getSolver(): ReductionCatalogSolver
// {
// return $this->solver;
// }

} }

+ 16
- 9
Controller/Order/CartController.php View File

use Lc\CaracoleBundle\Controller\AbstractController; use Lc\CaracoleBundle\Controller\AbstractController;
use Lc\CaracoleBundle\Form\Order\OrderProductsType; use Lc\CaracoleBundle\Form\Order\OrderProductsType;
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
class CartController extends AbstractController class CartController extends AbstractController
{ {
protected ProductFamilyInterface $productFamily; protected ProductFamilyInterface $productFamily;
protected int $quantityOrder = 1;
protected array $orderProducts = []; protected array $orderProducts = [];


public function addProductFamily(Request $request): JsonResponse public function addProductFamily(Request $request): JsonResponse
$data = $form->getData(); $data = $form->getData();
foreach ($data as $orderProduct) { foreach ($data as $orderProduct) {
if ($orderProduct instanceof OrderProductInterface) { if ($orderProduct instanceof OrderProductInterface) {
if ($orderProduct->getQuantityOrder() > 0) {
$addOrderProduct = $this->getOrderShopContainer()->getBuilder()->addOrderProduct(
$orderShop,
$orderProduct
);
}
if (isset($addOrderProduct) && $addOrderProduct && $orderProduct->getQuantityOrder() > 0) {
$this->orderProducts[] = $orderProduct;
}
$this->addOrderProduct($orderShop, $orderProduct);
} }
} }
} }
return new JsonResponse($return); return new JsonResponse($return);
} }


public function addOrderProduct(OrderShopInterface $orderShop, OrderProductInterface $orderProduct): void
{
$this->quantityOrder = $orderProduct->getQuantityOrder();
$addOrderProduct = $this->getOrderShopContainer()->getBuilder()->addOrderProduct(
$orderShop,
$orderProduct
);

if (isset($addOrderProduct) && $addOrderProduct && $orderProduct->getQuantityOrder() > 0) {
$this->orderProducts[] = $orderProduct;
}
}

/** /**
* @Route("/order-reduction-cart/delete/{id}", name="delete_reduction_cart") * @Route("/order-reduction-cart/delete/{id}", name="delete_reduction_cart")
*/ */

+ 0
- 18
Controller/Product/ProductFamilyAdminController.php View File

return $responseParameters; return $responseParameters;
} }


public function showSalesStatistic(AdminContext $context)
{
$productFamily = $context->getEntity()->getInstance();

$currentSection = $this->get(SectionResolver::class)->getCurrent();
$productsSalesStatistic = $this->get(OrderShopContainer::class)->getBuilder()->getProductsSalesStatistic($currentSection, $productFamily, 16);
$parameters = array(
'productFamily' => $productFamily,
'productsSalesStatistic' => $productsSalesStatistic
);

//TODO flashMessages ???
$response['flashMessages'] = [];//$this->utils->getFlashMessages();
$response['data'] = $this->render('@LcCaracole/admin/product/modal/show_products_sales_statistic.html.twig', $parameters)->getContent();
$response['statistics'] = $productsSalesStatistic;
return new Response(json_encode($response));
}

} }

+ 156
- 7
Definition/Field/Reduction/ReductionCatalogFieldDefinition.php View File



namespace Lc\CaracoleBundle\Definition\Field\Reduction; namespace Lc\CaracoleBundle\Definition\Field\Reduction;


use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\CaracoleBundle\Definition\Field\AbstractFieldDefinition;
use Lc\CaracoleBundle\Repository\Section\SectionStore;
use Lc\CaracoleBundle\Context\MerchantContextTrait;
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition;
use Lc\CaracoleBundle\Field\AssociationField;
use Lc\CaracoleBundle\Model\Config\TaxRateModel;
use Lc\CaracoleBundle\Model\Config\UnitModel;
use Lc\CaracoleBundle\Repository\Product\ProductCategoryStore;
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore;
use Lc\CaracoleBundle\Repository\User\GroupUserStore;
use Lc\CaracoleBundle\Repository\User\UserStore;
use Lc\SovBundle\Field\BooleanField;
use Lc\SovBundle\Translation\TranslatorAdmin; use Lc\SovBundle\Translation\TranslatorAdmin;


class ReductionCatalogFieldDefinition extends AbstractFieldDefinition class ReductionCatalogFieldDefinition extends AbstractFieldDefinition
{ {
protected SectionStore $sectionStore;
use MerchantContextTrait;


public function __construct(TranslatorAdmin $translatorAdmin, SectionStore $sectionStore)
protected GroupUserStore $groupUserStore;
protected UserStore $userStore;
protected ProductFamilyStore $productFamilyStore;
protected ProductCategoryStore $productCategoryStore;

public function __construct(
TranslatorAdmin $translatorAdmin,
GroupUserStore $groupUserStore,
UserStore $userStore,
ProductFamilyStore $productFamilyStore,
ProductCategoryStore $productCategoryStore
)
{ {
parent::__construct($translatorAdmin); parent::__construct($translatorAdmin);
$this->sectionStore = $sectionStore;
$this->groupUserStore = $groupUserStore;
$this->userStore = $userStore;
$this->productFamilyStore = $productFamilyStore;
$this->productCategoryStore = $productCategoryStore;
}

public function configureIndex(): array
{

return [
'id',
'title',
'value',
'status',
'isDisplayed'

];
}

public function configureForm(): array
{
return [
'title',
'behaviorTaxRate',
'unit',
'value',
'permanent',
'dateStart',
'dateEnd',
'usersActive',
'users',
'groupUsersActive',
'groupUsers',
'productCategoriesActive',
'productCategories',
'productFamiliesActive',
'productFamilies',
'status',
'isDisplayed'

];
} }


public function configureFields(): array public function configureFields(): array
{ {
$groupUserArray = $this->groupUserStore->setMerchant($this->merchant)->get();
$usersArray = $this->userStore->setMerchant($this->merchant)->getJoinGroupUsers();
$productFamilyArray = $this->productFamilyStore->setMerchant($this->merchant)->get();
$productCategoryArray = $this->productCategoryStore->setMerchant($this->merchant)->get();

return [ return [
'title' => TextField::new('title')->setSortable(true)
// @TODO : à faire
'title' => TextField::new('title')->setSortable(true),
'behaviorTaxRate' => ChoiceField::new('behaviorTaxRate')
->setFormTypeOption('required', true)
->setFormTypeOption('empty_data', TaxRateModel::BEHAVIOR_TAX_RATE_INCLUDED)
->setChoices(
$this->translatorAdmin->transChoices(
TaxRateModel::getBehaviorTaxRateChoices(),
'TaxRate',
'behaviorTaxRate'
)
),
'unit' => ChoiceField::new('unit')
->setFormTypeOption('expanded', true)
->setFormTypeOption('required', true)
->setChoices(
$this->translatorAdmin->transChoices(
UnitModel::getUnitAmountChoices(),
'Unit',
'unit'
)
),
'value' => NumberField::new('value')->setTemplatePath('@LcCaracole/admin/reduction/field/amount.html.twig'),
'permanent' => BooleanField::new('permanent'),
'dateStart' => DateTimeField::new('dateStart'),
'dateEnd' => DateTimeField::new('dateEnd'),
'isDisplayed'=> BooleanField::new('isDisplayed'),
'groupUsersActive' => BooleanField::new('groupUsersActive')->setFormTypeOption('mapped', false),
'groupUsers' => AssociationField::new('groupUsers')
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig')
->setFormTypeOption('choices', $groupUserArray),

'usersActive' => BooleanField::new('usersActive')->setFormTypeOption('mapped', false),

'users' => AssociationField::new('users')
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig')
->setFormTypeOption('choices', $usersArray)
->setFormTypeOption(
'choice_attr',
function ($choice, $key, $value) {
$data = array();
foreach ($choice->getGroupUsers() as $groupUser) {
$data[] = '_' . $groupUser->getId() . '_';
}

return ['data-group-users' => json_encode($data)];
},
),


'productCategoriesActive' => BooleanField::new('productCategoriesActive')->setFormTypeOption('mapped', false),
'productCategories' => AssociationField::new('productCategories')
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig')
->setFormTypeOption('choice_label',
// @TODO : attention, code dupliqué de ProductCategoriesFilter
function ($category) {
$isOffline = '';
if ($category->getStatus() != 1) {
$isOffline = " [Hors ligne]";
}
$section = ' [' . $category->getSection()->getTitle() . ']';;
return $category . $section . $isOffline;
})
->setFormTypeOption('choices', $productCategoryArray),


'productFamiliesActive' => BooleanField::new('productFamiliesActive')->setFormTypeOption('mapped', false),
'productFamilies' => AssociationField::new('productFamilies')
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig')
->setFormTypeOption('choices', $productFamilyArray)
->setFormTypeOption(
'choice_attr',
function ($choice, $key, $value) {
$data = array();
foreach ($choice->getProductCategories() as $category) {
$data[] = '_' . $category->getId() . '_';
}
return [
'data-product-categories' => json_encode($data),
'data-supplier' => $choice->getSupplier()->getId()
];
}
),
'productFamily' => AssociationField::new('productFamily')
->setFormTypeOption('choices', $productFamilyArray)
]; ];
} }
} }

+ 0
- 64
EventSubscriber/Product/DuplicateProductfamilyEventSubscriber.php View File

<?php

namespace Lc\CaracoleBundle\EventSubscriber\Product;

use Doctrine\ORM\EntityManagerInterface;

use Lc\CaracoleBundle\Model\Address\AddressInterface;
use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Doctrine\Extension\SluggableInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\StatusInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Event\EntityComponentEvent;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Repository\AbstractRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class DuplicateProductfamilyEventSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;

public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}

public static function getSubscribedEvents()
{
return [
EntityComponentEvent::DUPLICATE_EVENT => ['duplicateProductOnDuplicateEvent'],
];
}

public function duplicateProductOnDuplicateEvent(EntityComponentEvent $event)
{
$entity = $event->getEntity();

$classMetadata = $this->em->getClassMetadata(get_class($entity));

/*foreach ($classMetadata->getAssociationMappings() as $associationMapping){
if(in_array(ProductInterface::class, class_implements($associationMapping['targetEntity']))){

/*foreach ($productFamily->getProducts() as $i => $product) {
$newProduct = clone $product;
$newProduct->setProductFamily($productFamily);
$this->em->persist($newProduct);
$productFamily->addProduct($newProduct);
}

$methodGet = 'get'.ucfirst($associationMapping['fieldName']);
$methodSet = 'set'.ucfirst($associationMapping['fieldName']);
if(method_exists($entity, $methodGet) && method_exists($entity, $methodSet)){
$newAddress = clone $entity->$methodGet();
$entity->$methodSet($newAddress);
$this->em->persist($newAddress);
}
}

}*/
}

}

+ 39
- 17
EventSubscriber/Product/UpdateProductfamilyAfterFlushEventSubscriber.php View File



namespace Lc\CaracoleBundle\EventSubscriber\Product; namespace Lc\CaracoleBundle\EventSubscriber\Product;


use Doctrine\ORM\EntityManagerInterface;

use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent; use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use Lc\CaracoleBundle\Builder\Order\OrderShopBuilder; use Lc\CaracoleBundle\Builder\Order\OrderShopBuilder;
use Lc\CaracoleBundle\Container\Product\ProductContainer;
use Lc\CaracoleBundle\Container\Product\ProductFamilyContainer;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\CaracoleBundle\Resolver\OpeningResolver;
use Lc\SovBundle\Translation\FlashBagTranslator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;


class UpdateProductfamilyAfterFlushEventSubscriber implements EventSubscriberInterface class UpdateProductfamilyAfterFlushEventSubscriber implements EventSubscriberInterface
{ {
protected EntityManagerInterface $em;
protected ProductFamilyContainer $productFamilyContainer;
protected ProductContainer $productContainer;
protected OrderShopBuilder $orderShopBuilder; protected OrderShopBuilder $orderShopBuilder;
protected OpeningResolver $openingResolver;
protected FlashBagTranslator $flashBagTranslator;


public function __construct(EntityManagerInterface $entityManager, ProductFamilyContainer $productFamilyContainer, ProductContainer $productContainer, OrderShopBuilder $orderShopBuilder)
public function __construct(
OrderShopBuilder $orderShopBuilder,
OpeningResolver $openingResolver,
FlashBagTranslator $flashBagTranslator
)
{ {
$this->em = $entityManager;
$this->productFamilyContainer = $productFamilyContainer;
$this->productContainer = $productContainer;
$this->orderShopBuilder = $orderShopBuilder; $this->orderShopBuilder = $orderShopBuilder;
$this->openingResolver = $openingResolver;
$this->flashBagTranslator = $flashBagTranslator;
} }


public static function getSubscribedEvents() public static function getSubscribedEvents()


public function processAfterFlushProductFamily(AfterEntityUpdatedEvent $event) public function processAfterFlushProductFamily(AfterEntityUpdatedEvent $event)
{ {
$entity = $event->getEntityInstance();
if ($entity instanceof ProductFamilyInterface) {
$this->orderShopBuilder->updatePriceByProductFamily($entity);
$productFamily = $event->getEntityInstance();
if ($productFamily instanceof ProductFamilyInterface) {


foreach ($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) {

$section = $productFamilySectionProperty->getSection();

if (!$this->openingResolver->isOpenSale($section)) {

$countOrderProductUpdated = $this->orderShopBuilder->updatePriceByProductFamily($productFamily, $section);

if ($countOrderProductUpdated) {
$this->flashBagTranslator->add(
'success',
'orderProductUpdated',
'OrderShop',
array(
'%count%' => $countOrderProductUpdated,
'%section%' => $section->getTitle()
)
);
}

}
}
} }
} }
} }

+ 34
- 52
EventSubscriber/Product/UpdateProductfamilyEventSubscriber.php View File

protected function processProducts($entity) protected function processProducts($entity)
{ {


if($entity->getId()) {
if ($entity->getId()) {
//Récupère le product origin //Récupère le product origin
$originProducts = $this->productContainer->getStore()->getOriginByProductFamily($entity); $originProducts = $this->productContainer->getStore()->getOriginByProductFamily($entity);

if (count($originProducts) > 1) {
throw new \ErrorException('Plusieurs OriginProduct pour un même produit... Contacter fab');
// Case Nouveau product family
} else {
if (count($originProducts) == 0) {
$entityClassName = $this->em->getEntityName(ProductInterface::class);
$originProduct = new $entityClassName();
$originProduct->setProductFamily($entity);
$originProduct->setOriginProduct(true);
$entity->addProduct($originProduct);
} else {
$originProduct = $originProducts[0];
}
}

if ($entity->getActiveProducts()) {
$originProduct->setStatus(-1);
} else {
//CAse de création d'un produit
$originProducts = array();
}
if (count($originProducts) > 1) {
throw new \ErrorException('Plusieurs OriginProduct pour un même produit... Contacter fab');
// Case Nouveau product family
} else {
if (count($originProducts) == 0) {
$entityClassName = $this->em->getEntityName(ProductInterface::class);
$originProduct = new $entityClassName();
$originProduct->setProductFamily($entity);
$originProduct->setOriginProduct(true);
$entity->addProduct($originProduct);
} else { } else {
$originProduct->setStatus(1);
$originProduct = $originProducts[0];
} }
}


//Enregistrement
$entity->addProduct($originProduct);
if ($entity->getActiveProducts()) {
$originProduct->setStatus(-1);
} else {
$originProduct->setStatus(1);
}


foreach ($entity->getProducts() as $product) {
$product->setProductFamily($entity);
//Enregistrement
$entity->addProduct($originProduct);


if ($entity->getProductsQuantityAsTitle() && $product->getStatus() >= 1) {
$product->setTitle(
str_replace('.', ',', $this->productContainer->getSolver()->getQuantityInherited($product)) . $this->productContainer->getSolver()->getUnitInherited($product)->getWording()
);
}
foreach ($entity->getProducts() as $product) {
$product->setProductFamily($entity);


$this->em->persist($product);
$entity->addProduct($product);
if ($entity->getProductsQuantityAsTitle() && $product->getStatus() >= 1) {
$product->setTitle(
str_replace('.', ',', $this->productContainer->getSolver()->getQuantityInherited($product)) . $this->productContainer->getSolver()->getUnitInherited($product)->getWording()
);
} }

$this->em->persist($product);
$entity->addProduct($product);
} }
}


/* protected function processCategories(ProductFamilyInterface $entity)
{
$productCategoryRepository = $this->em->getRepository(ProductCategoryInterface::class);
$productCategories = $entity->getProductCategories();

$entity->initProductCategories();

foreach ($productCategories as $key => $bool) {
if (is_bool($bool) && $bool) {
if (strpos($key, 'category_children_') !== false) {
$idCategory = (int)str_replace('category_children_', '', $key);
} else {
$idCategory = (int)str_replace('category_', '', $key);
}

$category = $productCategoryRepository->find($idCategory);
$entity->addProductCategory($category);
}
}
}*/
}
} }

+ 1
- 0
Factory/Reduction/ReductionCatalogFactory.php View File

$class = ReductionCatalogContainer::getEntityFqcn(); $class = ReductionCatalogContainer::getEntityFqcn();
$reductionCatalog = new $class; $reductionCatalog = new $class;


$reductionCatalog->setIsDisplayed(true);
$reductionCatalog->setMerchant($merchant); $reductionCatalog->setMerchant($merchant);
$reductionCatalog->setStatus($status); $reductionCatalog->setStatus($status);



+ 1
- 1
Model/Product/ProductFamilyModel.php View File

protected $image; protected $image;


/** /**
* @ORM\ManyToMany(targetEntity="Lc\CaracoleBundle\Model\Product\QualityLabelInterface", fetch="EAGER")
* @ORM\ManyToMany(targetEntity="Lc\CaracoleBundle\Model\Product\QualityLabelInterface", fetch="LAZY")
*/ */
protected $qualityLabels; protected $qualityLabels;



+ 23
- 0
Model/Reduction/ReductionCatalogModel.php View File

*/ */
protected $productCategories; protected $productCategories;


/**
* @ORM\Column(type="boolean", nullable=false)
*/
protected $isDisplayed;

public function __construct() public function __construct()
{ {
$this->__reductionPropertyConstruct(); $this->__reductionPropertyConstruct();
return $this; return $this;
} }



public function getIsDisplayed(): bool
{
return $this->isDisplayed;
}

public function isDisplayed(): bool
{
return $this->isDisplayed;
}

public function setIsDisplayed(bool $isDisplayed): self
{
$this->isDisplayed = $isDisplayed;

return $this;
}

} }

+ 1
- 1
Repository/MerchantStoreTrait.php View File



public function addFilterByMerchantViaSectionRequired(RepositoryQueryInterface $query): StoreInterface public function addFilterByMerchantViaSectionRequired(RepositoryQueryInterface $query): StoreInterface
{ {
$this->addFilterByMerchantOptionnal($query);
$this->addFilterByMerchantViaSectionOptionnal($query);


if(!$this->isMerchantDefined()) { if(!$this->isMerchantDefined()) {
throw new \ErrorException('Le Merchant doit être définie dans '.get_class($this)); throw new \ErrorException('Le Merchant doit être définie dans '.get_class($this));

+ 1
- 0
Repository/Order/OrderShopRepositoryQuery.php View File

); );
} }



public function selectSum(): self public function selectSum(): self
{ {
$this->joinProduct(); $this->joinProduct();

+ 5
- 2
Repository/Order/OrderShopStore.php View File

use Lc\CaracoleBundle\Model\Distribution\DistributionInterface; use Lc\CaracoleBundle\Model\Distribution\DistributionInterface;
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductInterface; use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface; use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
public function countValidOrderProductsOfDistributionsByProducts( public function countValidOrderProductsOfDistributionsByProducts(
array $distributions, array $distributions,
array $products, array $products,
ProductFamilyInterface $productFamily,
$query = null $query = null
): array { ): array {
$query = $this->createDefaultQuery($query); $query = $this->createDefaultQuery($query);
->selectSum() ->selectSum()
->groupBy('distribution.cycleNumber, product.id'); ->groupBy('distribution.cycleNumber, product.id');


//TODO vérifier ou est utilisé cette fonction ???


return $query->find(); return $query->find();
} }
DistributionInterface $distribution, DistributionInterface $distribution,
ProductInterface $product, ProductInterface $product,
$query = null $query = null
): ?string {
): float {
//TODO attention à vérifier //TODO attention à vérifier
$query = $this->createQuery($query); $query = $this->createQuery($query);


if ($result) { if ($result) {
return $result['quantity']; return $result['quantity'];
} }
return null;
return 0;
} }


public function isReductionCreditAllowAddToOrder( public function isReductionCreditAllowAddToOrder(

+ 4
- 2
Repository/Product/ProductFamilyStore.php View File

protected ProductFamilyRepositoryQuery $query; protected ProductFamilyRepositoryQuery $query;
protected PriceSolver $priceSolver; protected PriceSolver $priceSolver;


public function __construct(ProductFamilyRepositoryQuery $query, PriceSolver $priceSolver)
{
public function __construct(
ProductFamilyRepositoryQuery $query,
PriceSolver $priceSolver
) {
$this->query = $query; $this->query = $query;
$this->priceSolver = $priceSolver; $this->priceSolver = $priceSolver;
} }

+ 58
- 40
Repository/Product/ProductRepositoryQuery.php View File



class ProductRepositoryQuery extends AbstractRepositoryQuery class ProductRepositoryQuery extends AbstractRepositoryQuery
{ {
protected bool $isJoinProductFamily =false;
protected bool $isJoinSections =false;
protected bool $isJoinProductFamilySectionProperties =false;
protected bool $isJoinProductFamily = false;
protected bool $isJoinSections = false;
protected bool $isJoinProductFamilySectionProperties = false;


public function __construct(ProductRepository $repository, PaginatorInterface $paginator) public function __construct(ProductRepository $repository, PaginatorInterface $paginator)
{ {
parent::__construct($repository, 'product', $paginator); parent::__construct($repository, 'product', $paginator);
} }

public function orderByDefault(): \Lc\SovBundle\Repository\AbstractRepositoryQuery public function orderByDefault(): \Lc\SovBundle\Repository\AbstractRepositoryQuery
{ {
return $this->orderBy('position', 'ASC'); return $this->orderBy('position', 'ASC');
} }


public function joinProductFamily():self
public function joinProductFamily(): self
{ {
if (!$this->isJoinProductFamily) { if (!$this->isJoinProductFamily) {
$this->isJoinProductFamily = true; $this->isJoinProductFamily = true;


return $this return $this
->innerJoin('.productFamily', 'productFamily')
->addSelect('productFamily');
->innerJoin('.productFamily', 'productFamily')
->addSelect('productFamily');
} }
return $this; return $this;
} }


public function filterBySection(SectionInterface $section):self

public function filterBySection(SectionInterface $section): self
{ {
$this->joinProductFamilySectionProperties(false); $this->joinProductFamilySectionProperties(false);
$this->andWhereSection('productFamilySectionProperties', $section); $this->andWhereSection('productFamilySectionProperties', $section);
} }




public function filterIsOnline():self
public function filterIsOnline(): self
{ {
$this->joinProductFamily(); $this->joinProductFamily();
$this->andWhereStatus('productFamily', 1); $this->andWhereStatus('productFamily', 1);
return $this; return $this;
} }


public function filterIsOnlineAndOffline(): self
{
$this->joinProductFamily();
$this->andWhere('productFamily.status >= 0');
$this->andWhere('.status >=0');
return $this;
}


public function filterIsOnSale(): self
{
$this->joinProductFamily();
$this->andWhere('productFamily.saleStatus = 1');
return $this;
}



public function filterIsOriginProduct():self
public function filterIsOriginProduct(): self
{ {
$this->andWhere('.originProduct = 1'); $this->andWhere('.originProduct = 1');
return $this; return $this;
} }




public function filterIsNotAvailableQuantitySupplierUnlimited():self
public function filterIsNotAvailableQuantitySupplierUnlimited(): self
{ {
$this->andWhere('productFamily.availableQuantitySupplierUnlimited != 1'); $this->andWhere('productFamily.availableQuantitySupplierUnlimited != 1');
return $this; return $this;
} }




public function filterAvailableQuantityNegative() :self
public function filterAvailableQuantityNegative(): self
{ {


$this->andWhere( $this->andWhere(
$this->query->expr()->orX(
$this->query->expr()->andX(
$this->query->expr()->orX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProductFamily',
'productFamily.behaviorCountStock LIKE :behaviorCountStockByMeasure'
),
'productFamily.availableQuantity < 0 '
),
$this->query->expr()->andX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProduct',
'product.availableQuantity < 0 '
)
$this->query->expr()->orX(
$this->query->expr()->andX(
$this->query->expr()->orX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProductFamily',
'productFamily.behaviorCountStock LIKE :behaviorCountStockByMeasure'
),
'productFamily.availableQuantity < 0 '
),
$this->query->expr()->andX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProduct',
'product.availableQuantity < 0 '
) )
)
); );
$this->setParameter( $this->setParameter(
'behaviorCountStockByProductFamily',
ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
'behaviorCountStockByProductFamily',
ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
); );
$this->setParameter('behaviorCountStockByMeasure', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE); $this->setParameter('behaviorCountStockByMeasure', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE);
$this->setParameter('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT); $this->setParameter('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT);
return $this; return $this;
} }


public function filterAvailableQuantitySupplierNegative() :self
public function filterAvailableQuantitySupplierNegative(): self
{ {


$this->andWhere( $this->andWhere(
$this->query->expr()->orX(
$this->query->expr()->andX(
$this->query->expr()->orX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProductFamily',
'productFamily.behaviorCountStock LIKE :behaviorCountStockByMeasure'
),
'productFamily.availableQuantitySupplier < 0 '
),
$this->query->expr()->andX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProduct',
'product.availableQuantitySupplier < 0 '
)
$this->query->expr()->orX(
$this->query->expr()->andX(
$this->query->expr()->orX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProductFamily',
'productFamily.behaviorCountStock LIKE :behaviorCountStockByMeasure'
),
'productFamily.availableQuantitySupplier < 0 '
),
$this->query->expr()->andX(
'productFamily.behaviorCountStock LIKE :behaviorCountStockByProduct',
'product.availableQuantitySupplier < 0 '
) )
)
); );
$this->setParameter( $this->setParameter(
'behaviorCountStockByProductFamily',
ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
'behaviorCountStockByProductFamily',
ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
); );
$this->setParameter('behaviorCountStockByMeasure', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE); $this->setParameter('behaviorCountStockByMeasure', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE);
$this->setParameter('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT); $this->setParameter('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT);

+ 2
- 0
Repository/StoreTrait.php View File

} }
return $this; return $this;
} }


} }

+ 0
- 7
Resources/views/admin/product/field/product_family_sales.html.twig View File

{# @var field \EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto #}

{% import '@LcCaracole/admin/product/macro/product_family_macro.html.twig' as pfm %}
{% set section_current = section_container.resolver.getCurrent() %}
{% if section_current %}
{{ pfm.product_family_sales_statistic(order_shop_container.builder.getProductsSalesStatistic(section_current, entity.instance, 2), entity.instance) }}
{% endif %}

+ 0
- 24
Resources/views/admin/product/macro/product_family_macro.html.twig View File

{% extends '@LcCaracole/admin/product/macro/product_family_macro.html.twig' %}


{% macro product_family_sales_statistic(productsSalesStatistic, productFamily) %}
{% if productsSalesStatistic and productsSalesStatistic|length %}
<button type="button" data-product-family="{{ productFamily.id }}"
class="lc-show-products-sales-statistic btn btn-sm"
data-toggle="tooltip" title="{{ 'showHistorySales'|sov_trans_admin_action }}"
data-url="{{ ea_url({crudAction : 'showSalesStatistic', entityId: productFamily.id }) }}">
{% for key, weekNumberQuantity in productsSalesStatistic['data']['total_sales']['data'] %}
<span class="text-success">
<i class="fa fa-calendar"></i>
{{ productsSalesStatistic['label'][key] }}</span>
<span class="text-info"><i class="fa fa-shopping-basket"></i>
<strong>
{{ weekNumberQuantity is null ? 0 : weekNumberQuantity }}
{% if productFamily and (productFamily.behaviorDisplaySale== constant('App\\Entity\\Product\\ProductFamily::BEHAVIOR_DISPLAY_SALE_BY_MEASURE')) %}
{{ productFamily.unit.unitReference }}
{% endif %}
</strong>
</span>
<br/>
{% endfor %}
</button>
{% endif %}
{% endmacro product_family_sales_statistic %}


{% macro autoresize_field(field) %} {% macro autoresize_field(field) %}
<tr> <tr>

+ 0
- 94
Resources/views/admin/product/modal/show_products_sales_statistic.html.twig View File

{% embed "@LcSov/adminlte/embed/modal.twig" %}
{% import '@LcCaracole/admin/product/macro/product_family_macro.html.twig' as pfm %}

{% block size %}modal-xl{% endblock %}
{% block id %}modal-products-sales-statistic{% endblock %}
{% block title %}Total ventes/semaines : {{ productFamily.title }}{% endblock %}

{% block body %}
<div class="row">
<div class="col-10">
{{ _self.btn_pss(productsSalesStatistic, productFamily, 'Global', 'total_sales') }}
{% if productFamily.activeProducts %}
{% for product in productFamily.products %}
{% if product.status >= 0 %}
{{ _self.btn_pss(productsSalesStatistic, productFamily, product.title , product.id ) }}
{% endif %}
{% endfor %}
{% endif %}

</div>

<div class="col-2">
<h5>Stock actuel</h5>
{% include 'admin/product/field/product_family_available_quantity.html.twig' with {item:productFamily, value: productFamily.availableQuantity} %}
</div>


<div class="col-12">
{{ _self.table_pss(productsSalesStatistic, productFamily, 'total_sales') }}
{% for product in productFamily.products %}
{% if product.status >= 0 %}
{{ _self.table_pss(productsSalesStatistic, productFamily, product.id) }}
{% endif %}
{% endfor %}
</div>
<div class="col-12">
<canvas id="chart"></canvas>
</div>

</div>
{% endblock %}

{% block footer %}{% endblock %}

{% macro btn_pss(productsSalesStatistic,productFamily, label, propertyName) %}
<button style="margin-bottom: 10px;" type="button" data-property-name="{{ propertyName }}"
class="btn btn-sm btn-primary btn-products-sales-statistic">
{{ label }} <br/>
{{ productsSalesStatistic['data'][propertyName]['average_period'] }}
{% if propertyName== 'total_sales' and productFamily and (productFamily.behaviorDisplaySale== constant('Lc\\CaracoleBundle\\Model\\Product\\ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_MEASURE')) %}
{{ productFamily.unit.unitReference }}
{% endif %}
<br/>
<small>(en moyenne)</small>
</button>
{% endmacro btn_pss %}

{% macro table_pss(productsSalesStatistic, productFamily, propertyName) %}
<div style="margin:20px 0;" class="table-products-sales-statistic" id="table-products-sales-statistic-{{ propertyName }}">

<table class="table table-bordered table-striped">
<tbody>
<tr>
<th class="text-success">
<i class="fa fa-calendar"></i> Semaine
</th>
{% for weekNumber, weekNumberQuantity in productsSalesStatistic['data'][propertyName]['data'] %}
<td class="text-success align-right">
{{ weekNumber }}
</td>
{% endfor %}
</tr>
<tr>
<th class="text-info">
<i class="fa fa-shopping-basket"></i> Commandés
</th>
{% for weekNumber, weekNumberQuantity in productsSalesStatistic['data'][propertyName]['data'] %}
<td class="text-info align-right">
<strong>
{{ weekNumberQuantity is null ? 0 : weekNumberQuantity }}
{% if propertyName== 'total_sales' and productFamily and (productFamily.behaviorDisplaySale== constant('Lc\\CaracoleBundle\\Model\\Product\\ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_MEASURE')) %}
{{ productFamily.unit.unitReference }}
{% endif %}
</strong>
</td>
{% endfor %}
</tr>

</tbody>
</table>
</div>
{% endmacro table_pss %}
{% endembed %}


+ 2
- 2
Solver/Order/OrderProductReductionCatalogSolver.php View File

$text = ''; $text = '';


if ($orderProductReductionCatalog->getUnit() == 'amount') { if ($orderProductReductionCatalog->getUnit() == 'amount') {
$text .= '- ' . $orderProductReductionCatalog->getValue() . '&nbsp;€';
$text .= '- ' . number_format($orderProductReductionCatalog->getValue(),2) . '&nbsp;€';
} }


if ($orderProductReductionCatalog->getUnit() == 'percent') { if ($orderProductReductionCatalog->getUnit() == 'percent') {
$text .= '- ' . $orderProductReductionCatalog->getValue() . '&nbsp;%';
$text .= '- ' . number_format($orderProductReductionCatalog->getValue(),2) . '&nbsp;%';
} }


return $text; return $text;

+ 34
- 7
Solver/Order/OrderProductSolver.php View File



use Lc\CaracoleBundle\Model\Order\OrderProductInterface; use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
use Lc\CaracoleBundle\Solver\Price\PriceSolver;
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver; use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver;
use Lc\CaracoleBundle\Solver\Product\ProductSolver; use Lc\CaracoleBundle\Solver\Product\ProductSolver;


{ {
protected ProductSolver $productSolver; protected ProductSolver $productSolver;
protected ProductFamilySolver $productFamilySolver; protected ProductFamilySolver $productFamilySolver;

public function __construct(ProductSolver $productSolver, ProductFamilySolver $productFamilySolver)
{
protected OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver;
protected PriceSolver $priceSolver;

public function __construct(
ProductSolver $productSolver,
ProductFamilySolver $productFamilySolver,
OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver,
PriceSolver $priceSolver
) {
$this->productSolver = $productSolver; $this->productSolver = $productSolver;
$this->productFamilySolver = $productFamilySolver; $this->productFamilySolver = $productFamilySolver;
$this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver;
$this->priceSolver = $priceSolver;
}

public function compare(OrderProductInterface $orderProduct1, OrderProductInterface $orderProduct2)
{
return $orderProduct1->getProduct()->getId() == $orderProduct2->getProduct()->getId()
&& $orderProduct1->getRedelivery() == $orderProduct2->getRedelivery()
&& (string)$this->priceSolver->getPrice($orderProduct1)
== (string)$this->priceSolver->getPrice($orderProduct2)
&& $this->orderProductReductionCatalogSolver->compare(
$orderProduct1->getOrderProductReductionCatalog(),
$orderProduct2->getOrderProductReductionCatalog()
);
} }


// groupOrderProductsByProductFamily // groupOrderProductsByProductFamily


// simple // simple
if ($productFamily->getBehaviorAddToCart() == 'simple') { if ($productFamily->getBehaviorAddToCart() == 'simple') {
if ($productFamily->getActiveProducts()) {
$title .= $titleProduct;
if ($this->productFamilySolver->hasProductsWithVariousWeight($productFamily)) {
$title .= ' - ' . $this->productSolver->getQuantityLabelInherited($product);

if($orderProduct->getOrderPackProduct()) {
$title .= $this->productFamilySolver->getTitleProduct($product);
}
else {
if ($productFamily->getActiveProducts()) {
$title .= $titleProduct;
if ($this->productFamilySolver->hasProductsWithVariousWeight($productFamily)) {
$title .= ' - ' . $this->productSolver->getQuantityLabelInherited($product);
}
} }
} }
} }

+ 7
- 2
Solver/Order/OrderShopSolver.php View File

]; ];
} }


public function isEmpty(OrderShopInterface $orderShop): bool
{
return $orderShop->getOrderProducts()->isEmpty();
}

public function countQuantities(OrderShopInterface $orderShop): int public function countQuantities(OrderShopInterface $orderShop): int
{ {
return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts()); return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts());
OrderShopInterface $orderShop, OrderShopInterface $orderShop,
ProductInterface $product, ProductInterface $product,
$byWeight = false $byWeight = false
): int {
): float {
$quantity = 0; $quantity = 0;
$productFamily = $product->getProductFamily(); $productFamily = $product->getProductFamily();
$behaviorCountStock = $productFamily->getBehaviorCountStock(); $behaviorCountStock = $productFamily->getBehaviorCountStock();
return false; return false;
} }



$productFamily = $product->getProductFamily(); $productFamily = $product->getProductFamily();
$quantityAsked = $quantityOrder; $quantityAsked = $quantityOrder;


return true; return true;
} }
} }

return false; return false;
} }



+ 13
- 8
Solver/Price/OrderProductPriceSolver.php View File

} }




public function getTotalWithReduction(OrderProductInterface $orderProduct)
public function getTotalWithReduction(OrderProductInterface $orderProduct, bool $round = true)
{ {
return $this->applyReductionCatalog( return $this->applyReductionCatalog(
$orderProduct, $orderProduct,
$this->getTotal($orderProduct), $this->getTotal($orderProduct),
$this->getTotalWithTax($orderProduct),
$this->getTotalWithTax($orderProduct, $round),
$orderProduct->getQuantityOrder(), $orderProduct->getQuantityOrder(),
null, null,
false
false,
$round
); );
} }


public function getTotalWithTax(OrderProductInterface $orderProduct)
public function getTotalWithTax(OrderProductInterface $orderProduct, $round = true)
{ {


return $this->applyTax( return $this->applyTax(
$this->getTotal($orderProduct), $this->getTotal($orderProduct),
$orderProduct->getTaxRate()->getValue()
$orderProduct->getTaxRate()->getValue(),
$round
); );
} }


public function getTotalWithTaxAndReduction(OrderProductInterface $orderProduct)
public function getTotalWithTaxAndReduction(OrderProductInterface $orderProduct, bool $round = true)
{ {
return $this->applyReductionCatalog( return $this->applyReductionCatalog(
$orderProduct, $orderProduct,
$this->getTotal($orderProduct), $this->getTotal($orderProduct),
$this->getTotalWithTax($orderProduct),
$orderProduct->getQuantityOrder()
$this->getTotalWithTax($orderProduct, $round),
$orderProduct->getQuantityOrder(),
null,
true,
$round
); );
} }



+ 2
- 1
Solver/Price/OrderShopPriceSolver.php View File



$total = 0; $total = 0;
foreach ($orderShop->getOrderProducts() as $orderProduct) { foreach ($orderShop->getOrderProducts() as $orderProduct) {
$total += $this->orderProductPriceResolver->getTotalWithReduction($orderProduct);
$total += $this->orderProductPriceResolver->getTotalWithReduction($orderProduct, false);
} }
return $this->round($total); return $this->round($total);
} }
{ {
$total = 0; $total = 0;
foreach ($orderProducts as $orderProduct) { foreach ($orderProducts as $orderProduct) {
//TODO : ici c'est pas possibble d'arrondir sinon ça fou une merde du tonnerre de de dieu !!!!
$total += $this->orderProductPriceResolver->getTotalWithTaxAndReduction($orderProduct); $total += $this->orderProductPriceResolver->getTotalWithTaxAndReduction($orderProduct);
} }



+ 8
- 2
Solver/Price/PriceSolverTrait.php View File



trait PriceSolverTrait trait PriceSolverTrait
{ {
public function applyTax($price, $taxRateValue)
public function applyTax($price, $taxRateValue, $round = true)
{ {
return $this->round($this->applyPercent($price, $taxRateValue));
$price = $this->applyPercent($price, $taxRateValue);

if($round) {
return $this->round($price);
}

return $price;
} }


public function applyReductionPercent($price, $percentage) public function applyReductionPercent($price, $percentage)

+ 26
- 17
Solver/Price/ProductPriceSolver.php View File



public function getSolver(ProductPropertyInterface $product) public function getSolver(ProductPropertyInterface $product)
{ {
if($product instanceof ProductFamilyInterface) {
if ($product instanceof ProductFamilyInterface) {
return $this->productFamilySolver; return $this->productFamilySolver;
} }


if($product instanceof ProductInterface) {
if ($product instanceof ProductInterface) {
return $this->productSolver; return $this->productSolver;
} }
} }
return $solver->getPriceInherited($product); return $solver->getPriceInherited($product);
} elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') { } elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') {
if ($solver->getQuantityInherited($product) > 0) { if ($solver->getQuantityInherited($product) > 0) {
return $solver->getPriceByRefUnitInherited($product) * ($solver->getQuantityInherited($product
return $solver->getPriceByRefUnitInherited($product) * ($solver->getQuantityInherited(
$product
) / $solver->getUnitInherited($product)->getCoefficient()); ) / $solver->getUnitInherited($product)->getCoefficient());
} else { } else {
return 0; return 0;
); );
} }



public function getPriceByRefUnit(ProductPropertyInterface $product) public function getPriceByRefUnit(ProductPropertyInterface $product)
{ {
$solver = $this->getSolver($product); $solver = $this->getSolver($product);
); );
} }



public function getPriceWithTaxAndReduction(ProductPropertyInterface $product) public function getPriceWithTaxAndReduction(ProductPropertyInterface $product)
{ {
//TODO voir différence entre prix ici et dans tableau décli
return $this->applyReductionCatalog( return $this->applyReductionCatalog(
$product, $product,
$this->getPrice($product), $this->getPrice($product),
} }


//Bridge pour applyReductionCatalog qui ne peut pas être appeler à cause du call //Bridge pour applyReductionCatalog qui ne peut pas être appeler à cause du call
public function getPriceWithTaxByReduction(ProductPropertyInterface $product, ReductionCatalogInterface $reductionCatalog)
{
public function getPriceWithTaxByReduction(
ProductPropertyInterface $product,
ReductionCatalogInterface $reductionCatalog
) {
return $this->applyReductionCatalog( return $this->applyReductionCatalog(
$product,
$this->getPrice($product),
$this->getPriceWithTax($product),
1,
$reductionCatalog
$product,
$this->getPrice($product),
$this->getPriceWithTax($product),
1,
$reductionCatalog
); );
} }


public function getPriceByRefUnitWithTaxAndReduction(ProductPropertyInterface $product) public function getPriceByRefUnitWithTaxAndReduction(ProductPropertyInterface $product)
{ {
return ($this->getPriceByRefUnitWithTax($product) * $this->getPriceWithTaxAndReduction($product))
/ $this->getPriceWithTax($product);
}
$priceWithTax = $this->getPriceWithTax($product);


if ($priceWithTax) {
return $this->round(
($this->getPriceByRefUnitWithTax($product) * $this->getPriceWithTaxAndReduction($product))
/ $priceWithTax
);
}

return 0;
}


public function getBuyingPrice(ProductPropertyInterface $product) public function getBuyingPrice(ProductPropertyInterface $product)
{ {
return $solver->getBuyingPriceInherited($product); return $solver->getBuyingPriceInherited($product);
} elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') { } elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') {
if ($solver->getQuantityInherited($product) > 0) { if ($solver->getQuantityInherited($product) > 0) {
return $solver->getBuyingPriceByRefUnitInherited($product) * ($solver->getQuantityInherited($product
return $solver->getBuyingPriceByRefUnitInherited($product) * ($solver->getQuantityInherited(
$product
) / $solver->getUnitInherited($product)->getCoefficient()); ) / $solver->getUnitInherited($product)->getCoefficient());
} else { } else {
return 0; return 0;
{ {
return $this->round($this->getPriceWithTax($product) / $this->getBuyingPrice($product)); return $this->round($this->getPriceWithTax($product) / $this->getBuyingPrice($product));
} }

} }



+ 39
- 14
Solver/Product/ProductFamilySolver.php View File

use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface; use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
use Lc\CaracoleBundle\Model\Product\ProductFamilySectionPropertyInterface;
use Lc\CaracoleBundle\Model\Product\ProductInterface; use Lc\CaracoleBundle\Model\Product\ProductInterface;
use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface; use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
use Lc\CaracoleBundle\Model\Section\SectionInterface; use Lc\CaracoleBundle\Model\Section\SectionInterface;
protected ProductFamilySectionPropertySolver $productFamilySectionPropertySolver; protected ProductFamilySectionPropertySolver $productFamilySectionPropertySolver;
protected ProductCategorySolver $productCategorySolver; protected ProductCategorySolver $productCategorySolver;


public function __construct(ProductSolver $productSolver, ProductFamilySectionPropertySolver $productFamilySectionPropertySolver, ProductCategorySolver $productCategorySolver)
{
public function __construct(
ProductSolver $productSolver,
ProductFamilySectionPropertySolver $productFamilySectionPropertySolver,
ProductCategorySolver $productCategorySolver
) {
$this->productSolver = $productSolver; $this->productSolver = $productSolver;
$this->productFamilySectionPropertySolver = $productFamilySectionPropertySolver; $this->productFamilySectionPropertySolver = $productFamilySectionPropertySolver;
$this->productCategorySolver = $productCategorySolver; $this->productCategorySolver = $productCategorySolver;
]; ];
} }



public function countProductFamiliesOrganizedByParentCategory(array $categories): int public function countProductFamiliesOrganizedByParentCategory(array $categories): int
{ {
$count = 0; $count = 0;
$productCategories = $productFamily->getProductCategories(); $productCategories = $productFamily->getProductCategories();


if (count($productCategories) > 0) { if (count($productCategories) > 0) {

foreach ($productCategories as $productCategory) { foreach ($productCategories as $productCategory) {
if($productCategory->getSection()->getId() == $section->getId()
if ($productCategory->getSection()->getId() == $section->getId()
&& $productCategory->getParent() !== null) { && $productCategory->getParent() !== null) {

return $productCategory->getParent(); return $productCategory->getParent();
} }
} }


public function getQuantityInherited(ProductFamilyInterface $productFamily): ?float public function getQuantityInherited(ProductFamilyInterface $productFamily): ?float
{ {
if($productFamily->getQuantity()){
if ($productFamily->getQuantity()) {
return $productFamily->getQuantity(); return $productFamily->getQuantity();
}else{
} else {
return 1; return 1;
} }
} }
$strLabels = ''; $strLabels = '';
$qualityLabelArray = $productFamily->getQualityLabels()->toArray(); $qualityLabelArray = $productFamily->getQualityLabels()->toArray();


foreach($qualityLabelArray as $index => $qualityLabel) {
foreach ($qualityLabelArray as $index => $qualityLabel) {
$strLabels .= $qualityLabel->getTitle(); $strLabels .= $qualityLabel->getTitle();


if ($index !== array_key_last($qualityLabelArray)) { if ($index !== array_key_last($qualityLabelArray)) {
} }




public function isCategoriesOnlineInSection(ProductFamilyInterface $productFamily, SectionInterface $section):bool
public function isCategoriesOnlineInSection(ProductFamilyInterface $productFamily, SectionInterface $section): bool
{ {
$isCategoriesOnlineInSection =false;
foreach ($productFamily->getProductCategories() as $productCatgory){
if($productCatgory->getSection() === $section && $this->productCategorySolver->isOnline($productCatgory)){
$isCategoriesOnlineInSection = false;
foreach ($productFamily->getProductCategories() as $productCatgory) {
if ($productCatgory->getSection() === $section && $this->productCategorySolver->isOnline($productCatgory)) {
$isCategoriesOnlineInSection = true; $isCategoriesOnlineInSection = true;
} }
} }
return $isCategoriesOnlineInSection; return $isCategoriesOnlineInSection;
} }

public function getTitleProduct(ProductInterface $product)
{
$productFamily = $product->getProductFamily();
$title = $product->getProductFamily()->getTitle();

if ($product->getTitle() && strlen($product->getTitle())) {
$title .= ' - ' . $product->getTitle();
}

if ($this->hasProductsWithVariousWeight($productFamily)) {
$title .= ' - ' . $this->productSolver->getQuantityLabelInherited($product);
}

return $title;
}

public function isReductionCatalogDisplayed(ProductFamilyInterface $productFamily): bool
{
return $this->hasReductionCatalog($productFamily) && $productFamily->getReductionCatalog()->isDisplayed();
}

public function hasReductionCatalog(ProductFamilyInterface $productFamily): bool
{
return (bool)$productFamily->getReductionCatalog();
}
} }



+ 10
- 12
Solver/Product/ProductSolver.php View File

} }


$allCategoriesSalesOff = true; $allCategoriesSalesOff = true;
$unavailableSpecificDay = false;


foreach ($product->getProductFamily()->getProductCategories() as $category) { foreach ($product->getProductFamily()->getProductCategories() as $category) {
if ($category->getParent()) { if ($category->getParent()) {
$allCategoriesSalesOff = false; $allCategoriesSalesOff = false;
} }
} }

// specific day
// @TODO : spécifique pdl ?
$displaySpecificDay = $category->getDisplaySpecificDay();
if ($displaySpecificDay && $displaySpecificDay != date('N')) {
$unavailableSpecificDay = true;
}
} }


if ($allCategoriesSalesOff) { if ($allCategoriesSalesOff) {
return false; return false;
} }


if ($unavailableSpecificDay) {
return false;
}

return true; return true;
} }


} }
} }


public function getFullTitle(ProductInterface $product)
{
if ($product->getTitle()) {
$endOfTitle = $product->getTitle();
} else {
$endOfTitle = $this->getQuantityInherited($product).' '.$this->getUnitInherited($product)->getWordingShort();
}
return $product->getProductFamily()->getTitle(). ' - '. $endOfTitle;
}

public function getQuantityInherited(ProductInterface $product) public function getQuantityInherited(ProductInterface $product)
{ {
if ($product->getQuantity()) { if ($product->getQuantity()) {

+ 1
- 1
Solver/Ticket/TicketSolver.php View File

{ {
public function getTypeChoices($context = 'backend'): array public function getTypeChoices($context = 'backend'): array
{ {
$choices = parent::getTypeChoices();
$choices = parent::getTypeChoices($context);
$choicesProduct = [ $choicesProduct = [
TicketModel::TYPE_PRODUCT_UNAVAILABLE, TicketModel::TYPE_PRODUCT_UNAVAILABLE,
TicketModel::TYPE_PRODUCT_ERROR TicketModel::TYPE_PRODUCT_ERROR

+ 12
- 8
Statistic/Product/ProductsSalesStatistic.php View File

'label' => 'Total ventes' 'label' => 'Total ventes'
] ]
); );

foreach ($this->productFamily->getProducts() as $product) { foreach ($this->productFamily->getProducts() as $product) {
$this->productIds[$product->getId()] = $product;
$this->addProperty(
$product->getId(),
[
'label' => $product->getTitle()
]
);
if($product->getId()) {
$this->productIds[$product->getId()] = $product;
$this->addProperty(
$product->getId(),
[
'label' => $product->getTitle()
]
);
}
} }
} }


{ {
$countsOrderedByCyclesAndProducts = $orderShopStore->countValidOrderProductsOfDistributionsByProducts( $countsOrderedByCyclesAndProducts = $orderShopStore->countValidOrderProductsOfDistributionsByProducts(
$this->distributionList, $this->distributionList,
$this->productIds
$this->productIds,
$this->productFamily
); );


foreach ($countsOrderedByCyclesAndProducts as $result) { foreach ($countsOrderedByCyclesAndProducts as $result) {

Loading…
Cancel
Save