You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

371 lines
13KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Repository\Product;
  3. use Lc\CaracoleBundle\Model\Product\ProductCategoryInterface;
  4. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  5. use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
  6. use Lc\CaracoleBundle\Repository\MerchantStoreTrait;
  7. use Lc\CaracoleBundle\Repository\SectionStoreTrait;
  8. use Lc\CaracoleBundle\Solver\Price\PriceSolver;
  9. use Lc\SovBundle\Model\User\UserInterface;
  10. use Lc\CaracoleBundle\Repository\AbstractStore;
  11. use Lc\SovBundle\Repository\RepositoryQueryInterface;
  12. use Symfony\Contracts\Cache\CacheInterface;
  13. use Symfony\Contracts\Cache\ItemInterface;
  14. class ProductFamilyStore extends AbstractStore
  15. {
  16. use SectionStoreTrait;
  17. use MerchantStoreTrait;
  18. protected ProductFamilyRepositoryQuery $query;
  19. protected PriceSolver $priceSolver;
  20. protected CacheInterface $cache;
  21. public function __construct(
  22. ProductFamilyRepositoryQuery $query,
  23. PriceSolver $priceSolver,
  24. CacheInterface $cache
  25. ) {
  26. $this->query = $query;
  27. $this->priceSolver = $priceSolver;
  28. $this->cache = $cache;
  29. }
  30. public function orderByDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  31. {
  32. $query->orderBy('position');
  33. return $query;
  34. }
  35. public function filtersDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  36. {
  37. $query->filterIsOnlineAndOffline();
  38. $this->addFilterBySectionOptionnal($query);
  39. $this->addFilterByMerchantViaSectionOptionnal($query);
  40. return $query;
  41. }
  42. public function relationsDefault($query): RepositoryQueryInterface
  43. {
  44. $query->joinProductCategories();
  45. $query->joinProducts();
  46. $query->joinQualityLabels();
  47. return $query;
  48. }
  49. public function getByParentCategory(
  50. ProductCategoryInterface $parentCategory,
  51. $user = null,
  52. $query = null
  53. ) {
  54. $productFamiliesArray = [];
  55. foreach ($parentCategory->getChildrens() as $i => $category) {
  56. //Essai d'alternative
  57. // foreach ($category->getProductFamilies() as $productFamily) {
  58. // if($productFamily->getStatus()==1) {
  59. // $productFamiliesArray[$productFamily->getId()] = $productFamily;
  60. // }
  61. // }
  62. $productFamiliesCategory = $this->getByCategory($category);
  63. foreach ($productFamiliesCategory as $productFamily) {
  64. $productFamiliesArray[$productFamily->getId()] = $productFamily;
  65. }
  66. uasort($productFamiliesArray, array($this, 'compMethodSortProductFamiliesByPosition'));
  67. }
  68. return $this->getWithReductions($productFamiliesArray, $user, true);
  69. }
  70. private function compMethodSortProductFamiliesByPosition($a, $b)
  71. {
  72. return $a->getPosition() > $b->getPosition();
  73. }
  74. // getProductFamiliesByCategory
  75. public function getByCategory(
  76. ProductCategoryInterface $productCategory,
  77. $query = null
  78. ) {
  79. $query = $this->createDefaultQuery($query);
  80. $query
  81. ->filterIsOnline()
  82. ->filterByProductCategory($productCategory);
  83. return $query->find();
  84. }
  85. //TODO ajouter status en donné de contexte pour éviter ce truc
  86. public function getByCategoryOnlineAndOffline(
  87. ProductCategoryInterface $productCategory,
  88. $query = null
  89. ) {
  90. $query = $this->createDefaultQuery($query);
  91. $query
  92. ->filterByProductCategory($productCategory);
  93. return $query->find();
  94. }
  95. // getProductFamiliesNovelties
  96. public function getNovelty($user = null, $organizeByParentCategory = true, $query = null)
  97. {
  98. $query = $this->createDefaultQuery($query);
  99. $query
  100. ->filterByPropertyNoveltyExpirationDate()
  101. ->filterIsOnline();
  102. $results = $query->find();
  103. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  104. }
  105. public function getCachedNovelty($user = null, $organizeByParentCategory = true, $query = null): array
  106. {
  107. $productFamilyStore = $this;
  108. return $this->cache->get($this->getCacheKeyNovelty(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) {
  109. $item->expiresAfter(3600);
  110. return $productFamilyStore->getNovelty($user, $organizeByParentCategory, $query);
  111. });
  112. }
  113. public function deleteCacheNovelty(): void
  114. {
  115. $this->cache->delete($this->getCacheKeyNovelty());
  116. }
  117. public function getCacheKeyNovelty()
  118. {
  119. return 'products_novelty_'.$this->section->getId();
  120. }
  121. // getProductFamiliesOrganics
  122. public function getOrganic($user = null, $organizeByParentCategory = true, $query = null)
  123. {
  124. $query = $this->createDefaultQuery($query);
  125. $query
  126. ->filterIsOrganicLabel()
  127. ->filterIsOnline();
  128. $results = $query->find();
  129. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  130. }
  131. // getProductFamiliesOnDiscount
  132. public function getDiscount($user = null, $organizeByParentCategory = true, $query = null)
  133. {
  134. return $this->getWithReductions($this->getOnline($query), $user, false, $organizeByParentCategory, true);
  135. }
  136. public function getCachedDiscount($user = null, $organizeByParentCategory = true, $query = null): array
  137. {
  138. $productFamilyStore = $this;
  139. return $this->cache->get($this->getCacheKeyDiscount(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) {
  140. $item->expiresAfter(3600);
  141. return $productFamilyStore->getDiscount($user, $organizeByParentCategory, $query);
  142. });
  143. }
  144. public function deleteCacheDiscount(): void
  145. {
  146. $this->cache->delete($this->getCacheKeyDiscount());
  147. }
  148. public function getCacheKeyDiscount()
  149. {
  150. return 'products_discount_'.$this->section->getId();
  151. }
  152. public function loadAllDatas(ProductFamilyInterface $productFamily)
  153. {
  154. $productFamily->getProductFamilySectionProperties()->toArray();
  155. }
  156. // getProductFamiliesFavorites
  157. public function getFavorite($user = null, $organizeByParentCategory = true, $query = null)
  158. {
  159. if ($user) {
  160. return $this->getWithReductions(
  161. $user->getFavoriteProductFamilies(),
  162. $user,
  163. false,
  164. $organizeByParentCategory
  165. );
  166. }
  167. return [];
  168. }
  169. // findByTerms
  170. public function getByTerms(
  171. $terms,
  172. $maxResults = false,
  173. $organizeByParentCategory = false,
  174. $user = null,
  175. $query = null
  176. ) {
  177. $query = $this->createDefaultQuery($query);
  178. $query->filterIsOnline();
  179. $query->filterByTerms($terms);
  180. $query->groupBy('id');
  181. if ($maxResults) {
  182. $query->limit($maxResults);
  183. }
  184. $results = $query->find();
  185. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  186. }
  187. public function getBestReductionCatalog(
  188. ProductFamilyInterface $productFamily,
  189. ReductionCatalogInterface $reductionCatalog1,
  190. ReductionCatalogInterface $reductionCatalog2
  191. ) {
  192. $price1 = $this->priceSolver->getPriceWithTaxByReduction(
  193. $productFamily,
  194. $reductionCatalog1
  195. );
  196. $price2 = $this->priceSolver->getPriceWithTaxByReduction(
  197. $productFamily,
  198. $reductionCatalog2
  199. );
  200. if ($price1 > $price2) {
  201. return $reductionCatalog2;
  202. } else {
  203. return $reductionCatalog1;
  204. }
  205. }
  206. // setReductionForProductFamilies
  207. public function getWithReductions(
  208. $productFamilies,
  209. UserInterface $user = null,
  210. $organizeByCategory = false,
  211. $organizeByParentCategory = false,
  212. $onlyOnDiscount = false
  213. ) {
  214. $conditions = [
  215. 'productFamiliesIds' => [],
  216. 'categories' => [],
  217. 'productFamilies' => [],
  218. ];
  219. foreach ($productFamilies as $productFamily) {
  220. $conditions['productFamiliesIds'][] = $productFamily->getId();
  221. $conditions['productFamilies'][] = $productFamily;
  222. $conditions['categories'] = array_merge(
  223. $conditions['categories'],
  224. $productFamily->getProductCategories()->toArray()
  225. );
  226. }
  227. if ($productFamilies) {
  228. $reductionCatalogs = $this->reductionCatalogStore->getByProductFamiliesConditions(
  229. $conditions,
  230. $user
  231. );
  232. }
  233. $productFamiliesToReturn = array();
  234. foreach ($productFamilies as $productFamily) {
  235. // Cache : chargement de toutes les données manquantes (fetch eager ne fonctionne pas)
  236. $this->loadAllDatas($productFamily);
  237. foreach ($reductionCatalogs as $reductionCatalog) {
  238. $conditionProductFamilies = $conditionProductFamily = $conditionProductCategory = false;
  239. if ($reductionCatalog->getProductFamilies()->contains(
  240. $productFamily
  241. ) || $reductionCatalog->getProductFamilies()->isEmpty()) {
  242. $conditionProductFamilies = true;
  243. }
  244. if ($reductionCatalog->getProductFamily() == $productFamily || $reductionCatalog->getProductFamily(
  245. ) === null) {
  246. $conditionProductFamily = true;
  247. }
  248. foreach ($productFamily->getProductCategories() as $productCategory) {
  249. if ($reductionCatalog->getProductCategories()->contains(
  250. $productCategory
  251. ) || $reductionCatalog->getProductCategories()->isEmpty()) {
  252. $conditionProductCategory = true;
  253. }
  254. }
  255. if ($conditionProductFamilies && $conditionProductFamily && $conditionProductCategory) {
  256. if ($productFamily->getReductionCatalog()) {
  257. $productFamily->setReductionCatalog(
  258. $this->getBestReductionCatalog(
  259. $productFamily,
  260. $reductionCatalog,
  261. $productFamily->getReductionCatalog()
  262. )
  263. );
  264. } else {
  265. $productFamily->setReductionCatalog($reductionCatalog);
  266. }
  267. }
  268. }
  269. if (($onlyOnDiscount && $productFamily->getReductionCatalog()) || !$onlyOnDiscount) {
  270. if ($organizeByParentCategory) {
  271. $productCategories = $productFamily->getProductCategories();
  272. if ($productCategories && count($productCategories) > 0) {
  273. $parentCategory = $productCategories[0]->getParentCategory();
  274. if ($this->productCategorySolver->isDisplay($parentCategory, $user)) {
  275. if (!isset($productFamiliesToReturn[$parentCategory->getId()])) {
  276. $productFamiliesToReturn[$parentCategory->getId()] = [
  277. 'category' => $parentCategory,
  278. 'products' => []
  279. ];
  280. }
  281. $productFamiliesToReturn[$parentCategory->getId()]['products'][] = $productFamily;
  282. }
  283. }
  284. } elseif ($organizeByCategory) {
  285. foreach ($productFamily->getProductCategories() as $productCategory) {
  286. if ($this->isDisplay($productFamily)) {
  287. $productFamiliesToReturn[$productCategory->getId()][] = $productFamily;
  288. }
  289. }
  290. } else {
  291. if ($this->isDisplay($productFamily)) {
  292. $productFamiliesToReturn[] = $productFamily;
  293. }
  294. }
  295. }
  296. }
  297. if ($organizeByParentCategory) {
  298. uasort($productFamiliesToReturn, array($this, 'compMethodSortProductFamiliesByParentCategory'));
  299. }
  300. return $productFamiliesToReturn;
  301. }
  302. public function getOneByTitle(string $title): ?ProductFamilyInterface
  303. {
  304. $query = $this->createDefaultQuery();
  305. $query->filterByTitle($title);
  306. return $query->findOne();
  307. }
  308. }