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.

358 lines
12KB

  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. $productFamiliesCategory = $this->getByCategory($category);
  57. foreach ($productFamiliesCategory as $productFamily) {
  58. $productFamiliesArray[$productFamily->getId()] = $productFamily;
  59. }
  60. uasort($productFamiliesArray, array($this, 'compMethodSortProductFamiliesByPosition'));
  61. }
  62. return $this->getWithReductions($productFamiliesArray, $user, true);
  63. }
  64. private function compMethodSortProductFamiliesByPosition($a, $b)
  65. {
  66. return $a->getPosition() > $b->getPosition();
  67. }
  68. // getProductFamiliesByCategory
  69. public function getByCategory(
  70. ProductCategoryInterface $productCategory,
  71. $query = null
  72. ) {
  73. $query = $this->createDefaultQuery($query);
  74. $query
  75. ->filterIsOnline()
  76. ->filterByProductCategory($productCategory);
  77. return $query->find();
  78. }
  79. //TODO ajouter status en donné de contexte pour éviter ce truc
  80. public function getByCategoryOnlineAndOffline(
  81. ProductCategoryInterface $productCategory,
  82. $query = null
  83. ) {
  84. $query = $this->createDefaultQuery($query);
  85. $query
  86. ->filterByProductCategory($productCategory);
  87. return $query->find();
  88. }
  89. // getProductFamiliesNovelties
  90. public function getNovelty($user = null, $organizeByParentCategory = true, $query = null)
  91. {
  92. $query = $this->createDefaultQuery($query);
  93. $query
  94. ->filterByPropertyNoveltyExpirationDate()
  95. ->filterIsOnline();
  96. $results = $query->find();
  97. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  98. }
  99. public function getCachedNovelty($user = null, $organizeByParentCategory = true, $query = null): array
  100. {
  101. $productFamilyStore = $this;
  102. return $this->cache->get($this->getCacheKeyNovelty(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) {
  103. $item->expiresAfter(3600);
  104. return $productFamilyStore->getNovelty($user, $organizeByParentCategory, $query);
  105. });
  106. }
  107. public function deleteCacheNovelty(): void
  108. {
  109. $this->cache->delete($this->getCacheKeyNovelty());
  110. }
  111. public function getCacheKeyNovelty()
  112. {
  113. return 'products_novelty_'.$this->section->getId();
  114. }
  115. // getProductFamiliesOrganics
  116. public function getOrganic($user = null, $organizeByParentCategory = true, $query = null)
  117. {
  118. $query = $this->createDefaultQuery($query);
  119. $query
  120. ->filterIsOrganicLabel()
  121. ->filterIsOnline();
  122. $results = $query->find();
  123. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  124. }
  125. // getProductFamiliesOnDiscount
  126. public function getDiscount($user = null, $organizeByParentCategory = true, $query = null)
  127. {
  128. return $this->getWithReductions($this->getOnline($query), $user, false, $organizeByParentCategory, true);
  129. }
  130. public function getCachedDiscount($user = null, $organizeByParentCategory = true, $query = null): array
  131. {
  132. $productFamilyStore = $this;
  133. return $this->cache->get($this->getCacheKeyDiscount(), function (ItemInterface $item) use ($productFamilyStore, $user, $organizeByParentCategory, $query) {
  134. $item->expiresAfter(3600);
  135. return $productFamilyStore->getDiscount($user, $organizeByParentCategory, $query);
  136. });
  137. }
  138. public function deleteCacheDiscount(): void
  139. {
  140. $this->cache->delete($this->getCacheKeyDiscount());
  141. }
  142. public function getCacheKeyDiscount()
  143. {
  144. return 'products_discount_'.$this->section->getId();
  145. }
  146. public function loadAllDatas(ProductFamilyInterface $productFamily)
  147. {
  148. $productFamily->getProductFamilySectionProperties()->toArray();
  149. }
  150. // getProductFamiliesFavorites
  151. public function getFavorite($user = null, $organizeByParentCategory = true, $query = null)
  152. {
  153. if ($user) {
  154. return $this->getWithReductions(
  155. $user->getFavoriteProductFamilies(),
  156. $user,
  157. false,
  158. $organizeByParentCategory
  159. );
  160. }
  161. return [];
  162. }
  163. // findByTerms
  164. public function getByTerms(
  165. $terms,
  166. $maxResults = false,
  167. $organizeByParentCategory = false,
  168. $user = null,
  169. $query = null
  170. ) {
  171. $query = $this->createDefaultQuery($query);
  172. $query->filterIsOnline();
  173. $query->filterByTerms($terms);
  174. $query->groupBy('id');
  175. if ($maxResults) {
  176. $query->limit($maxResults);
  177. }
  178. $results = $query->find();
  179. return $this->getWithReductions($results, $user, false, $organizeByParentCategory);
  180. }
  181. public function getBestReductionCatalog(
  182. ProductFamilyInterface $productFamily,
  183. ReductionCatalogInterface $reductionCatalog1,
  184. ReductionCatalogInterface $reductionCatalog2
  185. ) {
  186. $price1 = $this->priceSolver->getPriceWithTaxByReduction(
  187. $productFamily,
  188. $reductionCatalog1
  189. );
  190. $price2 = $this->priceSolver->getPriceWithTaxByReduction(
  191. $productFamily,
  192. $reductionCatalog2
  193. );
  194. if ($price1 > $price2) {
  195. return $reductionCatalog2;
  196. } else {
  197. return $reductionCatalog1;
  198. }
  199. }
  200. // setReductionForProductFamilies
  201. public function getWithReductions(
  202. $productFamilies,
  203. UserInterface $user = null,
  204. $organizeByCategory = false,
  205. $organizeByParentCategory = false,
  206. $onlyOnDiscount = false
  207. ) {
  208. $conditions = [
  209. 'productFamiliesIds' => [],
  210. 'categories' => [],
  211. 'productFamilies' => [],
  212. ];
  213. foreach ($productFamilies as $productFamily) {
  214. $conditions['productFamiliesIds'][] = $productFamily->getId();
  215. $conditions['productFamilies'][] = $productFamily;
  216. $conditions['categories'] = array_merge(
  217. $conditions['categories'],
  218. $productFamily->getProductCategories()->toArray()
  219. );
  220. }
  221. if ($productFamilies) {
  222. $reductionCatalogs = $this->reductionCatalogStore->getByProductFamiliesConditions(
  223. $conditions,
  224. $user
  225. );
  226. }
  227. $productFamiliesToReturn = array();
  228. foreach ($productFamilies as $productFamily) {
  229. // Cache : chargement de toutes les données manquantes (fetch eager ne fonctionne pas)
  230. $this->loadAllDatas($productFamily);
  231. foreach ($reductionCatalogs as $reductionCatalog) {
  232. $conditionProductFamilies = $conditionProductFamily = $conditionProductCategory = false;
  233. if ($reductionCatalog->getProductFamilies()->contains(
  234. $productFamily
  235. ) || $reductionCatalog->getProductFamilies()->isEmpty()) {
  236. $conditionProductFamilies = true;
  237. }
  238. if ($reductionCatalog->getProductFamily() == $productFamily || $reductionCatalog->getProductFamily(
  239. ) === null) {
  240. $conditionProductFamily = true;
  241. }
  242. foreach ($productFamily->getProductCategories() as $productCategory) {
  243. if ($reductionCatalog->getProductCategories()->contains(
  244. $productCategory
  245. ) || $reductionCatalog->getProductCategories()->isEmpty()) {
  246. $conditionProductCategory = true;
  247. }
  248. }
  249. if ($conditionProductFamilies && $conditionProductFamily && $conditionProductCategory) {
  250. if ($productFamily->getReductionCatalog()) {
  251. $productFamily->setReductionCatalog(
  252. $this->getBestReductionCatalog(
  253. $productFamily,
  254. $reductionCatalog,
  255. $productFamily->getReductionCatalog()
  256. )
  257. );
  258. } else {
  259. $productFamily->setReductionCatalog($reductionCatalog);
  260. }
  261. }
  262. }
  263. if (($onlyOnDiscount && $productFamily->getReductionCatalog()) || !$onlyOnDiscount) {
  264. if ($organizeByParentCategory) {
  265. $productCategories = $productFamily->getProductCategories();
  266. if ($productCategories && count($productCategories) > 0) {
  267. $parentCategory = $productCategories[0]->getParentCategory();
  268. if ($this->productCategorySolver->isDisplay($parentCategory, $user)) {
  269. if (!isset($productFamiliesToReturn[$parentCategory->getId()])) {
  270. $productFamiliesToReturn[$parentCategory->getId()] = [
  271. 'category' => $parentCategory,
  272. 'products' => []
  273. ];
  274. }
  275. $productFamiliesToReturn[$parentCategory->getId()]['products'][] = $productFamily;
  276. }
  277. }
  278. } elseif ($organizeByCategory) {
  279. foreach ($productFamily->getProductCategories() as $productCategory) {
  280. if ($this->isDisplay($productFamily)) {
  281. $productFamiliesToReturn[$productCategory->getId()][] = $productFamily;
  282. }
  283. }
  284. } else {
  285. if ($this->isDisplay($productFamily)) {
  286. $productFamiliesToReturn[] = $productFamily;
  287. }
  288. }
  289. }
  290. }
  291. if ($organizeByParentCategory) {
  292. uasort($productFamiliesToReturn, array($this, 'compMethodSortProductFamiliesByParentCategory'));
  293. }
  294. return $productFamiliesToReturn;
  295. }
  296. }