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.

531 line
18KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Solver\Product;
  3. use Doctrine\Common\Collections\ArrayCollection;
  4. use Doctrine\Common\Collections\Collection;
  5. use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface;
  6. use Lc\CaracoleBundle\Model\Merchant\MerchantInterface;
  7. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  8. use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
  9. use Lc\CaracoleBundle\Model\Product\ProductInterface;
  10. use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
  11. use Lc\CaracoleBundle\Model\Section\SectionInterface;
  12. class ProductFamilySolver
  13. {
  14. protected ProductSolver $productSolver;
  15. protected ProductFamilySectionPropertySolver $productFamilySectionPropertySolver;
  16. protected ProductCategorySolver $productCategorySolver;
  17. public function __construct(
  18. ProductSolver $productSolver,
  19. ProductFamilySectionPropertySolver $productFamilySectionPropertySolver,
  20. ProductCategorySolver $productCategorySolver
  21. ) {
  22. $this->productSolver = $productSolver;
  23. $this->productFamilySectionPropertySolver = $productFamilySectionPropertySolver;
  24. $this->productCategorySolver = $productCategorySolver;
  25. }
  26. public static function getBehaviorCountStockChoices(): array
  27. {
  28. return [
  29. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE,
  30. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT,
  31. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY,
  32. ];
  33. }
  34. public static function getWaringMessageTypeChoices(): array
  35. {
  36. return [
  37. ProductFamilyModel::WARNING_MESSAGE_TYPE_ERROR,
  38. ProductFamilyModel::WARNING_MESSAGE_TYPE_INFO,
  39. ProductFamilyModel::WARNING_MESSAGE_TYPE_SUCCESS,
  40. ProductFamilyModel::WARNING_MESSAGE_TYPE_WARNING,
  41. ];
  42. }
  43. public static function getBehaviorAddToCartChoices(): array
  44. {
  45. return [
  46. ProductFamilyModel::BEHAVIOR_ADD_TO_CART_MULTIPLE,
  47. ProductFamilyModel::BEHAVIOR_ADD_TO_CART_SIMPLE,
  48. ];
  49. }
  50. public static function getBehaviorPriceChoices(): array
  51. {
  52. return [
  53. ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE,
  54. ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT,
  55. ];
  56. }
  57. public static function getTypeExpirationDateChoices(): array
  58. {
  59. return [
  60. ProductFamilyModel::TYPE_EXPIRATION_DATE_DLC,
  61. ProductFamilyModel::TYPE_EXPIRATION_DATE_DDM,
  62. ProductFamilyModel::TYPE_EXPIRATION_DATE_DLUO,
  63. ];
  64. }
  65. public static function getBehaviorExpirationDateChoices(): array
  66. {
  67. return [
  68. ProductFamilyModel::BEHAVIOR_EXPIRATION_DATE_BY_PRODUCT_FAMILY,
  69. ProductFamilyModel::BEHAVIOR_EXPIRATION_DATE_BY_PRODUCT,
  70. ];
  71. }
  72. public static function getBehaviorDisplaySaleChoices(): array
  73. {
  74. return [
  75. ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_MEASURE,
  76. ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_QUANTITY,
  77. ];
  78. }
  79. public function countProductFamiliesOrganizedByParentCategory(array $categories): int
  80. {
  81. $count = 0;
  82. foreach ($categories as $category) {
  83. $count += count($category['products']);
  84. }
  85. return $count;
  86. }
  87. public function getAvailableQuantityInherited(ProductFamilyInterface $productFamily)
  88. {
  89. $availableQuantity = 0;
  90. switch ($productFamily->getBehaviorCountStock()) {
  91. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE :
  92. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :
  93. $availableQuantity = $productFamily->getAvailableQuantity();
  94. break;
  95. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
  96. foreach ($this->getProductsOnline($productFamily) as $product) {
  97. $availableQuantity += $this->productSolver->getAvailableQuantityInherited($product);
  98. }
  99. break;
  100. }
  101. return $availableQuantity;
  102. }
  103. public function getAvailableQuantitySupplierInherited(ProductFamilyInterface $productFamily)
  104. {
  105. $availableQuantity = 0;
  106. switch ($productFamily->getBehaviorCountStock()) {
  107. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE :
  108. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :
  109. $availableQuantity = $productFamily->getAvailableQuantitySupplier();
  110. break;
  111. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
  112. foreach ($this->getProductsOnline($productFamily) as $product) {
  113. $availableQuantity += $this->productSolver->getAvailableQuantitySupplierInherited($product);
  114. }
  115. break;
  116. }
  117. return $availableQuantity;
  118. }
  119. public function getTaxRateInherited(ProductPropertyInterface $productFamily)
  120. {
  121. if ($productFamily instanceof ProductInterface) {
  122. $productFamily = $productFamily->getProductFamily();
  123. }
  124. if ($productFamily->getTaxRate()) {
  125. return $productFamily->getTaxRate();
  126. } else {
  127. return $productFamily->getProductFamilySectionProperties()[0]->getSection()->getMerchant()->getTaxRate();
  128. }
  129. }
  130. public function getProductsOnline(ProductFamilyInterface $productFamily): Collection
  131. {
  132. $products = $productFamily->getProducts();
  133. $productsOnlineArray = new ArrayCollection();
  134. foreach ($products as $product) {
  135. if ($product->getStatus() == 1 && $product->getOriginProduct() != true) {
  136. $productsOnlineArray[] = $product;
  137. }
  138. }
  139. return $productsOnlineArray;
  140. }
  141. public function getReductionCatalogInherited(ProductFamilyInterface $productFamily): ?ReductionCatalogInterface
  142. {
  143. return $productFamily->getReductionCatalog();
  144. }
  145. public function getProductCategoryParent(ProductFamilyInterface $productFamily, SectionInterface $section)
  146. {
  147. $productCategories = $productFamily->getProductCategories();
  148. if (count($productCategories) > 0) {
  149. foreach ($productCategories as $productCategory) {
  150. if ($productCategory->getSection()->getId() == $section->getId()
  151. && $productCategory->getParent() !== null) {
  152. return $productCategory->getParent();
  153. }
  154. }
  155. }
  156. return false;
  157. }
  158. public function getProductCategoryChild(ProductFamilyInterface $productFamily, SectionInterface $section)
  159. {
  160. $productCategories = $productFamily->getProductCategories();
  161. foreach ($productCategories as $productCategory) {
  162. if ($productCategory->getParent() && $productCategory->getSection() == $section) {
  163. return $productCategory;
  164. }
  165. }
  166. return false;
  167. }
  168. public function isPropertyNoveltyOnline(ProductFamilyInterface $productFamily): ?bool
  169. {
  170. if ($productFamily->getPropertyNoveltyExpirationDate()) {
  171. $now = new \DateTime();
  172. if ($now <= $productFamily->getPropertyNoveltyExpirationDate()) {
  173. return true;
  174. }
  175. }
  176. return false;
  177. }
  178. public function countProperties(ProductFamilyInterface $productFamily): bool
  179. {
  180. $count = 0;
  181. $count += (int)strlen($productFamily->getPropertyOrganicLabel()) > 0;
  182. $count += (int)strlen($productFamily->getPropertyWeight()) > 0;
  183. $count += (int)strlen($productFamily->getPropertyFragrances()) > 0;
  184. $count += (int)strlen($productFamily->getPropertyComposition()) > 0;
  185. $count += (int)strlen($productFamily->getPropertyAllergens()) > 0;
  186. $count += (int)strlen($productFamily->getPropertyAlcoholLevel()) > 0;
  187. $count += (int)strlen($productFamily->getPropertyCharacteristics()) > 0;
  188. $count += (int)strlen($productFamily->getPropertyFeature()) > 0;
  189. $count += (int)strlen($productFamily->getPropertyPackaging()) > 0;
  190. $count += (int)strlen($productFamily->getPropertyQuantity()) > 0;
  191. $count += (int)strlen($productFamily->getPropertyVariety()) > 0;
  192. $count += (int)($productFamily->getPropertyExpirationDate() != null);
  193. return $count;
  194. }
  195. public function hasProductsWithVariousWeight(ProductFamilyInterface $productFamily)
  196. {
  197. if ($productFamily->getActiveProducts()) {
  198. $arrayCountProducts = [];
  199. $products = $this->getProductsOnline($productFamily);
  200. foreach ($products as $product) {
  201. $titleProduct = $this->productSolver->getTitleInherited($product);
  202. if (!isset($arrayCountProducts[$titleProduct])) {
  203. $arrayCountProducts[$titleProduct] = [];
  204. }
  205. if (!in_array(
  206. $this->productSolver->getQuantityLabelInherited($product),
  207. $arrayCountProducts[$titleProduct]
  208. )) {
  209. $arrayCountProducts[$titleProduct][] = $this->productSolver->getQuantityLabelInherited($product);
  210. }
  211. if (count($arrayCountProducts[$titleProduct]) > 1) {
  212. return true;
  213. }
  214. }
  215. }
  216. return false;
  217. }
  218. public function getProductsGroupByTitle(ProductFamilyInterface $productFamily): array
  219. {
  220. $arrayProductsGroupByTitle = [];
  221. $products = $this->getProductsOnline($productFamily);
  222. foreach ($products as $product) {
  223. if ($product->getStatus() == 1) {
  224. $titleProduct = $this->productSolver->getTitleInherited($product);
  225. if (!isset($arrayProductsGroupByTitle[$titleProduct])) {
  226. $arrayProductsGroupByTitle[$titleProduct] = [];
  227. }
  228. $arrayProductsGroupByTitle[$titleProduct][] = $product;
  229. }
  230. }
  231. return $arrayProductsGroupByTitle;
  232. }
  233. public function getQuantityTitle(ProductFamilyInterface $productFamily, ProductInterface $product)
  234. {
  235. $title = $this->productSolver->getQuantityLabelInherited($product);
  236. if ($this->hasProductsWithVariousWeight($productFamily)) {
  237. $title .= ', ' . $this->productSolver->getTitleInherited($product);
  238. }
  239. return $title;
  240. }
  241. public function getOriginProduct(ProductFamilyInterface $productFamily): ?ProductInterface
  242. {
  243. $products = $productFamily->getProducts();
  244. foreach ($products as $product) {
  245. if ($product->getOriginProduct()) {
  246. return $product;
  247. }
  248. }
  249. return null;
  250. }
  251. public function getOriginProductOnline(ProductFamilyInterface $productFamily): ?ProductInterface
  252. {
  253. $originProduct = $this->getOriginProduct($productFamily);
  254. if ($originProduct->getStatus() == 1) {
  255. return $originProduct;
  256. } else {
  257. return null;
  258. }
  259. }
  260. public function hasOneProductOnline(ProductFamilyInterface $productFamily)
  261. {
  262. if (($productFamily->getActiveProducts() && count($this->getProductsOnline($productFamily)) > 0)
  263. || (!$productFamily->getActiveProducts() && $this->getOriginProduct($productFamily))) {
  264. return true;
  265. }
  266. return false;
  267. }
  268. public function getFieldBuyingPrice(ProductFamilyInterface $productFamily): string
  269. {
  270. if ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
  271. return 'buyingPrice';
  272. } elseif ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
  273. return 'buyingPriceByRefUnit';
  274. }
  275. }
  276. public function getFieldPrice(ProductFamilyInterface $productFamily): string
  277. {
  278. if ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
  279. return 'price';
  280. } elseif ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
  281. return 'priceByRefUnit';
  282. }
  283. }
  284. public function getBehaviorPriceInherited(ProductFamilyInterface $productFamily): string
  285. {
  286. return $productFamily->getBehaviorPrice();
  287. }
  288. public function getBuyingPriceByRefUnitInherited(ProductFamilyInterface $productFamily): ?float
  289. {
  290. return $productFamily->getBuyingPriceByRefUnit();
  291. }
  292. public function getBuyingPriceInherited(ProductFamilyInterface $productFamily): ?float
  293. {
  294. return $productFamily->getBuyingPrice();
  295. }
  296. public function getPriceByRefUnitInherited(ProductFamilyInterface $productFamily): ?float
  297. {
  298. return $productFamily->getPriceByRefUnit();
  299. }
  300. public function getQuantityInherited(ProductFamilyInterface $productFamily): ?float
  301. {
  302. if ($productFamily->getQuantity()) {
  303. return $productFamily->getQuantity();
  304. } else {
  305. return 1;
  306. }
  307. }
  308. public function getUnitInherited(ProductFamilyInterface $productFamily)
  309. {
  310. return $productFamily->getUnit();
  311. }
  312. public function getPriceInherited(ProductFamilyInterface $productFamily)
  313. {
  314. return $productFamily->getPrice();
  315. }
  316. public function getSummaryQualityLabels(ProductFamilyInterface $productFamily): string
  317. {
  318. $strLabels = '';
  319. $qualityLabelArray = $productFamily->getQualityLabels()->toArray();
  320. foreach ($qualityLabelArray as $index => $qualityLabel) {
  321. $strLabels .= $qualityLabel->getTitle();
  322. if ($index !== array_key_last($qualityLabelArray)) {
  323. $strLabels .= ', ';
  324. }
  325. }
  326. return $strLabels;
  327. }
  328. public function hasQualityLabel(ProductFamilyInterface $productFamily): bool
  329. {
  330. $qualityLabels = $productFamily->getQualityLabels();
  331. return $qualityLabels && count($qualityLabels) > 0;
  332. }
  333. public function getOrganicLabel(ProductFamilyInterface $productFamily)
  334. {
  335. return $this->getQualityLabelByArray($productFamily, ProductFamilyModel::$organicLabels);
  336. }
  337. public function getGeographicLabel(ProductFamilyInterface $productFamily)
  338. {
  339. return $this->getQualityLabelByArray($productFamily, ProductFamilyModel::$geographicLabels);
  340. }
  341. public function getQualityLabelByArray(ProductFamilyInterface $productFamily, array $labelArray)
  342. {
  343. $qualityLabelArray = $productFamily->getQualityLabels();
  344. foreach ($qualityLabelArray as $qualityLabel) {
  345. if (in_array($qualityLabel->getDevAlias(), $labelArray)) {
  346. return $qualityLabel;
  347. }
  348. }
  349. return false;
  350. }
  351. public function hasOrganicLabel(ProductFamilyInterface $productFamily)
  352. {
  353. return $this->hasQualityLabelByArray($productFamily, ProductFamilyModel::$organicLabels);
  354. }
  355. public function hasGeographicLabel(ProductFamilyInterface $productFamily)
  356. {
  357. return $this->hasQualityLabelByArray($productFamily, ProductFamilyModel::$geographicLabels);
  358. }
  359. public function hasQualityLabelByArray(ProductFamilyInterface $productFamily, array $labelArray)
  360. {
  361. $qualityLabelArray = $productFamily->getQualityLabels();
  362. foreach ($qualityLabelArray as $qualityLabel) {
  363. if (in_array($qualityLabel->getDevAlias(), $labelArray)) {
  364. return true;
  365. }
  366. }
  367. return false;
  368. }
  369. public function getSection(ProductFamilyInterface $productFamily): ?SectionInterface
  370. {
  371. foreach ($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) {
  372. if ($productFamilySectionProperty->getStatus()) {
  373. return $productFamilySectionProperty->getSection();
  374. }
  375. }
  376. return null;
  377. }
  378. public function getMerchant(ProductFamilyInterface $productFamily): ?MerchantInterface
  379. {
  380. foreach ($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) {
  381. return $productFamilySectionProperty->getSection()->getMerchant();
  382. }
  383. return null;
  384. }
  385. public function isInSection(ProductFamilyInterface $productFamily, SectionInterface $section): bool
  386. {
  387. foreach ($productFamily->getProductFamilySectionProperties() as $productFamilySectionProperty) {
  388. if ($productFamilySectionProperty->getSection()->getId() == $section->getId(
  389. ) && $productFamilySectionProperty->getStatus()) {
  390. return true;
  391. }
  392. }
  393. return false;
  394. }
  395. public function isCategoriesOnlineInSection(ProductFamilyInterface $productFamily, SectionInterface $section): bool
  396. {
  397. $isCategoriesOnlineInSection = false;
  398. foreach ($productFamily->getProductCategories() as $productCatgory) {
  399. if ($productCatgory->getSection() === $section && $this->productCategorySolver->isOnline($productCatgory)) {
  400. $isCategoriesOnlineInSection = true;
  401. }
  402. }
  403. return $isCategoriesOnlineInSection;
  404. }
  405. public function getTitleProduct(ProductInterface $product)
  406. {
  407. $productFamily = $product->getProductFamily();
  408. $title = $product->getProductFamily()->getTitle();
  409. if ($product->getTitle() && strlen($product->getTitle())) {
  410. $title .= ' - ' . $product->getTitle();
  411. }
  412. if ($this->hasProductsWithVariousWeight($productFamily)) {
  413. $title .= ' - ' . $this->productSolver->getQuantityLabelInherited($product);
  414. }
  415. return $title;
  416. }
  417. public function isReductionCatalogDisplayed(ProductFamilyInterface $productFamily): bool
  418. {
  419. return $this->hasReductionCatalog($productFamily) && $productFamily->getReductionCatalog()->isDisplayed();
  420. }
  421. public function hasReductionCatalog(ProductFamilyInterface $productFamily): bool
  422. {
  423. return (bool)$productFamily->getReductionCatalog();
  424. }
  425. }