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.

419 lines
15KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Solver\Order;
  3. use App\Entity\Order\OrderShop;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Collection;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Lc\CaracoleBundle\Model\File\DocumentInterface;
  8. use Lc\CaracoleBundle\Model\File\DocumentModel;
  9. use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
  10. use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
  11. use Lc\CaracoleBundle\Model\Order\OrderShopModel;
  12. use Lc\CaracoleBundle\Model\Order\OrderStatusInterface;
  13. use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
  14. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  15. use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
  16. use Lc\CaracoleBundle\Model\Product\ProductInterface;
  17. use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
  18. use Lc\CaracoleBundle\Model\Section\SectionInterface;
  19. use Lc\CaracoleBundle\Solver\Product\ProductFamilySectionPropertySolver;
  20. use Lc\CaracoleBundle\Solver\Product\ProductSolver;
  21. class OrderShopSolver
  22. {
  23. protected EntityManagerInterface $entityManager;
  24. protected ProductSolver $productSolver;
  25. public function __construct(
  26. EntityManagerInterface $entityManager,
  27. ProductSolver $productSolver
  28. ) {
  29. $this->entityManager = $entityManager;
  30. $this->productSolver = $productSolver;
  31. }
  32. public static function getTypeDeliveryChoices()
  33. {
  34. return [
  35. OrderShopModel::DELIVERY_TYPE_HOME,
  36. OrderShopModel::DELIVERY_TYPE_POINTSALE,
  37. ];
  38. }
  39. public function isEmpty(OrderShopInterface $orderShop): bool
  40. {
  41. return $orderShop->getOrderProducts()->isEmpty();
  42. }
  43. public function countQuantities(OrderShopInterface $orderShop): int
  44. {
  45. return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts());
  46. }
  47. public function countQuantitiesByOrderProducts($orderProducts = []): int
  48. {
  49. $count = 0;
  50. foreach ($orderProducts as $orderProduct) {
  51. $count += $orderProduct->getQuantityOrder();
  52. }
  53. return $count;
  54. }
  55. public function getOrderProductsByParentCategory(OrderShopInterface $orderShop): array
  56. {
  57. $categoriesArray = [];
  58. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  59. $productCategories = $orderProduct->getProduct()->getProductFamily()->getProductCategories();
  60. $category = $productCategories[0]->getParentCategory();
  61. $labelCategory = $category->getTitle();
  62. if (!isset($categoriesArray[$labelCategory])) {
  63. $categoriesArray[$labelCategory] = [];
  64. }
  65. $categoriesArray[$labelCategory][] = $orderProduct;
  66. }
  67. return $categoriesArray;
  68. }
  69. // getOrderProductsByProductFamily
  70. public function getOrderProductsByProductFamily(
  71. OrderShopInterface $orderShop,
  72. ProductFamilyInterface $productFamily
  73. ): array {
  74. $arrayOrderProducts = [];
  75. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  76. if ($orderProduct->getProduct()->getProductFamily() == $productFamily) {
  77. $arrayOrderProducts[] = $orderProduct;
  78. }
  79. }
  80. return $arrayOrderProducts;
  81. }
  82. public function getQuantityOrderByProduct(
  83. OrderShopInterface $orderShop,
  84. ProductInterface $product,
  85. $byWeight = false
  86. ): float {
  87. $quantity = 0;
  88. $productFamily = $product->getProductFamily();
  89. $behaviorCountStock = $productFamily->getBehaviorCountStock();
  90. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  91. if ($orderProduct->getProduct()->getId() == $product->getId()
  92. || (($behaviorCountStock == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY || $behaviorCountStock == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE)
  93. && $orderProduct->getProduct()->getProductFamily()->getId() == $productFamily->getId())) {
  94. if ($byWeight) {
  95. $quantity += $orderProduct->getQuantityOrder() * ($orderProduct->getQuantityProduct(
  96. ) / $this->productSolver->getUnitInherited(
  97. $orderProduct->getProduct()
  98. )->getCoefficient());
  99. } else {
  100. $quantity += $orderProduct->getQuantityOrder();
  101. }
  102. }
  103. }
  104. return $quantity;
  105. }
  106. // isProductAvailable
  107. public function isProductAvailable(
  108. SectionInterface $section,
  109. ?OrderShopInterface $orderShop,
  110. ProductInterface $product,
  111. int $quantityOrder = 0,
  112. bool $checkCart = false
  113. ) {
  114. if ($product->getStatus() != 1 || $product->getProductFamily()->getStatus(
  115. ) != 1 || !$this->productSolver->isProductSaleStatusOn($product)) {
  116. return false;
  117. }
  118. $productFamily = $product->getProductFamily();
  119. $quantityAsked = $quantityOrder;
  120. if ($productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE) {
  121. if (!$quantityOrder) {
  122. $quantityAsked = $this->getQuantityOrderByProduct($orderShop, $product, true);
  123. } else {
  124. $quantityAsked = ($this->productSolver->getQuantityInherited($product)
  125. / $this->productSolver->getUnitInherited($product)->getCoefficient()) * $quantityOrder;
  126. }
  127. if ($checkCart) {
  128. $quantityAsked += $this->getQuantityOrderByProduct($orderShop, $product, true);
  129. }
  130. }
  131. if (($productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
  132. || $productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT)) {
  133. if (!$quantityOrder) {
  134. $quantityAsked = $this->getQuantityOrderByProduct($orderShop, $product);
  135. }
  136. if ($checkCart) {
  137. $quantityAsked += $this->getQuantityOrderByProduct($orderShop, $product);
  138. }
  139. }
  140. if ($this->productSolver->getAvailableQuantityInherited($product) >= $quantityAsked) {
  141. return true;
  142. } else {
  143. return false;
  144. }
  145. }
  146. public function isOneProductAvailable(SectionInterface $section, $productArray): bool
  147. {
  148. foreach($productArray as $product) {
  149. if($this->isProductAvailable($section, null, $product, 1, false)) {
  150. return true;
  151. }
  152. }
  153. return false;
  154. }
  155. public function isOneProductAvailableAddCart(OrderShopInterface $orderShop, $products): bool
  156. {
  157. foreach ($products as $product) {
  158. if ($this->isProductAvailable($orderShop->getSection(), $orderShop, $product, 1, true)) {
  159. return true;
  160. }
  161. }
  162. return false;
  163. }
  164. public function isOrderProductAvailableAddCart(OrderProductInterface $orderProduct, OrderShopInterface $orderShop)
  165. {
  166. return $this->isProductAvailable(
  167. $orderShop->getSection(),
  168. $orderShop,
  169. $orderProduct->getProduct(),
  170. 1,
  171. true
  172. );
  173. }
  174. public function getTotalOrderPayments(OrderShopInterface $orderShop, $mergeComplementaryOrderShop = false): float
  175. {
  176. $totalAmount = floatval(0);
  177. foreach ($orderShop->getOrderPayments() as $orderPayment) {
  178. $totalAmount = $orderPayment->getAmount() + $totalAmount;
  179. }
  180. if ($mergeComplementaryOrderShop) {
  181. foreach ($this->getValidComplementaryOrderShops($orderShop) as $complementaryOrderShop) {
  182. foreach ($complementaryOrderShop->getOrderPayments() as $orderPayment) {
  183. $totalAmount = $orderPayment->getAmount() + $totalAmount;
  184. }
  185. }
  186. }
  187. return $totalAmount;
  188. }
  189. public function getValidComplementaryOrderShops(OrderShopInterface $orderShop): Collection
  190. {
  191. $arrayComplementaryOrderShops = new ArrayCollection();
  192. foreach ($orderShop->getComplementaryOrderShops() as $complementaryOrderShop) {
  193. if ($this->isValid($complementaryOrderShop)) {
  194. $arrayComplementaryOrderShops[] = $complementaryOrderShop;
  195. }
  196. }
  197. return $arrayComplementaryOrderShops;
  198. }
  199. public function countValidComplementaryOrderShops(OrderShopInterface $orderShop): int
  200. {
  201. return count($this->getValidComplementaryOrderShops($orderShop));
  202. }
  203. public function getOrderStatusHistory(OrderShopInterface $orderShop, OrderStatusInterface $status)
  204. {
  205. $orderStatusHistories = $orderShop->getOrderStatusHistories();
  206. if (count($orderStatusHistories) > 0) {
  207. foreach ($orderStatusHistories as $orderStatusHistory) {
  208. if ($orderStatusHistory->getOrderStatus() === $status) {
  209. return $orderStatusHistory;
  210. }
  211. }
  212. }
  213. return null;
  214. }
  215. public function getDocumentInvoice(OrderShopInterface $orderShop): ?DocumentInterface
  216. {
  217. foreach ($orderShop->getDocuments() as $document) {
  218. if ($document->getType() == DocumentModel::TYPE_INVOICE) {
  219. return $document;
  220. }
  221. }
  222. return null;
  223. }
  224. public function isDeliveryHome(OrderShopInterface $orderShop): bool
  225. {
  226. return $orderShop->getDeliveryType() == OrderShopModel::DELIVERY_TYPE_HOME;
  227. }
  228. public function isDeliveryPointSale(OrderShopInterface $orderShop): bool
  229. {
  230. return $orderShop->getDeliveryType() == OrderShopModel::DELIVERY_TYPE_POINTSALE;
  231. }
  232. public function isComplementaryOrderShop(OrderShopInterface $orderShop): bool
  233. {
  234. return (bool)$orderShop->getMainOrderShop();
  235. }
  236. public function mergeComplentaryOrderShops(
  237. OrderShopInterface $orderShop,
  238. bool $combineProducts = true,
  239. bool $onlySameSection = false
  240. ): OrderShopInterface {
  241. $this->entityManager->refresh($orderShop);
  242. if ($this->getValidComplementaryOrderShops($orderShop)) {
  243. foreach ($this->getValidComplementaryOrderShops($orderShop) as $complementaryOrderShop) {
  244. if (!$onlySameSection || $complementaryOrderShop->getSection()->getId()
  245. == $orderShop->getSection()->getId()) {
  246. // @TODO : obligatoire sinon un seul orderProduct de présent
  247. $this->entityManager->refresh($complementaryOrderShop);
  248. foreach ($complementaryOrderShop->getOrderProducts() as $orderProductAdd) {
  249. $updated = false;
  250. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  251. if ($combineProducts && $orderProduct->getProduct()->getId(
  252. ) == $orderProductAdd->getProduct()->getId()
  253. && (string)$orderProduct->getPrice() == (string)$orderProductAdd->getPrice()
  254. ) {
  255. $orderProduct->setUpdatedOnMergeComplementaryOrderShop(true);
  256. $orderProduct->setQuantityOrder(
  257. $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder()
  258. );
  259. $updated = true;
  260. }
  261. }
  262. if (!$updated) {
  263. $orderProductAdd->setOnMergeComplementaryOrderShop($complementaryOrderShop);
  264. $orderProductAdd->setCreatedOnMergeComplementaryOrderShop(true);
  265. $orderShop->addOrderProduct($orderProductAdd);
  266. }
  267. }
  268. }
  269. }
  270. }
  271. return $orderShop;
  272. }
  273. public function refreshOrderShops(array $orderShops): array
  274. {
  275. foreach ($orderShops as $orderShop) {
  276. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  277. $this->entityManager->refresh($orderProduct);
  278. }
  279. $this->entityManager->refresh($orderShop);
  280. }
  281. return $orderShops;
  282. }
  283. public function isReductionCreditAddedToOrder(
  284. OrderShopInterface $orderShop,
  285. ReductionCreditInterface $reductionCredit
  286. ) {
  287. foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) {
  288. if ($orderReductionCredit->getReductionCredit() == $reductionCredit) {
  289. return true;
  290. }
  291. }
  292. return false;
  293. }
  294. public function hasOrderProductAlreadyInCart(
  295. OrderShopInterface $orderShop,
  296. OrderProductInterface $orderProductTest
  297. ): ?OrderProductInterface {
  298. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  299. if ($orderProduct->getProduct() == $orderProductTest->getProduct()) {
  300. return $orderProduct;
  301. }
  302. }
  303. return null;
  304. }
  305. public function isValid(OrderShopInterface $orderShop): bool
  306. {
  307. if ($orderShop->getOrderStatus() && in_array(
  308. $orderShop->getOrderStatus()->getAlias(),
  309. OrderStatusModel::$statusAliasAsValid
  310. ) > 0) {
  311. return true;
  312. }
  313. return false;
  314. }
  315. public function isCart(OrderShopInterface $orderShop): bool
  316. {
  317. if ($orderShop->getOrderStatus() && in_array(
  318. $orderShop->getOrderStatus()->getAlias(),
  319. OrderStatusModel::$statusAliasAsCart
  320. ) > 0) {
  321. return true;
  322. }
  323. return false;
  324. }
  325. public function isDone(OrderShopInterface $orderShop): bool
  326. {
  327. if ($orderShop->getOrderStatus() && $orderShop->getOrderStatus()->getAlias() == OrderStatusModel::ALIAS_DONE) {
  328. return true;
  329. }
  330. return false;
  331. }
  332. // getProductQuantityMaxAddCart
  333. public function getProductQuantityMaxAddCart(OrderShopInterface $orderShop, ProductInterface $product)
  334. {
  335. $productFamily = $product->getProductFamily();
  336. $byWeight = false;
  337. if ($productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE) {
  338. $byWeight = true;
  339. }
  340. return max(
  341. $this->productSolver->getAvailableQuantityInherited($product) - $this->getQuantityOrderByProduct(
  342. $orderShop,
  343. $product,
  344. $byWeight
  345. ),
  346. 0
  347. );
  348. }
  349. public function hasMakeAChoiceAboutComplementaryOrder(OrderShop $orderShop): bool
  350. {
  351. return $orderShop->getMainOrderShop() || $orderShop->getDeclineComplementaryOrderShop();
  352. }
  353. }