@@ -48,6 +48,7 @@ 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,7 +64,7 @@ class OrderShopBuilder | |||
protected OrderProductBuilder $orderProductBuilder; | |||
protected DocumentBuilder $documentBuilder; | |||
protected EventDispatcherInterface $eventDispatcher; | |||
protected FlashBagInterface $flashBag; | |||
protected FlashBagTranslator $flashBag; | |||
protected ProductSolver $productSolver; | |||
protected OrderShopResolver $orderShopResolver; | |||
protected OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver; | |||
@@ -84,7 +85,7 @@ class OrderShopBuilder | |||
DocumentBuilder $documentBuilder, | |||
PriceSolver $priceSolver, | |||
EventDispatcherInterface $eventDispatcher, | |||
FlashBagInterface $flashBag, | |||
FlashBagTranslator $flashBag, | |||
ProductSolver $productSolver, | |||
OrderShopResolver $orderShopResolver, | |||
OrderProductReductionCatalogSolver $orderProductReductionCatalogSolver, | |||
@@ -322,6 +323,8 @@ class OrderShopBuilder | |||
$persist = true | |||
): OrderShopInterface { | |||
// @TODO : intégrer la gestion des OrderPackProduct dans cette méthode | |||
// TODO essayer de comprendre pourquoi on doit faire un refresh ici | |||
$this->entityManager->refresh($orderShop1); | |||
$this->entityManager->refresh($orderShop2); | |||
@@ -645,5 +648,41 @@ class OrderShopBuilder | |||
return $productsSalesStatistic->getAsArray(); | |||
} | |||
public function delete(OrderShopInterface $orderShop) | |||
{ | |||
// delete OrderProduct | |||
foreach($orderShop->getOrderProducts() as $orderProduct) { | |||
$this->entityManager->delete($orderProduct); | |||
} | |||
// delete OrderPackProduct | |||
foreach($orderShop->getOrderPackProducts() as $orderPackProduct) { | |||
$this->entityManager->delete($orderPackProduct); | |||
} | |||
// delete OrderPayment | |||
foreach($orderShop->getOrderPayments() as $orderPayment) { | |||
$this->entityManager->delete($orderPayment); | |||
} | |||
// delete OrderReductionCarts | |||
foreach($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$this->entityManager->delete($orderReductionCart); | |||
} | |||
// delete OrderReductionCredits | |||
foreach($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$this->entityManager->delete($orderReductionCredit); | |||
} | |||
// delete OrderStatusHistory | |||
foreach($orderShop->getOrderStatusHistories() as $orderStatusHistory) { | |||
$this->entityManager->delete($orderStatusHistory); | |||
} | |||
// delete OrderShop | |||
$this->entityManager->delete($orderShop); | |||
$this->entityManager->flush(); | |||
} | |||
} |
@@ -2,7 +2,51 @@ | |||
namespace Lc\CaracoleBundle\Builder\Product; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Container\Section\SectionContainer; | |||
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
class ProductFamilyBuilder | |||
{ | |||
protected EntityManagerInterface $entityManager; | |||
protected SectionContainer $sectionContainer; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
SectionContainer $sectionContainer | |||
) | |||
{ | |||
$this->entityManager = $entityManager; | |||
$this->sectionContainer = $sectionContainer; | |||
} | |||
public function setMerchant(ProductFamilyInterface $productFamily, MerchantInterface $merchant): void | |||
{ | |||
$sectionStore = $this->sectionContainer->getStore()->setMerchant($merchant); | |||
// Les ProductFamilySectionProperty sont créées en double, on rectifie ici | |||
$productFamilySectionPropertyArray = []; | |||
foreach($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) { | |||
$productFamilySectionPropertyArray[$productFamilySectionProperty->getId()] = $productFamilySectionProperty; | |||
$productFamily->removeProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
foreach($productFamilySectionPropertyArray as $productFamilySectionProperty) { | |||
$oldSection = $productFamilySectionProperty->getSection(); | |||
$newSection = $sectionStore->getOneByDevAlias($oldSection->getDevAlias()); | |||
if($newSection) { | |||
$productFamilySectionProperty->setProductFamily($productFamily); | |||
$productFamilySectionProperty->setSection($newSection); | |||
$productFamily->addProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
else { | |||
$this->entityManager->remove($productFamilySectionProperty); | |||
$productFamily->removeProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
} | |||
$productFamily->initProductCategories(); | |||
} | |||
} |
@@ -45,8 +45,11 @@ class VisitorBuilder | |||
$visitor->setLastAccess(new \DateTime()); | |||
$this->entityManager->update($visitor); | |||
$this->entityManager->flush(); | |||
// Erreur : The EntityManager is closed. #713 | |||
if($this->entityManager->isOpen()) { | |||
$this->entityManager->update($visitor); | |||
$this->entityManager->flush(); | |||
} | |||
} | |||
// setCookieVisitor |
@@ -64,9 +64,12 @@ abstract class AbstractAdminController extends SovAbstractAdminController | |||
$controller->configureFields($autocompleteContext['originatingPage']) | |||
)->getByProperty($autocompleteContext['propertyName']); | |||
$filterManager = $this->get(FilterManager::class); | |||
$filteredValue = ['value' => $context->getRequest()->query->get('q')]; | |||
$filterManager->applyFilter($repositoryQuery, $field, $filteredValue); | |||
if($field) { | |||
$filterManager = $this->get(FilterManager::class); | |||
$filteredValue = ['value' => $context->getRequest()->query->get('q')]; | |||
$filterManager->applyFilter($repositoryQuery, $field, $filteredValue); | |||
} | |||
$repositoryQuery->select('.' . $autocompleteContext['propertyName']); | |||
$responses = array(); |
@@ -130,40 +130,14 @@ trait AdminControllerTrait | |||
$newEntity = $entityComponent->duplicateEntity($context->getEntity()->getInstance()); | |||
$merchant = $duplicateOtherMerchantForm->get('merchants')->getData(); | |||
// | |||
if($this->isInstanceOf(ProductFamilyInterface::class)) { | |||
$sectionStore = $this->getSectionContainer()->getStore()->setMerchant($merchant); | |||
// Les ProductFamilySectionproperty sont créées en double, on rectifie ici | |||
// @TODO : j'imagine qu'on peut faire mieux que ça. Résoudre le problème à la base par exemple. | |||
$productFamilySectionPropertyArray = []; | |||
foreach($newEntity->getProductFamilySectionProperties() as $productFamilySectionProperty) { | |||
$productFamilySectionPropertyArray[$productFamilySectionProperty->getId()] = $productFamilySectionProperty; | |||
$newEntity->removeProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
foreach($productFamilySectionPropertyArray as $productFamilySectionProperty) { | |||
$oldSection = $productFamilySectionProperty->getSection(); | |||
$newSection = $sectionStore->getOneByDevAlias($oldSection->getDevAlias()); | |||
if($newSection) { | |||
$productFamilySectionProperty->setProductFamily($newEntity); | |||
$productFamilySectionProperty->setSection($newSection); | |||
$newEntity->addProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
else { | |||
$entityManager->remove($productFamilySectionProperty); | |||
$newEntity->removeProductFamilySectionProperty($productFamilySectionProperty); | |||
} | |||
} | |||
$newEntity->initProductCategories(); | |||
} | |||
$this->getProductFamilyContainer()->getBuilder()->setMerchant($newEntity, $merchant); | |||
} | |||
else { | |||
$newEntity->setMerchant($merchant); | |||
} | |||
// | |||
// | |||
$entityManager->create($newEntity, false); | |||
$entityManager->flush(); | |||
@@ -30,7 +30,7 @@ class CartController extends AbstractController | |||
$data = $request->request->all(); | |||
if (isset($data['order_products']['id_product_family'])) { | |||
$idProductFamily = $data['order_products']['id_product_family']; | |||
$idProductFamily = (int) $data['order_products']['id_product_family']; | |||
$this->productFamily = $this->getProductFamilyContainer()->getStore()->getOneById($idProductFamily); | |||
if(!$this->productFamily) { |
@@ -14,26 +14,31 @@ class FavoriteController extends AbstractController | |||
*/ | |||
public function toggle(Request $request) | |||
{ | |||
$user = $this->_getUser(); | |||
$user = $this->getUserCurrent(); | |||
$productFamily = $this->_getProductFamily($request); | |||
if ($user->getFavoriteProductFamilies()->contains($productFamily)) { | |||
$user->removeFavoriteProductFamily($productFamily); | |||
$isFavorite = false; | |||
$message = 'Le produit a bien été supprimé de vos favoris'; | |||
} else { | |||
$user->addFavoriteProductFamily($productFamily); | |||
$isFavorite = true; | |||
$message = 'Le produit a bien été ajouté à vos favoris'; | |||
if($user && $productFamily) { | |||
if ($user->getFavoriteProductFamilies()->contains($productFamily)) { | |||
$user->removeFavoriteProductFamily($productFamily); | |||
$isFavorite = false; | |||
$message = 'Le produit a bien été supprimé de vos favoris'; | |||
} else { | |||
$user->addFavoriteProductFamily($productFamily); | |||
$isFavorite = true; | |||
$message = 'Le produit a bien été ajouté à vos favoris'; | |||
} | |||
$this->_saveUser($user); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'is_favorite' => $isFavorite, | |||
'message' => $message | |||
]); | |||
} | |||
else { | |||
return $this->_errorResponse(); | |||
} | |||
$this->_saveUser($user); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'is_favorite' => $isFavorite, | |||
'message' => $message | |||
]); | |||
} | |||
/** | |||
@@ -41,16 +46,21 @@ class FavoriteController extends AbstractController | |||
*/ | |||
public function add(Request $request) | |||
{ | |||
$user = $this->_getUser(); | |||
$user = $this->getUserCurrent(); | |||
$productFamily = $this->_getProductFamily($request); | |||
$user->addFavoriteProductFamily($productFamily); | |||
$this->_saveUser($user); | |||
if($user && $productFamily) { | |||
$user->addFavoriteProductFamily($productFamily); | |||
$this->_saveUser($user); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'message' => 'Le produit a bien été ajouté à vos favoris' | |||
]); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'message' => 'Le produit a bien été ajouté à vos favoris' | |||
]); | |||
} | |||
else { | |||
return $this->_errorResponse(); | |||
} | |||
} | |||
/** | |||
@@ -58,32 +68,27 @@ class FavoriteController extends AbstractController | |||
*/ | |||
public function delete(Request $request) | |||
{ | |||
$user = $this->_getUser(); | |||
$user = $this->getUserCurrent(); | |||
$productFamily = $this->_getProductFamily($request); | |||
$user->removeFavoriteProductFamily($productFamily); | |||
$this->_saveUser($user); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'message' => 'Le produit a bien été supprimé de vos favoris' | |||
]); | |||
} | |||
if($user && $productFamily) { | |||
$user->removeFavoriteProductFamily($productFamily); | |||
$this->_saveUser($user); | |||
private function _getUser() | |||
{ | |||
$user = $this->getUserCurrent(); | |||
if (!$user) { | |||
throw new \ErrorException('Vous devez être connecté pour gérer vos favoris'); | |||
return new JsonResponse([ | |||
'return' => 'success', | |||
'message' => 'Le produit a bien été supprimé de vos favoris' | |||
]); | |||
} | |||
else { | |||
return $this->_errorResponse(); | |||
} | |||
return $user; | |||
} | |||
private function _saveUser($user) | |||
{ | |||
$entityManager = $this->getEntityManager(); | |||
$entityManager->persist($user); | |||
$entityManager->update($user); | |||
$entityManager->flush(); | |||
} | |||
@@ -97,8 +102,14 @@ class FavoriteController extends AbstractController | |||
if (isset($productFamily) && $productFamily) { | |||
return $productFamily; | |||
} else { | |||
throw new \ErrorException('Ce produit est introuvable'); | |||
} | |||
} | |||
private function _errorResponse() | |||
{ | |||
return new JsonResponse([ | |||
'return' => 'error', | |||
'message' => 'Une erreur est survenue.' | |||
]); | |||
} | |||
} |
@@ -18,7 +18,7 @@ abstract class ProductFamilyAdminController extends AbstractAdminController | |||
public function configureCrud(Crud $crud): Crud | |||
{ | |||
$crud = parent::configureCrud($crud); | |||
$crud->setPaginatorPageSize(100); | |||
if ($this->getRequestCrudAction() === ActionDefinition::SORT) { | |||
$crud->setDefaultSort(['position' => 'ASC']); | |||
} else { |
@@ -12,14 +12,19 @@ trait FieldDefinitionTrait | |||
use MerchantContextTrait; | |||
use SectionContextTrait; | |||
protected ?array $sectionArray = null; | |||
public function configureFieldsBase(): array | |||
{ | |||
$sectionArray = $this->sectionStore->setMerchant($this->merchant)->get(); | |||
if(is_null($this->sectionArray)){ | |||
$this->sectionArray = $this->sectionStore->setMerchant($this->merchant)->get(); | |||
} | |||
return array_merge(parent::configureFieldsBase(), [ | |||
'section' => AssociationField::new('section') | |||
->setTemplatePath('@LcCaracole/admin/section/field/section.html.twig') | |||
->setFormTypeOption('choices', $sectionArray) | |||
->setFormTypeOption('choices', $this->sectionArray) | |||
]); | |||
} | |||
@@ -18,6 +18,8 @@ class ProductCategoryFieldDefinition extends AbstractFieldDefinition | |||
protected SectionStore $sectionStore; | |||
protected ProductCategoryStore $productCategoryStore; | |||
protected ?array $productCategoryArray = null; | |||
public function __construct( | |||
TranslatorAdmin $translatorAdmin, | |||
SectionStore $sectionStore, | |||
@@ -70,15 +72,17 @@ class ProductCategoryFieldDefinition extends AbstractFieldDefinition | |||
public function configureFields(): array | |||
{ | |||
$productCategoryArray = $this->productCategoryStore | |||
if(is_null($this->productCategoryArray)) { | |||
$this->productCategoryArray = $this->productCategoryStore | |||
->setSection($this->section) | |||
->getParents(); | |||
} | |||
return [ | |||
'title' => TextField::new('title')->setSortable(true), | |||
'position' => NumberField::new('position')->setSortable(true), | |||
'parent' => AssociationField::new('parent') | |||
->setFormTypeOption('choices', $productCategoryArray) | |||
->setFormTypeOption('choices', $this->productCategoryArray) | |||
->setFormTypeOption( | |||
'choice_label', | |||
function ($productCategory) { |
@@ -27,6 +27,11 @@ class ReductionCatalogFieldDefinition extends AbstractFieldDefinition | |||
protected ProductFamilyStore $productFamilyStore; | |||
protected ProductCategoryStore $productCategoryStore; | |||
protected ?array $groupUserArray = null; | |||
protected ?array $usersArray= null; | |||
protected ?array $productFamilyArray= null; | |||
protected ?array $productCategoryArray= null; | |||
public function __construct( | |||
TranslatorAdmin $translatorAdmin, | |||
GroupUserStore $groupUserStore, | |||
@@ -81,10 +86,21 @@ class ReductionCatalogFieldDefinition extends AbstractFieldDefinition | |||
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(); | |||
if(is_null($this->groupUserArray)) { | |||
$this->groupUserArray = $this->groupUserStore->setMerchant($this->merchant)->get(); | |||
} | |||
if(is_null($this->usersArray)) { | |||
$this->usersArray = $this->userStore->setMerchant($this->merchant)->getJoinGroupUsers(); | |||
} | |||
if(is_null($this->productFamilyArray)) { | |||
$this->productFamilyArray = $this->productFamilyStore->setMerchant($this->merchant)->get(); | |||
} | |||
if(is_null($this->productCategoryArray)) { | |||
$this->productCategoryArray = $this->productCategoryStore->setMerchant($this->merchant)->get(); | |||
} | |||
return [ | |||
'title' => TextField::new('title')->setSortable(true), | |||
@@ -116,13 +132,13 @@ class ReductionCatalogFieldDefinition extends AbstractFieldDefinition | |||
'groupUsersActive' => BooleanField::new('groupUsersActive')->setFormTypeOption('mapped', false), | |||
'groupUsers' => AssociationField::new('groupUsers') | |||
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig') | |||
->setFormTypeOption('choices', $groupUserArray), | |||
->setFormTypeOption('choices', $this->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('choices', $this->usersArray) | |||
->setFormTypeOption( | |||
'choice_attr', | |||
function ($choice, $key, $value) { | |||
@@ -149,13 +165,13 @@ class ReductionCatalogFieldDefinition extends AbstractFieldDefinition | |||
$section = ' [' . $category->getSection()->getTitle() . ']';; | |||
return $category . $section . $isOffline; | |||
}) | |||
->setFormTypeOption('choices', $productCategoryArray), | |||
->setFormTypeOption('choices', $this->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('choices', $this->productFamilyArray) | |||
->setFormTypeOption( | |||
'choice_attr', | |||
function ($choice, $key, $value) { | |||
@@ -170,7 +186,7 @@ class ReductionCatalogFieldDefinition extends AbstractFieldDefinition | |||
} | |||
), | |||
'productFamily' => AssociationField::new('productFamily') | |||
->setFormTypeOption('choices', $productFamilyArray) | |||
->setFormTypeOption('choices', $this->productFamilyArray) | |||
]; | |||
} | |||
} |
@@ -12,6 +12,8 @@ class NewsFieldDefinition extends SovNewsFieldDefinition | |||
{ | |||
use FieldDefinitionTrait; | |||
protected ?array $newsletterArray = null; | |||
protected SectionStore $sectionStore; | |||
protected NewsletterStore $newsletterStore; | |||
@@ -36,12 +38,14 @@ class NewsFieldDefinition extends SovNewsFieldDefinition | |||
{ | |||
$fieldArray = parent::configureFields(); | |||
$newsletterArray = $this->newsletterStore | |||
if(is_null($this->newsletterArray)){ | |||
$this->newsletterArray = $this->newsletterStore | |||
->setSection($this->section) | |||
->setMerchant($this->merchant) | |||
->get(); | |||
} | |||
$fieldArray['newsletter']->setFormTypeOption('choices', $newsletterArray); | |||
$fieldArray['newsletter']->setFormTypeOption('choices', $this->newsletterArray); | |||
return $fieldArray; | |||
} |
@@ -21,15 +21,19 @@ class UserFieldDefinition extends SovUserFieldDefinition | |||
{ | |||
use MerchantContextTrait; | |||
protected ?array $newsletterArray = null; | |||
protected ?array $groupUserArray = null; | |||
protected GroupUserStore $groupUserStore; | |||
protected NewsletterStore $newsletterStore; | |||
public function __construct( | |||
TranslatorAdmin $translatorAdmin, | |||
RolesDefinition $rolesDefinition, | |||
GroupUserStore $groupUserStore, | |||
GroupUserStore $groupUserStore, | |||
NewsletterStore $newsletterStore | |||
) { | |||
) | |||
{ | |||
parent::__construct($translatorAdmin, $rolesDefinition); | |||
$this->groupUserStore = $groupUserStore; | |||
@@ -70,19 +74,24 @@ class UserFieldDefinition extends SovUserFieldDefinition | |||
public function configureFields(): array | |||
{ | |||
$groupUsers = $this->groupUserStore->setMerchant($this->merchant)->getAll(); | |||
$newsletters = $this->newsletterStore->getAll(); | |||
if (is_null($this->newsletterArray)) { | |||
$this->newsletterArray = $this->newsletterStore->getAll(); | |||
} | |||
if (is_null($this->groupUserArray)) { | |||
$this->groupUserArray = $this->groupUserStore->setMerchant($this->merchant)->getAll(); | |||
} | |||
return array_merge(parent::configureFields(), [ | |||
'isSaleAlwaysOpen' => BooleanField::new('isSaleAlwaysOpen'), | |||
'newsletters' => AssociationField::new('newsletters') | |||
->setFormTypeOption('choices', $newsletters) | |||
->setFormTypeOption('choices', $this->newsletterArray) | |||
->setFormTypeOption('choice_label', function ($choice) { | |||
return $choice->getTitle() . '[' . $choice->getSection()->getMerchant() . ']'; | |||
}) | |||
->setSortable(true), | |||
'groupUsers' => AssociationField::new('groupUsers') | |||
->setFormTypeOption('choices', $groupUsers) | |||
->setFormTypeOption('choices', $this->groupUserArray) | |||
->setCustomOption('class', GroupUser::class) | |||
->setTemplatePath('@LcSov/adminlte/crud/field/association_many.html.twig') | |||
->setFormTypeOption('choice_label', function ($choice) { |
@@ -15,9 +15,6 @@ class AddressFactory extends AbstractFactory | |||
$class = AddressContainer::getEntityFqcn(); | |||
$address = new $class; | |||
$address->setMerchant($merchant); | |||
return $address; | |||
} | |||
} |
@@ -49,11 +49,17 @@ abstract class ProductFamilyModel extends AbstractFullEntity implements ProductP | |||
const QUALITY_LABEL_RECUP = 'recup'; | |||
static $organicLabels = [ | |||
self::QUALITY_LABEL_AB, | |||
self::QUALITY_LABEL_NP, | |||
self::QUALITY_LABEL_HVE, | |||
self::QUALITY_LABEL_TVVR | |||
self::QUALITY_LABEL_AB, | |||
self::QUALITY_LABEL_NP, | |||
self::QUALITY_LABEL_HVE, | |||
self::QUALITY_LABEL_TVVR | |||
]; | |||
static $organicStrictLabels = [ | |||
self::QUALITY_LABEL_AB, | |||
self::QUALITY_LABEL_NP | |||
]; | |||
static $geographicLabels = [ | |||
self::QUALITY_LABEL_AOC, | |||
self::QUALITY_LABEL_AOP, |
@@ -61,7 +61,6 @@ class OrderShopRepositoryQuery extends AbstractRepositoryQuery | |||
public function selectSum(): self | |||
{ | |||
$this->joinProduct(); | |||
$this->joinDistribution(); | |||
return $this | |||
->select( | |||
'SUM(orderProducts.quantityOrder) as quantity, distribution.cycleNumber as cycleNumber, distribution.year as year , product.id as productId' | |||
@@ -161,6 +160,7 @@ class OrderShopRepositoryQuery extends AbstractRepositoryQuery | |||
public function filterByDistributions(array $distributionArray): self | |||
{ | |||
$this->joinDistribution(); | |||
return $this | |||
->andWhere('.distribution IN (:distributions)') | |||
->setParameter('distributions', $distributionArray); |
@@ -26,6 +26,8 @@ class ProductCategoryRepositoryQuery extends AbstractRepositoryQuery | |||
return $this | |||
->innerJoin('.productFamilies', 'productFamilies'); | |||
//@GONE AWAY avec un addSelect('productFamilies') on gagne 10 requetes | |||
} | |||
return $this; | |||
@@ -37,4 +39,9 @@ class ProductCategoryRepositoryQuery extends AbstractRepositoryQuery | |||
return $this->andWhere('productFamilies.status = 1'); | |||
} | |||
public function filterByTitle(string $title): self | |||
{ | |||
return $this->andWhere('.title LIKE :title')->setParameter('title', $title); | |||
} | |||
} |
@@ -53,4 +53,11 @@ class ProductCategoryStore extends AbstractStore | |||
$query->filterByDevAlias($devAlias); | |||
return $query->find(); | |||
} | |||
public function getOneByTitle(string $title): ?ProductCategoryInterface | |||
{ | |||
$query = $this->createDefaultQuery(); | |||
$query->filterByTitle($title); | |||
return $query->findOne(); | |||
} | |||
} |
@@ -140,7 +140,7 @@ class ProductFamilyRepositoryQuery extends AbstractRepositoryQuery | |||
{ | |||
return $this->innerJoin('.qualityLabels', 'qualityLabel') | |||
->andWhere('qualityLabel.devAlias IN (:organicLabels)') | |||
->setParameter(':organicLabels', ProductFamilyModel::$organicLabels); | |||
->setParameter(':organicLabels', ProductFamilyModel::$organicStrictLabels); | |||
} | |||
public function filterIsNovelty() | |||
@@ -189,7 +189,7 @@ class ProductFamilyRepositoryQuery extends AbstractRepositoryQuery | |||
$this->innerJoin('.products', 'products'); | |||
if ($addSelect) { | |||
// Décommenté sinon doctrine n'hydrate pas correctement les produits liés au ProductFamily (exemple : un seul sur deux) | |||
// $this->addSelect('products'); | |||
//$this->addSelect('products'); | |||
} | |||
} | |||
return $this; | |||
@@ -201,4 +201,8 @@ class ProductFamilyRepositoryQuery extends AbstractRepositoryQuery | |||
return $this; | |||
} | |||
public function filterByTitle(string $title): self | |||
{ | |||
return $this->andWhere('.title LIKE :title')->setParameter('title', $title); | |||
} | |||
} |
@@ -11,6 +11,8 @@ use Lc\CaracoleBundle\Solver\Price\PriceSolver; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\CaracoleBundle\Repository\AbstractStore; | |||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
use Symfony\Contracts\Cache\CacheInterface; | |||
use Symfony\Contracts\Cache\ItemInterface; | |||
class ProductFamilyStore extends AbstractStore | |||
{ | |||
@@ -19,13 +21,16 @@ class ProductFamilyStore extends AbstractStore | |||
protected ProductFamilyRepositoryQuery $query; | |||
protected PriceSolver $priceSolver; | |||
protected CacheInterface $cache; | |||
public function __construct( | |||
ProductFamilyRepositoryQuery $query, | |||
PriceSolver $priceSolver | |||
PriceSolver $priceSolver, | |||
CacheInterface $cache | |||
) { | |||
$this->query = $query; | |||
$this->priceSolver = $priceSolver; | |||
$this->cache = $cache; | |||
} | |||
public function orderByDefault(RepositoryQueryInterface $query): RepositoryQueryInterface | |||
@@ -60,6 +65,13 @@ class ProductFamilyStore extends AbstractStore | |||
$productFamiliesArray = []; | |||
foreach ($parentCategory->getChildrens() as $i => $category) { | |||
//Essai d'alternative | |||
// foreach ($category->getProductFamilies() as $productFamily) { | |||
// if($productFamily->getStatus()==1) { | |||
// $productFamiliesArray[$productFamily->getId()] = $productFamily; | |||
// } | |||
// } | |||
$productFamiliesCategory = $this->getByCategory($category); | |||
foreach ($productFamiliesCategory as $productFamily) { | |||
$productFamiliesArray[$productFamily->getId()] = $productFamily; | |||
@@ -116,6 +128,25 @@ class ProductFamilyStore extends AbstractStore | |||
return $this->getWithReductions($results, $user, false, $organizeByParentCategory); | |||
} | |||
public function getCachedNovelty($user = null, $organizeByParentCategory = true, $query = null): array | |||
{ | |||
$productFamilyStore = $this; | |||
return $this->cache->get($this->getCacheKeyNovelty(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) { | |||
$item->expiresAfter(3600); | |||
return $productFamilyStore->getNovelty($user, $organizeByParentCategory, $query); | |||
}); | |||
} | |||
public function deleteCacheNovelty(): void | |||
{ | |||
$this->cache->delete($this->getCacheKeyNovelty()); | |||
} | |||
public function getCacheKeyNovelty() | |||
{ | |||
return 'products_novelty_'.$this->section->getId(); | |||
} | |||
// getProductFamiliesOrganics | |||
public function getOrganic($user = null, $organizeByParentCategory = true, $query = null) | |||
{ | |||
@@ -134,6 +165,31 @@ class ProductFamilyStore extends AbstractStore | |||
return $this->getWithReductions($this->getOnline($query), $user, false, $organizeByParentCategory, true); | |||
} | |||
public function getCachedDiscount($user = null, $organizeByParentCategory = true, $query = null): array | |||
{ | |||
$productFamilyStore = $this; | |||
return $this->cache->get($this->getCacheKeyDiscount(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) { | |||
$item->expiresAfter(3600); | |||
return $productFamilyStore->getDiscount($user, $organizeByParentCategory, $query); | |||
}); | |||
} | |||
public function deleteCacheDiscount(): void | |||
{ | |||
$this->cache->delete($this->getCacheKeyDiscount()); | |||
} | |||
public function getCacheKeyDiscount() | |||
{ | |||
return 'products_discount_'.$this->section->getId(); | |||
} | |||
public function loadAllDatas(ProductFamilyInterface $productFamily) | |||
{ | |||
$productFamily->getProductFamilySectionProperties()->toArray(); | |||
} | |||
// getProductFamiliesFavorites | |||
public function getFavorite($user = null, $organizeByParentCategory = true, $query = null) | |||
{ | |||
@@ -227,6 +283,10 @@ class ProductFamilyStore extends AbstractStore | |||
$productFamiliesToReturn = array(); | |||
foreach ($productFamilies as $productFamily) { | |||
// Cache : chargement de toutes les données manquantes (fetch eager ne fonctionne pas) | |||
$this->loadAllDatas($productFamily); | |||
foreach ($reductionCatalogs as $reductionCatalog) { | |||
$conditionProductFamilies = $conditionProductFamily = $conditionProductCategory = false; | |||
@@ -301,4 +361,10 @@ class ProductFamilyStore extends AbstractStore | |||
return $productFamiliesToReturn; | |||
} | |||
public function getOneByTitle(string $title): ?ProductFamilyInterface | |||
{ | |||
$query = $this->createDefaultQuery(); | |||
$query->filterByTitle($title); | |||
return $query->findOne(); | |||
} | |||
} |
@@ -2,8 +2,10 @@ | |||
namespace Lc\CaracoleBundle\Resolver; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; | |||
use Lc\CaracoleBundle\Solver\Order\OrderShopSolver; | |||
use Lc\CaracoleBundle\Solver\Price\PriceSolver; | |||
use Lc\CaracoleBundle\Solver\Product\ProductFamilySolver; | |||
@@ -11,11 +13,13 @@ class ProductFamilyResolver | |||
{ | |||
protected PriceSolver $priceSolver; | |||
protected ProductFamilySolver $productFamilySolver; | |||
protected OrderShopSolver $orderShopSolver; | |||
public function __construct(PriceSolver $priceSolver, ProductFamilySolver $productFamilySolver) | |||
public function __construct(PriceSolver $priceSolver, ProductFamilySolver $productFamilySolver, OrderShopSolver $orderShopSolver) | |||
{ | |||
$this->priceSolver = $priceSolver; | |||
$this->productFamilySolver = $productFamilySolver; | |||
$this->orderShopSolver = $orderShopSolver; | |||
} | |||
public function getMultiplyingFactor(ProductFamilyInterface $productFamily) | |||
@@ -23,76 +27,93 @@ class ProductFamilyResolver | |||
if ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) { | |||
if ($productFamily->getBuyingPrice() > 0) { | |||
return number_format( | |||
$this->priceSolver->getPriceWithTax($productFamily) / $productFamily->getBuyingPrice(), | |||
3 | |||
$this->priceSolver->getPriceWithTax($productFamily) / $productFamily->getBuyingPrice(), | |||
3 | |||
); | |||
} | |||
} elseif ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) { | |||
if ($productFamily->getBuyingPriceByRefUnit() > 0) { | |||
return number_format( | |||
$this->priceSolver->getPriceByRefUnitWithTax( | |||
$productFamily | |||
) / $productFamily->getBuyingPriceByRefUnit(), | |||
3 | |||
$this->priceSolver->getPriceByRefUnitWithTax( | |||
$productFamily | |||
) / $productFamily->getBuyingPriceByRefUnit(), | |||
3 | |||
); | |||
} | |||
} | |||
} | |||
public function getCheapestProduct(ProductFamilyInterface $productFamily) | |||
public function getCheapestProduct(ProductFamilyInterface $productFamily, OrderShopInterface $orderShop = null) | |||
{ | |||
$priceSolver = $this->priceSolver; | |||
return $this->getCheapestOrMostExpensiveProduct( | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceWithTaxAndReduction( | |||
$a | |||
) > $priceSolver->getPriceWithTaxAndReduction($b); | |||
}, | |||
true | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceWithTaxAndReduction( | |||
$a | |||
) > $priceSolver->getPriceWithTaxAndReduction($b); | |||
}, | |||
true, | |||
$orderShop | |||
); | |||
} | |||
public function getCheapestProductByRefUnit(ProductFamilyInterface $productFamily) | |||
public function getCheapestProductByRefUnit(ProductFamilyInterface $productFamily, OrderShopInterface $orderShop = null) | |||
{ | |||
$priceSolver = $this->priceSolver; | |||
return $this->getCheapestOrMostExpensiveProduct( | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceByRefUnitWithTaxAndReduction( | |||
$a | |||
) > $priceSolver->getPriceByRefUnitWithTaxAndReduction($b); | |||
}, | |||
false | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceByRefUnitWithTaxAndReduction( | |||
$a | |||
) > $priceSolver->getPriceByRefUnitWithTaxAndReduction($b); | |||
}, | |||
false, | |||
$orderShop | |||
); | |||
} | |||
public function getMostExpensiveProductByRefUnit(ProductFamilyInterface $productFamily) | |||
public function getMostExpensiveProductByRefUnit(ProductFamilyInterface $productFamily, OrderShopInterface $orderShop = null) | |||
{ | |||
$priceSolver = $this->priceSolver; | |||
return $this->getCheapestOrMostExpensiveProduct( | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceByRefUnitWithTaxAndReduction( | |||
$a | |||
) < $priceSolver->getPriceByRefUnitWithTaxAndReduction($b); | |||
}, | |||
false | |||
$productFamily, | |||
function ($a, $b) use ($priceSolver) { | |||
return $priceSolver->getPriceByRefUnitWithTaxAndReduction( | |||
$a | |||
) < $priceSolver->getPriceByRefUnitWithTaxAndReduction($b); | |||
}, | |||
false, | |||
$orderShop | |||
); | |||
} | |||
private function getCheapestOrMostExpensiveProduct( | |||
ProductFamilyInterface $productFamily, | |||
$comparisonFunction, | |||
$returnSelfIfNotActiveProducts | |||
) { | |||
ProductFamilyInterface $productFamily, | |||
$comparisonFunction, | |||
$returnSelfIfNotActiveProducts, | |||
OrderShopInterface $orderShop = null | |||
) | |||
{ | |||
if ($productFamily->getActiveProducts()) { | |||
$products = $this->productFamilySolver->getProductsOnline($productFamily)->getValues(); | |||
if (count($products) > 0) { | |||
usort($products, $comparisonFunction); | |||
if($orderShop) { | |||
foreach ($products as $product) { | |||
return $product; | |||
// Retourner le produit en fonction de sa disponibilité | |||
// if ($this->orderShopSolver->isProductAvailable($orderShop->getSection(), $orderShop, $product, 1, true)) | |||
} | |||
} | |||
return $products[0]; | |||
} | |||
} else { |
@@ -111,14 +111,20 @@ class SectionResolver | |||
} | |||
} | |||
/* | |||
* /!\ Cache désactivé car génération d'une erreur du type : | |||
* "A new entity was found through the relationship 'App\Entity\Order\OrderShop#section' that was not configured to cascade persist operations for entity: Marché" | |||
* | |||
* Arrive sur les pages générées via le cache HTTP (CacheController.php) | |||
*/ | |||
if ($sectionCurrent) { | |||
$this->cacheSectionCurrent = $sectionCurrent; | |||
//$this->cacheSectionCurrent = $sectionCurrent; | |||
return $sectionCurrent; | |||
} elseif ($returnVisitedIfOutOfSection && $currentVisitedSection) { | |||
$this->cacheSectionVisited = $currentVisitedSection; | |||
//$this->cacheSectionVisited = $currentVisitedSection; | |||
return $currentVisitedSection; | |||
} elseif ($returnDefaultIfOutOfSections && $sectionDefault) { | |||
$this->cacheSectionDefault = $sectionDefault; | |||
//$this->cacheSectionDefault = $sectionDefault; | |||
return $sectionDefault; | |||
} | |||
@@ -44,8 +44,8 @@ setting_definition: | |||
settings: | |||
orderReferencePrefix: Préfixe référence commandes | |||
orderState: Statut d'ouverture des commandes | |||
orderClosedStart: Période commandes fermées (début) | |||
orderClosedEnd: Période commandes fermées (fin) | |||
orderClosedStart: "Période commandes fermées (début : définir comme date le lendemain du jour de fermeture de la section)" | |||
orderClosedEnd: "Période commandes fermées (fin : définir comme date la veille du jour de ré-ouverture de la section)" | |||
orderMaximumPerCycle: Nombre maximum de commande par cycle de vente | |||
colorPrimary: Couleur primaire | |||
colorSecondary: Couleur secondaire |
@@ -10,8 +10,10 @@ | |||
{% endif %} | |||
{% endif %} | |||
{% if cycleType == "year" %} | |||
A{{ distribution.cycleNumber }} | |||
{% else %} | |||
{{ labelCycleType ~ distribution.cycleNumber }}A{{ distribution.year|slice(2,2) }} | |||
{% if cycleType is defined %} | |||
{% if cycleType == "year" %} | |||
A{{ distribution.cycleNumber }} | |||
{% else %} | |||
{{ labelCycleType ~ distribution.cycleNumber }}A{{ distribution.year|slice(2,2) }} | |||
{% endif %} | |||
{% endif %} |
@@ -1 +1,9 @@ | |||
{{ price_solver.getPriceWithTax(entity.instance)|format_price|raw }} | |||
{% set priceWithTax = price_solver.getPriceWithTax(entity.instance)|format_price %} | |||
{% set priceWithTaxAndReduction = price_solver.getPriceWithTaxAndReduction(entity.instance)|format_price %} | |||
{% if priceWithTax != priceWithTaxAndReduction %} | |||
<s>{{ priceWithTax|raw }}</s><br /> | |||
{{ priceWithTaxAndReduction|raw }} | |||
{% else %} | |||
{{ priceWithTaxAndReduction|raw }} | |||
{% endif %} |
@@ -0,0 +1,5 @@ | |||
{% if entity.instance.getNewsletters()|length %} | |||
<span class="badge badge-success">Oui</span> | |||
{% else %} | |||
<span class="badge badge-secondary">Non</span> | |||
{% endif %} |
@@ -126,7 +126,7 @@ class OrderShopSolver | |||
// isProductAvailable | |||
public function isProductAvailable( | |||
SectionInterface $section, | |||
OrderShopInterface $orderShop, | |||
?OrderShopInterface $orderShop, | |||
ProductInterface $product, | |||
int $quantityOrder = 0, | |||
bool $checkCart = false | |||
@@ -171,6 +171,16 @@ class OrderShopSolver | |||
} | |||
} | |||
public function isOneProductAvailable(SectionInterface $section, $productArray): bool | |||
{ | |||
foreach($productArray as $product) { | |||
if($this->isProductAvailable($section, null, $product, 1, false)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
public function isOneProductAvailableAddCart(OrderShopInterface $orderShop, $products): bool | |||
{ | |||
foreach ($products as $product) { | |||
@@ -221,6 +231,11 @@ class OrderShopSolver | |||
} | |||
return $arrayComplementaryOrderShops; | |||
} | |||
public function countValidComplementaryOrderShops(OrderShopInterface $orderShop): int | |||
{ | |||
return count($this->getValidComplementaryOrderShops($orderShop)); | |||
} | |||
public function getOrderStatusHistory(OrderShopInterface $orderShop, OrderStatusInterface $status) | |||
{ |
@@ -12,10 +12,11 @@ class ProductFamilySectionPropertySolver | |||
public function getProductFamilySectionProperty(ProductFamilyInterface $productFamily, SectionInterface $section):? ProductFamilySectionPropertyInterface | |||
{ | |||
foreach ($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) { | |||
if ($productFamilySectionProperty->getSection() == $section) { | |||
if ($productFamilySectionProperty->getSection()->getId() == $section->getId()) { | |||
return $productFamilySectionProperty; | |||
} | |||
} | |||
return null; | |||
} | |||
@@ -152,7 +152,7 @@ class ProductFamilySolver | |||
if ($productFamily->getTaxRate()) { | |||
return $productFamily->getTaxRate(); | |||
} else { | |||
return $productFamily->getProductFamilySectionProperties()[0]->getSection()->getMerchant()->getTaxRate(); | |||
return $this->getMerchant($productFamily)->getTaxRate(); | |||
} | |||
} | |||
@@ -191,7 +191,6 @@ class ProductFamilySolver | |||
return false; | |||
} | |||
public function getProductCategoryChild(ProductFamilyInterface $productFamily, SectionInterface $section) | |||
{ | |||
$productCategories = $productFamily->getProductCategories(); | |||
@@ -205,7 +204,6 @@ class ProductFamilySolver | |||
return false; | |||
} | |||
public function isPropertyNoveltyOnline(ProductFamilyInterface $productFamily): ?bool | |||
{ | |||
if ($productFamily->getPropertyNoveltyExpirationDate()) { | |||
@@ -218,7 +216,6 @@ class ProductFamilySolver | |||
return false; | |||
} | |||
public function countProperties(ProductFamilyInterface $productFamily): bool | |||
{ | |||
$count = 0; | |||
@@ -239,7 +236,6 @@ class ProductFamilySolver | |||
return $count; | |||
} | |||
public function hasProductsWithVariousWeight(ProductFamilyInterface $productFamily) | |||
{ | |||
if ($productFamily->getActiveProducts()) { | |||
@@ -268,7 +264,6 @@ class ProductFamilySolver | |||
return false; | |||
} | |||
public function getProductsGroupByTitle(ProductFamilyInterface $productFamily): array | |||
{ | |||
$arrayProductsGroupByTitle = []; | |||
@@ -489,7 +484,6 @@ class ProductFamilySolver | |||
return false; | |||
} | |||
public function isCategoriesOnlineInSection(ProductFamilyInterface $productFamily, SectionInterface $section): bool | |||
{ | |||
$isCategoriesOnlineInSection = false; |
@@ -59,13 +59,13 @@ class OrderShopTransformer | |||
$i = 0; | |||
$orderProductsByParentCategory = $this->orderShopSolver->getOrderProductsByParentCategory($orderShop); | |||
foreach ($orderProductsByParentCategory as $labelCategory => $orderProducts) { | |||
foreach ($orderProducts as $orderProduct) { | |||
// $orderProductsByParentCategory = $this->orderShopSolver->getOrderProductsByParentCategory($orderShop); | |||
// foreach ($orderProductsByParentCategory as $labelCategory => $orderProducts) { | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$data['orderProducts'][$i]['id'] = $orderProduct->getId(); | |||
$data['orderProducts'][$i]['product'] = $orderProduct->getProduct()->getId(); | |||
$data['orderProducts'][$i]['quantityOrder'] = $orderProduct->getQuantityOrder(); | |||
$data['orderProducts'][$i]['labelCategory'] = $labelCategory; | |||
// $data['orderProducts'][$i]['labelCategory'] = $labelCategory; | |||
$data['orderProducts'][$i]['title'] = $orderProduct->getTitle(); | |||
$data['orderProducts'][$i]['price'] = $this->priceSolver->getPrice($orderProduct); | |||
$data['orderProducts'][$i]['priceWithTax'] = $this->priceSolver->getPriceWithTax($orderProduct); | |||
@@ -78,7 +78,7 @@ class OrderShopTransformer | |||
); | |||
$i++; | |||
} | |||
} | |||
// } | |||
return $data; | |||
} |