@@ -3,9 +3,12 @@ | |||
namespace Lc\CaracoleBundle\Builder\Order; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Factory\Order\OrderProductReductionCatalogFactory; | |||
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\Resolver\Price\PriceResolver; | |||
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore; | |||
use Lc\CaracoleBundle\Solver\Order\OrderProductSolver; | |||
use Lc\CaracoleBundle\Solver\Price\PriceSolver; | |||
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver; | |||
@@ -19,6 +22,8 @@ class OrderProductBuilder | |||
protected ProductSolver $productSolver; | |||
protected ProductFamilySolver $productFamilySolver; | |||
protected OrderProductSolver $orderProductSolver; | |||
protected OrderProductReductionCatalogFactory $orderProductReductionCatalogFactory; | |||
protected ProductFamilyStore $productFamilyStore; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
@@ -26,7 +31,9 @@ class OrderProductBuilder | |||
OrderProductStore $orderProductStore, | |||
ProductSolver $productSolver, | |||
OrderProductSolver $orderProductSolver, | |||
ProductFamilySolver $productFamilySolver | |||
ProductFamilySolver $productFamilySolver, | |||
OrderProductReductionCatalogFactory $orderProductReductionCatalogFactory, | |||
ProductFamilyStore $productFamilyStore | |||
) { | |||
$this->entityManager = $entityManager; | |||
$this->priceSolver = $priceSolver; | |||
@@ -34,6 +41,8 @@ class OrderProductBuilder | |||
$this->productSolver = $productSolver; | |||
$this->orderProductSolver = $orderProductSolver; | |||
$this->productFamilySolver = $productFamilySolver; | |||
$this->orderProductReductionCatalogFactory = $orderProductReductionCatalogFactory; | |||
$this->productFamilyStore = $productFamilyStore; | |||
} | |||
public function init(OrderProductInterface $orderProduct) :OrderProductInterface | |||
@@ -47,4 +56,24 @@ class OrderProductBuilder | |||
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; | |||
} | |||
} |
@@ -29,6 +29,7 @@ use Lc\CaracoleBundle\Model\Order\OrderStatusInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; | |||
use Lc\CaracoleBundle\Model\Product\ProductInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
@@ -38,15 +39,15 @@ use Lc\CaracoleBundle\Repository\Order\OrderShopStore; | |||
use Lc\CaracoleBundle\Repository\Order\OrderStatusStore; | |||
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore; | |||
use Lc\CaracoleBundle\Resolver\MerchantResolver; | |||
use Lc\CaracoleBundle\Resolver\OpeningResolver; | |||
use Lc\CaracoleBundle\Resolver\OrderShopResolver; | |||
use Lc\CaracoleBundle\Solver\Order\OrderProductReductionCatalogSolver; | |||
use Lc\CaracoleBundle\Solver\Order\OrderProductSolver; | |||
use Lc\CaracoleBundle\Solver\Order\OrderShopSolver; | |||
use Lc\CaracoleBundle\Solver\Price\PriceSolver; | |||
use Lc\CaracoleBundle\Solver\Product\ProductSolver; | |||
use Lc\CaracoleBundle\Statistic\Product\ProductsSalesStatistic; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\SovBundle\Translation\FlashBagTranslator; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; | |||
@@ -63,15 +64,14 @@ class OrderShopBuilder | |||
protected DocumentBuilder $documentBuilder; | |||
protected EventDispatcherInterface $eventDispatcher; | |||
protected FlashBagInterface $flashBag; | |||
protected OpeningResolver $openingResolver; | |||
protected ProductSolver $productSolver; | |||
protected OrderShopResolver $orderShopResolver; | |||
protected OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver; | |||
protected DistributionBuilder $distributionBuilder; | |||
protected MerchantResolver $merchantResolver; | |||
protected CreditHistoryBuilder $creditHistoryBuilder; | |||
protected FlashBagTranslator $flashBagTranslator; | |||
protected OrderShopFactory $orderShopFactory; | |||
protected OrderProductSolver $orderProductSolver; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
@@ -85,15 +85,14 @@ class OrderShopBuilder | |||
PriceSolver $priceSolver, | |||
EventDispatcherInterface $eventDispatcher, | |||
FlashBagInterface $flashBag, | |||
OpeningResolver $openingResolver, | |||
ProductSolver $productSolver, | |||
OrderShopResolver $orderShopResolver, | |||
OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver, | |||
DistributionBuilder $distributionBuilder, | |||
MerchantResolver $merchantResolver, | |||
CreditHistoryBuilder $creditHistoryBuilder, | |||
FlashBagTranslator $flashBagTranslator, | |||
OrderShopFactory $orderShopFactory | |||
OrderShopFactory $orderShopFactory, | |||
OrderProductSolver $orderProductSolver | |||
) { | |||
$this->entityManager = $entityManager; | |||
$this->orderShopStore = $orderShopStore; | |||
@@ -106,15 +105,14 @@ class OrderShopBuilder | |||
$this->priceSolver = $priceSolver; | |||
$this->eventDispatcher = $eventDispatcher; | |||
$this->flashBag = $flashBag; | |||
$this->openingResolver = $openingResolver; | |||
$this->productSolver = $productSolver; | |||
$this->orderShopResolver = $orderShopResolver; | |||
$this->orderProductReductionCatalogSolver = $orderProductReductionCatalogSolver; | |||
$this->distributionBuilder = $distributionBuilder; | |||
$this->merchantResolver = $merchantResolver; | |||
$this->creditHistoryBuilder = $creditHistoryBuilder; | |||
$this->flashBagTranslator = $flashBagTranslator; | |||
$this->orderShopFactory = $orderShopFactory; | |||
$this->orderProductSolver = $orderProductSolver; | |||
} | |||
public function create( | |||
@@ -234,39 +232,26 @@ class OrderShopBuilder | |||
): bool { | |||
$return = false; | |||
$orderProductAdd->setOrderShop($orderShop); | |||
if ($this->orderShopSolver->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) { | |||
if ($orderProductAdd->getQuantityOrder() > 0) { | |||
$updated = false; | |||
$this->orderProductBuilder->init($orderProductAdd); | |||
$productFamily = $this->productFamilyStore->setSection($orderShop->getSection())->getOneBySlug( | |||
$orderProductAdd->getProduct()->getProductFamily()->getSlug() | |||
); | |||
if ($productFamily) { | |||
$reductionCatalog = $productFamily->getReductionCatalog(); | |||
if ($reductionCatalog && $reductionCatalog->getStatus()) { | |||
$orderProductReductionCatalogFactory = new OrderProductReductionCatalogFactory(); | |||
$orderProductReductionCatalog = $orderProductReductionCatalogFactory->create( | |||
$reductionCatalog->getTitle(), | |||
$reductionCatalog->getValue(), | |||
$reductionCatalog->getUnit(), | |||
$reductionCatalog->getBehaviorTaxRate() | |||
); | |||
$orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog); | |||
//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) { | |||
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->getQuantityOrder() + $orderProductAdd->getQuantityOrder() | |||
); | |||
@@ -336,38 +321,38 @@ class OrderShopBuilder | |||
OrderShopInterface $orderShop2, | |||
$persist = true | |||
): 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($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) { | |||
$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 | |||
@@ -498,23 +483,25 @@ class OrderShopBuilder | |||
public function deductAvailabilityProduct(OrderShopInterface $orderShop): void | |||
{ | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$this->applyDeductAvailabilityProduct($orderShop, $orderProduct); | |||
$this->applyDeductAvailabilityProduct($orderShop, $orderProduct->getProduct(), $orderProduct->getQuantityOrder()); | |||
} | |||
} | |||
public function applyDeductAvailabilityProduct( | |||
OrderShopInterface $orderShop, | |||
OrderProductInterface $orderProduct | |||
ProductInterface $product, | |||
int $quantityOrder | |||
): void { | |||
switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) { | |||
switch ($product->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())); | |||
$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->setUpdatedBy($orderShop->getUser()); | |||
@@ -523,10 +510,10 @@ class OrderShopBuilder | |||
break; | |||
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->setUpdatedBy($orderShop->getUser()); | |||
@@ -534,10 +521,9 @@ class OrderShopBuilder | |||
break; | |||
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->setUpdatedBy($orderShop->getUser()); | |||
@@ -545,54 +531,39 @@ class OrderShopBuilder | |||
break; | |||
} | |||
$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; | |||
} | |||
@@ -7,6 +7,7 @@ use Lc\CaracoleBundle\Definition\Field\Reduction\ReductionCatalogFieldDefinition | |||
use Lc\CaracoleBundle\Factory\Reduction\ReductionCatalogFactory; | |||
use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogRepositoryQuery; | |||
use Lc\CaracoleBundle\Repository\Reduction\ReductionCatalogStore; | |||
use Lc\CaracoleBundle\Solver\Reduction\ReductionCatalogSolver; | |||
class ReductionCatalogContainer | |||
{ | |||
@@ -27,7 +28,6 @@ class ReductionCatalogContainer | |||
$this->fieldDefinition = $fieldDefinition; | |||
} | |||
public static function getEntityFqcn() | |||
{ | |||
return ReductionCatalog::class; | |||
@@ -55,4 +55,9 @@ class ReductionCatalogContainer | |||
return $this->fieldDefinition; | |||
} | |||
// public function getSolver(): ReductionCatalogSolver | |||
// { | |||
// return $this->solver; | |||
// } | |||
} |
@@ -5,6 +5,7 @@ namespace Lc\CaracoleBundle\Controller\Order; | |||
use Lc\CaracoleBundle\Controller\AbstractController; | |||
use Lc\CaracoleBundle\Form\Order\OrderProductsType; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
use Symfony\Component\HttpFoundation\JsonResponse; | |||
use Symfony\Component\HttpFoundation\RedirectResponse; | |||
@@ -17,6 +18,7 @@ use Symfony\Component\Routing\Annotation\Route; | |||
class CartController extends AbstractController | |||
{ | |||
protected ProductFamilyInterface $productFamily; | |||
protected int $quantityOrder = 1; | |||
protected array $orderProducts = []; | |||
public function addProductFamily(Request $request): JsonResponse | |||
@@ -63,15 +65,7 @@ class CartController extends AbstractController | |||
$data = $form->getData(); | |||
foreach ($data as $orderProduct) { | |||
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); | |||
} | |||
} | |||
} | |||
@@ -81,6 +75,19 @@ class CartController extends AbstractController | |||
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") | |||
*/ |
@@ -51,22 +51,4 @@ abstract class ProductFamilyAdminController extends AbstractAdminController | |||
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)); | |||
} | |||
} |
@@ -2,26 +2,175 @@ | |||
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 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; | |||
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); | |||
$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 | |||
{ | |||
$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 [ | |||
'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) | |||
]; | |||
} | |||
} |
@@ -1,64 +0,0 @@ | |||
<?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); | |||
} | |||
} | |||
}*/ | |||
} | |||
} |
@@ -2,31 +2,29 @@ | |||
namespace Lc\CaracoleBundle\EventSubscriber\Product; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent; | |||
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\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; | |||
class UpdateProductfamilyAfterFlushEventSubscriber implements EventSubscriberInterface | |||
{ | |||
protected EntityManagerInterface $em; | |||
protected ProductFamilyContainer $productFamilyContainer; | |||
protected ProductContainer $productContainer; | |||
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->openingResolver = $openingResolver; | |||
$this->flashBagTranslator = $flashBagTranslator; | |||
} | |||
public static function getSubscribedEvents() | |||
@@ -38,9 +36,33 @@ class UpdateProductfamilyAfterFlushEventSubscriber implements EventSubscriberInt | |||
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() | |||
) | |||
); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -80,67 +80,49 @@ class UpdateProductfamilyEventSubscriber implements EventSubscriberInterface | |||
protected function processProducts($entity) | |||
{ | |||
if($entity->getId()) { | |||
if ($entity->getId()) { | |||
//Récupère le product origin | |||
$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 { | |||
$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); | |||
} | |||
} | |||
}*/ | |||
} | |||
} |
@@ -16,6 +16,7 @@ class ReductionCatalogFactory extends AbstractFactory | |||
$class = ReductionCatalogContainer::getEntityFqcn(); | |||
$reductionCatalog = new $class; | |||
$reductionCatalog->setIsDisplayed(true); | |||
$reductionCatalog->setMerchant($merchant); | |||
$reductionCatalog->setStatus($status); | |||
@@ -250,7 +250,7 @@ abstract class ProductFamilyModel extends AbstractFullEntity implements ProductP | |||
protected $image; | |||
/** | |||
* @ORM\ManyToMany(targetEntity="Lc\CaracoleBundle\Model\Product\QualityLabelInterface", fetch="EAGER") | |||
* @ORM\ManyToMany(targetEntity="Lc\CaracoleBundle\Model\Product\QualityLabelInterface", fetch="LAZY") | |||
*/ | |||
protected $qualityLabels; | |||
@@ -56,6 +56,11 @@ abstract class ReductionCatalogModel extends AbstractLightEntity implements Redu | |||
*/ | |||
protected $productCategories; | |||
/** | |||
* @ORM\Column(type="boolean", nullable=false) | |||
*/ | |||
protected $isDisplayed; | |||
public function __construct() | |||
{ | |||
$this->__reductionPropertyConstruct(); | |||
@@ -151,4 +156,22 @@ abstract class ReductionCatalogModel extends AbstractLightEntity implements Redu | |||
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; | |||
} | |||
} |
@@ -53,7 +53,7 @@ trait MerchantStoreTrait | |||
public function addFilterByMerchantViaSectionRequired(RepositoryQueryInterface $query): StoreInterface | |||
{ | |||
$this->addFilterByMerchantOptionnal($query); | |||
$this->addFilterByMerchantViaSectionOptionnal($query); | |||
if(!$this->isMerchantDefined()) { | |||
throw new \ErrorException('Le Merchant doit être définie dans '.get_class($this)); |
@@ -57,6 +57,7 @@ class OrderShopRepositoryQuery extends AbstractRepositoryQuery | |||
); | |||
} | |||
public function selectSum(): self | |||
{ | |||
$this->joinProduct(); |
@@ -10,6 +10,7 @@ use Lc\CaracoleBundle\Builder\File\DocumentBuilder; | |||
use Lc\CaracoleBundle\Model\Distribution\DistributionInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface; | |||
@@ -590,6 +591,7 @@ class OrderShopStore extends AbstractStore | |||
public function countValidOrderProductsOfDistributionsByProducts( | |||
array $distributions, | |||
array $products, | |||
ProductFamilyInterface $productFamily, | |||
$query = null | |||
): array { | |||
$query = $this->createDefaultQuery($query); | |||
@@ -600,6 +602,7 @@ class OrderShopStore extends AbstractStore | |||
->selectSum() | |||
->groupBy('distribution.cycleNumber, product.id'); | |||
//TODO vérifier ou est utilisé cette fonction ??? | |||
return $query->find(); | |||
} | |||
@@ -609,7 +612,7 @@ class OrderShopStore extends AbstractStore | |||
DistributionInterface $distribution, | |||
ProductInterface $product, | |||
$query = null | |||
): ?string { | |||
): float { | |||
//TODO attention à vérifier | |||
$query = $this->createQuery($query); | |||
@@ -626,7 +629,7 @@ class OrderShopStore extends AbstractStore | |||
if ($result) { | |||
return $result['quantity']; | |||
} | |||
return null; | |||
return 0; | |||
} | |||
public function isReductionCreditAllowAddToOrder( |
@@ -20,8 +20,10 @@ class ProductFamilyStore extends AbstractStore | |||
protected ProductFamilyRepositoryQuery $query; | |||
protected PriceSolver $priceSolver; | |||
public function __construct(ProductFamilyRepositoryQuery $query, PriceSolver $priceSolver) | |||
{ | |||
public function __construct( | |||
ProductFamilyRepositoryQuery $query, | |||
PriceSolver $priceSolver | |||
) { | |||
$this->query = $query; | |||
$this->priceSolver = $priceSolver; | |||
} | |||
@@ -50,6 +52,22 @@ class ProductFamilyStore extends AbstractStore | |||
return $query; | |||
} | |||
public function isReductionCatalogDisplayed(ProductFamilyInterface $productFamily): bool | |||
{ | |||
$reductionCatalog = $this->reductionCatalogStore->setMerchant($this->merchant) | |||
->getByProductFamily($productFamily); | |||
return $this->hasReductionCatalog($productFamily) && $reductionCatalog->isDisplayed(); | |||
} | |||
public function hasReductionCatalog(ProductFamilyInterface $productFamily): bool | |||
{ | |||
$reductionCatalog = $this->reductionCatalogStore->setMerchant($this->merchant) | |||
->getByProductFamily($productFamily); | |||
return (bool)$reductionCatalog; | |||
} | |||
public function getByParentCategory( | |||
ProductCategoryInterface $parentCategory, | |||
$user = null, |
@@ -12,32 +12,34 @@ use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
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) | |||
{ | |||
parent::__construct($repository, 'product', $paginator); | |||
} | |||
public function orderByDefault(): \Lc\SovBundle\Repository\AbstractRepositoryQuery | |||
{ | |||
return $this->orderBy('position', 'ASC'); | |||
} | |||
public function joinProductFamily():self | |||
public function joinProductFamily(): self | |||
{ | |||
if (!$this->isJoinProductFamily) { | |||
$this->isJoinProductFamily = true; | |||
return $this | |||
->innerJoin('.productFamily', 'productFamily') | |||
->addSelect('productFamily'); | |||
->innerJoin('.productFamily', 'productFamily') | |||
->addSelect('productFamily'); | |||
} | |||
return $this; | |||
} | |||
public function filterBySection(SectionInterface $section):self | |||
public function filterBySection(SectionInterface $section): self | |||
{ | |||
$this->joinProductFamilySectionProperties(false); | |||
$this->andWhereSection('productFamilySectionProperties', $section); | |||
@@ -86,7 +88,7 @@ class ProductRepositoryQuery extends AbstractRepositoryQuery | |||
} | |||
public function filterIsOnline():self | |||
public function filterIsOnline(): self | |||
{ | |||
$this->joinProductFamily(); | |||
$this->andWhereStatus('productFamily', 1); | |||
@@ -94,8 +96,24 @@ class ProductRepositoryQuery extends AbstractRepositoryQuery | |||
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'); | |||
return $this; | |||
@@ -108,61 +126,61 @@ class ProductRepositoryQuery extends AbstractRepositoryQuery | |||
} | |||
public function filterIsNotAvailableQuantitySupplierUnlimited():self | |||
public function filterIsNotAvailableQuantitySupplierUnlimited(): self | |||
{ | |||
$this->andWhere('productFamily.availableQuantitySupplierUnlimited != 1'); | |||
return $this; | |||
} | |||
public function filterAvailableQuantityNegative() :self | |||
public function filterAvailableQuantityNegative(): self | |||
{ | |||
$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( | |||
'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('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT); | |||
return $this; | |||
} | |||
public function filterAvailableQuantitySupplierNegative() :self | |||
public function filterAvailableQuantitySupplierNegative(): self | |||
{ | |||
$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( | |||
'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('behaviorCountStockByProduct', ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT); |
@@ -15,4 +15,6 @@ trait StoreTrait | |||
} | |||
return $this; | |||
} | |||
} |
@@ -1,7 +0,0 @@ | |||
{# @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 %} |
@@ -1,28 +1,4 @@ | |||
{% 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) %} | |||
<tr> |
@@ -1,94 +0,0 @@ | |||
{% 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 %} | |||
@@ -12,11 +12,11 @@ class OrderProductReductionCatalogSolver | |||
$text = ''; | |||
if ($orderProductReductionCatalog->getUnit() == 'amount') { | |||
$text .= '- ' . $orderProductReductionCatalog->getValue() . ' €'; | |||
$text .= '- ' . number_format($orderProductReductionCatalog->getValue(),2) . ' €'; | |||
} | |||
if ($orderProductReductionCatalog->getUnit() == 'percent') { | |||
$text .= '- ' . $orderProductReductionCatalog->getValue() . ' %'; | |||
$text .= '- ' . number_format($orderProductReductionCatalog->getValue(),2) . ' %'; | |||
} | |||
return $text; |
@@ -4,6 +4,7 @@ namespace Lc\CaracoleBundle\Solver\Order; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Solver\Price\PriceSolver; | |||
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver; | |||
use Lc\CaracoleBundle\Solver\Product\ProductSolver; | |||
@@ -11,11 +12,31 @@ class OrderProductSolver | |||
{ | |||
protected ProductSolver $productSolver; | |||
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->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 | |||
@@ -113,10 +134,16 @@ class OrderProductSolver | |||
// 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); | |||
} | |||
} | |||
} | |||
} |
@@ -42,6 +42,11 @@ class OrderShopSolver | |||
]; | |||
} | |||
public function isEmpty(OrderShopInterface $orderShop): bool | |||
{ | |||
return $orderShop->getOrderProducts()->isEmpty(); | |||
} | |||
public function countQuantities(OrderShopInterface $orderShop): int | |||
{ | |||
return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts()); | |||
@@ -131,6 +136,7 @@ class OrderShopSolver | |||
return false; | |||
} | |||
$productFamily = $product->getProductFamily(); | |||
$quantityAsked = $quantityOrder; | |||
@@ -172,7 +178,6 @@ class OrderShopSolver | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
@@ -102,34 +102,39 @@ class OrderProductPriceSolver | |||
} | |||
public function getTotalWithReduction(OrderProductInterface $orderProduct) | |||
public function getTotalWithReduction(OrderProductInterface $orderProduct, bool $round = true) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$orderProduct, | |||
$this->getTotal($orderProduct), | |||
$this->getTotalWithTax($orderProduct), | |||
$this->getTotalWithTax($orderProduct, $round), | |||
$orderProduct->getQuantityOrder(), | |||
null, | |||
false | |||
false, | |||
$round | |||
); | |||
} | |||
public function getTotalWithTax(OrderProductInterface $orderProduct) | |||
public function getTotalWithTax(OrderProductInterface $orderProduct, $round = true) | |||
{ | |||
return $this->applyTax( | |||
$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( | |||
$orderProduct, | |||
$this->getTotal($orderProduct), | |||
$this->getTotalWithTax($orderProduct), | |||
$orderProduct->getQuantityOrder() | |||
$this->getTotalWithTax($orderProduct, $round), | |||
$orderProduct->getQuantityOrder(), | |||
null, | |||
true, | |||
$round | |||
); | |||
} | |||
@@ -34,7 +34,7 @@ class OrderShopPriceSolver | |||
$total = 0; | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalWithReduction($orderProduct); | |||
$total += $this->orderProductPriceResolver->getTotalWithReduction($orderProduct, false); | |||
} | |||
return $this->round($total); | |||
} | |||
@@ -145,7 +145,7 @@ class OrderShopPriceSolver | |||
{ | |||
$total = 0; | |||
foreach ($orderProducts as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalWithTaxAndReduction($orderProduct); | |||
$total += $this->orderProductPriceResolver->getTotalWithTaxAndReduction($orderProduct, false); | |||
} | |||
return $this->round($total); |
@@ -9,9 +9,15 @@ use Lc\CaracoleBundle\Model\Product\ProductInterface; | |||
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) |
@@ -24,11 +24,11 @@ class ProductPriceSolver | |||
public function getSolver(ProductPropertyInterface $product) | |||
{ | |||
if($product instanceof ProductFamilyInterface) { | |||
if ($product instanceof ProductFamilyInterface) { | |||
return $this->productFamilySolver; | |||
} | |||
if($product instanceof ProductInterface) { | |||
if ($product instanceof ProductInterface) { | |||
return $this->productSolver; | |||
} | |||
} | |||
@@ -41,7 +41,8 @@ class ProductPriceSolver | |||
return $solver->getPriceInherited($product); | |||
} elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') { | |||
if ($solver->getQuantityInherited($product) > 0) { | |||
return $solver->getPriceByRefUnitInherited($product) * ($solver->getQuantityInherited($product | |||
return $solver->getPriceByRefUnitInherited($product) * ($solver->getQuantityInherited( | |||
$product | |||
) / $solver->getUnitInherited($product)->getCoefficient()); | |||
} else { | |||
return 0; | |||
@@ -57,7 +58,6 @@ class ProductPriceSolver | |||
); | |||
} | |||
public function getPriceByRefUnit(ProductPropertyInterface $product) | |||
{ | |||
$solver = $this->getSolver($product); | |||
@@ -78,9 +78,9 @@ class ProductPriceSolver | |||
); | |||
} | |||
public function getPriceWithTaxAndReduction(ProductPropertyInterface $product) | |||
{ | |||
//TODO voir différence entre prix ici et dans tableau décli | |||
return $this->applyReductionCatalog( | |||
$product, | |||
$this->getPrice($product), | |||
@@ -89,23 +89,32 @@ class ProductPriceSolver | |||
} | |||
//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( | |||
$product, | |||
$this->getPrice($product), | |||
$this->getPriceWithTax($product), | |||
1, | |||
$reductionCatalog | |||
$product, | |||
$this->getPrice($product), | |||
$this->getPriceWithTax($product), | |||
1, | |||
$reductionCatalog | |||
); | |||
} | |||
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) | |||
{ | |||
@@ -115,7 +124,8 @@ class ProductPriceSolver | |||
return $solver->getBuyingPriceInherited($product); | |||
} elseif ($solver->getBehaviorPriceInherited($product) == 'by-reference-unit') { | |||
if ($solver->getQuantityInherited($product) > 0) { | |||
return $solver->getBuyingPriceByRefUnitInherited($product) * ($solver->getQuantityInherited($product | |||
return $solver->getBuyingPriceByRefUnitInherited($product) * ($solver->getQuantityInherited( | |||
$product | |||
) / $solver->getUnitInherited($product)->getCoefficient()); | |||
} else { | |||
return 0; | |||
@@ -148,6 +158,5 @@ class ProductPriceSolver | |||
{ | |||
return $this->round($this->getPriceWithTax($product) / $this->getBuyingPrice($product)); | |||
} | |||
} | |||
@@ -7,7 +7,6 @@ use Doctrine\Common\Collections\Collection; | |||
use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilySectionPropertyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
@@ -18,8 +17,11 @@ class ProductFamilySolver | |||
protected ProductFamilySectionPropertySolver $productFamilySectionPropertySolver; | |||
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->productFamilySectionPropertySolver = $productFamilySectionPropertySolver; | |||
$this->productCategorySolver = $productCategorySolver; | |||
@@ -87,7 +89,6 @@ class ProductFamilySolver | |||
]; | |||
} | |||
public function countProductFamiliesOrganizedByParentCategory(array $categories): int | |||
{ | |||
$count = 0; | |||
@@ -178,11 +179,9 @@ class ProductFamilySolver | |||
$productCategories = $productFamily->getProductCategories(); | |||
if (count($productCategories) > 0) { | |||
foreach ($productCategories as $productCategory) { | |||
if($productCategory->getSection()->getId() == $section->getId() | |||
if ($productCategory->getSection()->getId() == $section->getId() | |||
&& $productCategory->getParent() !== null) { | |||
return $productCategory->getParent(); | |||
} | |||
} | |||
@@ -372,9 +371,9 @@ class ProductFamilySolver | |||
public function getQuantityInherited(ProductFamilyInterface $productFamily): ?float | |||
{ | |||
if($productFamily->getQuantity()){ | |||
if ($productFamily->getQuantity()) { | |||
return $productFamily->getQuantity(); | |||
}else{ | |||
} else { | |||
return 1; | |||
} | |||
} | |||
@@ -394,7 +393,7 @@ class ProductFamilySolver | |||
$strLabels = ''; | |||
$qualityLabelArray = $productFamily->getQualityLabels()->toArray(); | |||
foreach($qualityLabelArray as $index => $qualityLabel) { | |||
foreach ($qualityLabelArray as $index => $qualityLabel) { | |||
$strLabels .= $qualityLabel->getTitle(); | |||
if ($index !== array_key_last($qualityLabelArray)) { | |||
@@ -481,15 +480,31 @@ class ProductFamilySolver | |||
} | |||
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; | |||
} | |||
} | |||
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; | |||
} | |||
} | |||
@@ -18,7 +18,6 @@ class ProductSolver | |||
} | |||
$allCategoriesSalesOff = true; | |||
$unavailableSpecificDay = false; | |||
foreach ($product->getProductFamily()->getProductCategories() as $category) { | |||
if ($category->getParent()) { | |||
@@ -30,23 +29,12 @@ class ProductSolver | |||
$allCategoriesSalesOff = false; | |||
} | |||
} | |||
// specific day | |||
// @TODO : spécifique pdl ? | |||
$displaySpecificDay = $category->getDisplaySpecificDay(); | |||
if ($displaySpecificDay && $displaySpecificDay != date('N')) { | |||
$unavailableSpecificDay = true; | |||
} | |||
} | |||
if ($allCategoriesSalesOff) { | |||
return false; | |||
} | |||
if ($unavailableSpecificDay) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
@@ -126,6 +114,16 @@ class ProductSolver | |||
} | |||
} | |||
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) | |||
{ | |||
if ($product->getQuantity()) { |
@@ -9,7 +9,7 @@ class TicketSolver extends SovTicketSolver | |||
{ | |||
public function getTypeChoices($context = 'backend'): array | |||
{ | |||
$choices = parent::getTypeChoices(); | |||
$choices = parent::getTypeChoices($context); | |||
$choicesProduct = [ | |||
TicketModel::TYPE_PRODUCT_UNAVAILABLE, | |||
TicketModel::TYPE_PRODUCT_ERROR |
@@ -43,14 +43,17 @@ class ProductsSalesStatistic extends Statistic | |||
'label' => 'Total ventes' | |||
] | |||
); | |||
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() | |||
] | |||
); | |||
} | |||
} | |||
} | |||
@@ -81,7 +84,8 @@ class ProductsSalesStatistic extends Statistic | |||
{ | |||
$countsOrderedByCyclesAndProducts = $orderShopStore->countValidOrderProductsOfDistributionsByProducts( | |||
$this->distributionList, | |||
$this->productIds | |||
$this->productIds, | |||
$this->productFamily | |||
); | |||
foreach ($countsOrderedByCyclesAndProducts as $result) { |