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.

418 lines
14KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Solver\Product;
  3. use Doctrine\Common\Collections\ArrayCollection;
  4. use Doctrine\Common\Collections\Collection;
  5. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  6. use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
  7. use Lc\CaracoleBundle\Model\Product\ProductInterface;
  8. use Lc\CaracoleBundle\Model\Reduction\ReductionCatalogInterface;
  9. use Lc\CaracoleBundle\Solver\Price\PriceSolver;
  10. class ProductFamilySolver
  11. {
  12. protected PriceSolver $priceSolver;
  13. public function __construct(PriceSolver $priceSolver)
  14. {
  15. $this->priceSolver = $priceSolver;
  16. }
  17. public function getMultiplyingFactor(ProductFamilyInterface $productFamily)
  18. {
  19. if ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
  20. if ($productFamily->getBuyingPrice() > 0) {
  21. return number_format(
  22. $this->priceSolver->getPriceWithTax($productFamily) / $productFamily->getBuyingPrice(),
  23. 3
  24. );
  25. }
  26. } elseif ($productFamily->getBehaviorPrice() == ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
  27. if ($productFamily->getBuyingPriceByRefUnit() > 0) {
  28. return number_format(
  29. $this->priceSolver->getPriceByRefUnitWithTax(
  30. $productFamily
  31. ) / $productFamily->getBuyingPriceByRefUnit(),
  32. 3
  33. );
  34. }
  35. }
  36. }
  37. public function getCheapestProduct(ProductFamilyInterface $productFamily)
  38. {
  39. $priceSolver = $this->priceSolver;
  40. return $this->getCheapestOrMostExpensiveProduct(
  41. $productFamily,
  42. function ($a, $b) use ($priceSolver) {
  43. return $priceSolver->getPriceWithTaxAndReduction(
  44. $a
  45. ) > $priceSolver->getPriceWithTaxAndReduction($b);
  46. },
  47. true
  48. );
  49. }
  50. public function getCheapestProductByRefUnit(ProductFamilyInterface $productFamily)
  51. {
  52. $priceSolver = $this->priceSolver;
  53. return $this->getCheapestOrMostExpensiveProduct(
  54. $productFamily,
  55. function ($a, $b) use ($priceSolver) {
  56. return $priceSolver->getPriceByRefUnitWithTaxAndReduction(
  57. $a
  58. ) > $priceSolver->getPriceByRefUnitWithTaxAndReduction($b);
  59. },
  60. false
  61. );
  62. }
  63. public function getMostExpensiveProductByRefUnit(ProductFamilyInterface $productFamily)
  64. {
  65. $priceSolver = $this->priceSolver;
  66. return $this->getCheapestOrMostExpensiveProduct(
  67. $productFamily,
  68. function ($a, $b) use ($priceSolver) {
  69. return $priceSolver->getPriceByRefUnitWithTaxAndReduction(
  70. $a
  71. ) < $priceSolver->getPriceByRefUnitWithTaxAndReduction($b);
  72. },
  73. false
  74. );
  75. }
  76. private function getCheapestOrMostExpensiveProduct(
  77. ProductFamilyInterface $productFamily,
  78. $comparisonFunction,
  79. $returnSelfIfNotActiveProducts
  80. ) {
  81. if ($productFamily->getActiveProducts()) {
  82. $products = $this->getProductsOnline($productFamily)->getValues();
  83. if (count($products) > 0) {
  84. usort($products, $comparisonFunction);
  85. return $products[0];
  86. }
  87. } else {
  88. return $this->getOriginProduct($productFamily);
  89. }
  90. if ($returnSelfIfNotActiveProducts) {
  91. return $productFamily;
  92. } else {
  93. return false;
  94. }
  95. }
  96. public function getAvailableQuantityInherited(ProductFamilyInterface $productFamily)
  97. {
  98. $availableQuantity = 0;
  99. switch ($productFamily->getBehaviorCountStock()) {
  100. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE :
  101. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :
  102. $availableQuantity = $productFamily->getAvailableQuantity();
  103. break;
  104. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
  105. foreach ($this->getProductsOnline($productFamily) as $product) {
  106. $availableQuantity += $product->getAvailableQuantityInherited();
  107. }
  108. break;
  109. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_UNLIMITED :
  110. $availableQuantity = false;
  111. break;
  112. }
  113. return $availableQuantity;
  114. }
  115. public function getTaxRateInherited(ProductFamilyInterface $productFamily)
  116. {
  117. if ($productFamily->getTaxRate()) {
  118. return $productFamily->getTaxRate();
  119. } else {
  120. return $productFamily->getSection()->getMerchant()->getTaxRate();
  121. }
  122. }
  123. public function getProductsOnline(ProductFamilyInterface $productFamily): Collection
  124. {
  125. $products = $productFamily->getProducts();
  126. $productsOnlineArray = new ArrayCollection();
  127. foreach ($products as $product) {
  128. if ($product->getStatus() == 1 && $product->getOriginProduct() != true) {
  129. $productsOnlineArray[] = $product;
  130. }
  131. }
  132. return $productsOnlineArray;
  133. }
  134. public function getReductionCatalogInherited(ProductFamilyInterface $productFamily): ?ReductionCatalogInterface
  135. {
  136. return $productFamily->getReductionCatalog();
  137. }
  138. public function getProductCategoryParent(ProductFamilyInterface $productFamily)
  139. {
  140. $productCategories = $productFamily->getProductCategories();
  141. if (count($productCategories) > 0) {
  142. return $productCategories[0]->getParent();
  143. }
  144. return false;
  145. }
  146. public function getProductCategoryChild(ProductFamilyInterface $productFamily)
  147. {
  148. $productCategories = $productFamily->getProductCategories();
  149. foreach ($productCategories as $productCategory) {
  150. if ($productCategory->getParent()) {
  151. return $productCategory;
  152. }
  153. }
  154. return false;
  155. }
  156. public function isPropertyNoveltyOnline(ProductFamilyInterface $productFamily): ?bool
  157. {
  158. if ($productFamily->getPropertyNoveltyExpirationDate()) {
  159. $now = new \DateTime();
  160. if ($now <= $productFamily->getPropertyNoveltyExpirationDate()) {
  161. return true;
  162. }
  163. }
  164. return false;
  165. }
  166. public function countProperties(ProductFamilyInterface $productFamily): bool
  167. {
  168. $count = 0;
  169. $count += (int)strlen($productFamily->getPropertyOrganicLabel()) > 0;
  170. $count += (int)strlen($productFamily->getPropertyWeight()) > 0;
  171. $count += (int)strlen($productFamily->getPropertyFragrances()) > 0;
  172. $count += (int)strlen($productFamily->getPropertyComposition()) > 0;
  173. $count += (int)strlen($productFamily->getPropertyAllergens()) > 0;
  174. $count += (int)strlen($productFamily->getPropertyAlcoholLevel()) > 0;
  175. $count += (int)strlen($productFamily->getPropertyCharacteristics()) > 0;
  176. $count += (int)strlen($productFamily->getPropertyFeature()) > 0;
  177. $count += (int)strlen($productFamily->getPropertyPackaging()) > 0;
  178. $count += (int)strlen($productFamily->getPropertyQuantity()) > 0;
  179. $count += (int)strlen($productFamily->getPropertyVariety()) > 0;
  180. $count += (int)($productFamily->getPropertyExpirationDate() != null);
  181. return $count;
  182. }
  183. public function hasProductsWithVariousWeight(ProductFamilyInterface $productFamily)
  184. {
  185. if ($productFamily->getActiveProducts()) {
  186. $arrayCountProducts = [];
  187. $products = $this->getProductsOnline($productFamily);
  188. foreach ($products as $product) {
  189. $titleProduct = $product->getTitleInherited();
  190. if (!isset($arrayCountProducts[$titleProduct])) {
  191. $arrayCountProducts[$titleProduct] = [];
  192. }
  193. if (!in_array($product->getQuantityLabelInherited(), $arrayCountProducts[$titleProduct])) {
  194. $arrayCountProducts[$titleProduct][] = $product->getQuantityLabelInherited();
  195. }
  196. if (count($arrayCountProducts[$titleProduct]) > 1) {
  197. return true;
  198. }
  199. }
  200. }
  201. return false;
  202. }
  203. public function getProductsGroupByTitle(ProductFamilyInterface $productFamily): array
  204. {
  205. $arrayProductsGroupByTitle = [];
  206. $products = $this->getProductsOnline($productFamily);
  207. foreach ($products as $product) {
  208. if ($product->getStatus() == 1) {
  209. $titleProduct = $product->getTitleInherited();
  210. if (!isset($arrayProductsGroupByTitle[$titleProduct])) {
  211. $arrayProductsGroupByTitle[$titleProduct] = [];
  212. }
  213. $arrayProductsGroupByTitle[$titleProduct][] = $product;
  214. }
  215. }
  216. return $arrayProductsGroupByTitle;
  217. }
  218. public function getOriginProduct(ProductFamilyInterface $productFamily): ?ProductInterface
  219. {
  220. $products = $productFamily->getProducts();
  221. foreach ($products as $product) {
  222. if ($product->getOriginProduct()) {
  223. return $product;
  224. }
  225. }
  226. return null;
  227. }
  228. public function getOriginProductOnline(ProductFamilyInterface $productFamily): ?ProductInterface
  229. {
  230. $originProduct = $this->getOriginProduct($productFamily);
  231. if ($originProduct->getStatus() == 1) {
  232. return $originProduct;
  233. } else {
  234. return null;
  235. }
  236. }
  237. public function hasOneProductOnline(ProductFamilyInterface $productFamily)
  238. {
  239. if (($productFamily->getActiveProducts() && count($this->getProductsOnline($productFamily)) > 0)
  240. || (!$productFamily->getActiveProducts() && $this->getOriginProduct($productFamily))) {
  241. return true;
  242. }
  243. return false;
  244. }
  245. public function getFieldBuyingPrice(ProductFamilyInterface $productFamily): string
  246. {
  247. if ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
  248. return 'buyingPrice';
  249. } elseif ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
  250. return 'buyingPriceByRefUnit';
  251. }
  252. }
  253. public function getFieldPrice(ProductFamilyInterface $productFamily): string
  254. {
  255. if ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE) {
  256. return 'price';
  257. } elseif ($productFamily->getBehaviorPrice() === ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT) {
  258. return 'priceByRefUnit';
  259. }
  260. }
  261. public function getBehaviorPriceInherited(ProductFamilyInterface $productFamily) :string
  262. {
  263. return $productFamily->getBehaviorPrice();
  264. }
  265. public function getBehaviorCountStockChoices(): array
  266. {
  267. return [
  268. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE,
  269. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT,
  270. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY,
  271. ProductFamilyModel::BEHAVIOR_COUNT_STOCK_UNLIMITED,
  272. ];
  273. }
  274. public function getBehaviorDisplaySaleChoices(): array
  275. {
  276. return [
  277. ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_MEASURE,
  278. ProductFamilyModel::BEHAVIOR_DISPLAY_SALE_BY_QUANTITY,
  279. ];
  280. }
  281. public function getBehaviorStockCycleChoices(): array
  282. {
  283. return [
  284. ProductFamilyModel::BEHAVIOR_STOCK_CYCLE_NON_RENEWABLE,
  285. ProductFamilyModel::BEHAVIOR_STOCK_CYCLE_RENEWABLE,
  286. ProductFamilyModel::BEHAVIOR_STOCK_CYCLE_RENEWABLE_VALIDATION,
  287. ];
  288. }
  289. public function getWaringMessageTypeChoices(): array
  290. {
  291. return [
  292. ProductFamilyModel::WARNING_MESSAGE_TYPE_ERROR,
  293. ProductFamilyModel::WARNING_MESSAGE_TYPE_INFO,
  294. ProductFamilyModel::WARNING_MESSAGE_TYPE_SUCCESS,
  295. ProductFamilyModel::WARNING_MESSAGE_TYPE_WARNING,
  296. ];
  297. }
  298. public function getBehaviorAddToCartChoices(): array
  299. {
  300. return [
  301. ProductFamilyModel::BEHAVIOR_ADD_TO_CART_MULTIPLE,
  302. ProductFamilyModel::BEHAVIOR_ADD_TO_CART_SIMPLE,
  303. ];
  304. }
  305. public function getBehaviorPriceChoices(): array
  306. {
  307. return [
  308. ProductFamilyModel::BEHAVIOR_PRICE_BY_PIECE,
  309. ProductFamilyModel::BEHAVIOR_PRICE_BY_REFERENCE_UNIT,
  310. ];
  311. }
  312. public function getPropertyOrganicLabelChoices(): array
  313. {
  314. return [
  315. ProductFamilyModel::PROPERTY_ORGANIC_LABEL_AB,
  316. ProductFamilyModel::PROPERTY_ORGANIC_LABEL_NP,
  317. ProductFamilyModel::PROPERTY_ORGANIC_LABEL_HVE,
  318. ProductFamilyModel::PROPERTY_ORGANIC_LABEL_TVVR,
  319. ];
  320. }
  321. public function getTypeExpirationDateChoices(): array
  322. {
  323. return [
  324. ProductFamilyModel::TYPE_EXPIRATION_DATE_DLC,
  325. ProductFamilyModel::TYPE_EXPIRATION_DATE_DDM,
  326. ProductFamilyModel::TYPE_EXPIRATION_DATE_DLUO,
  327. ];
  328. }
  329. public function getBehaviorExpirationDateChoices(): array
  330. {
  331. return [
  332. ProductFamilyModel::BEHAVIOR_EXPIRATION_DATE_BY_PRODUCT_FAMILY,
  333. ProductFamilyModel::BEHAVIOR_EXPIRATION_DATE_BY_PRODUCT,
  334. ];
  335. }
  336. }