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.

OrderShopSolver.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. namespace Lc\CaracoleBundle\Solver\Order;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Lc\CaracoleBundle\Model\File\DocumentInterface;
  5. use Lc\CaracoleBundle\Model\File\DocumentModel;
  6. use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
  7. use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
  8. use Lc\CaracoleBundle\Model\Order\OrderShopModel;
  9. use Lc\CaracoleBundle\Model\Order\OrderStatusInterface;
  10. use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
  11. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  12. use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
  13. use Lc\CaracoleBundle\Model\Product\ProductInterface;
  14. use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
  15. use Lc\CaracoleBundle\Solver\Price\PriceSolver;
  16. use Lc\CaracoleBundle\Solver\Product\ProductSolver;
  17. class OrderShopSolver
  18. {
  19. protected PriceSolver $priceSolver;
  20. protected EntityManagerInterface $entityManager;
  21. protected ProductSolver $productSolver;
  22. public function __construct(PriceSolver $priceSolver, EntityManagerInterface $entityManager, ProductSolver $productSolver)
  23. {
  24. $this->priceSolver = $priceSolver;
  25. $this->entityManager = $entityManager;
  26. $this->productSolver = $productSolver;
  27. }
  28. public function countQuantities(OrderShopInterface $orderShop): int
  29. {
  30. return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts());
  31. }
  32. public function countQuantitiesByOrderProducts($orderProducts = []): int
  33. {
  34. $count = 0;
  35. foreach ($orderProducts as $orderProduct) {
  36. $count += $orderProduct->getQuantityOrder();
  37. }
  38. return $count;
  39. }
  40. public function getOrderProductsByParentCategory(OrderShopInterface $orderShop): array
  41. {
  42. $categoriesArray = [];
  43. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  44. $productCategories = $orderProduct->getProduct()->getProductFamily()->getProductCategories();
  45. $category = $productCategories[0]->getParentCategory();
  46. $labelCategory = $category->getTitle();
  47. if (!isset($categoriesArray[$labelCategory])) {
  48. $categoriesArray[$labelCategory] = [];
  49. }
  50. $categoriesArray[$labelCategory][] = $orderProduct;
  51. }
  52. return $categoriesArray;
  53. }
  54. // getOrderProductsByProductFamily
  55. public function getOrderProductsByProductFamily(
  56. OrderShopInterface $orderShop,
  57. ProductFamilyInterface $productFamily
  58. ): array {
  59. $arrayOrderProducts = [];
  60. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  61. if ($orderProduct->getProduct()->getProductFamily() == $productFamily) {
  62. $arrayOrderProducts[] = $orderProduct;
  63. }
  64. }
  65. return $arrayOrderProducts;
  66. }
  67. public function getQuantityOrderByProduct(
  68. OrderShopInterface $orderShop,
  69. ProductInterface $product,
  70. $byWeight = false
  71. ): int {
  72. $quantity = 0;
  73. $productFamily = $product->getProductFamily();
  74. $behaviorCountStock = $productFamily->getBehaviorCountStock();
  75. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  76. if ($orderProduct->getProduct()->getId() == $product->getId()
  77. || (($behaviorCountStock == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY || $behaviorCountStock == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE)
  78. && $orderProduct->getProduct()->getProductFamily()->getId() == $productFamily->getId())) {
  79. if ($byWeight) {
  80. $quantity += $orderProduct->getQuantityOrder() * ($orderProduct->getQuantityProduct(
  81. ) / $orderProduct->getProduct()->getUnitInherited()->getCoefficient());
  82. } else {
  83. $quantity += $orderProduct->getQuantityOrder();
  84. }
  85. }
  86. }
  87. return $quantity;
  88. }
  89. // isProductAvailable
  90. public function isProductAvailable(ProductInterface $product, $quantityOrder = 0, $checkCart = false, $orderShop = null)
  91. {
  92. if ($product->getStatus() != 1 || $product->getProductFamily()->getStatus() != 1 || !$this->productSolver->isProductSaleStatusOn($product)) {
  93. return false;
  94. }
  95. // @TODO : orderShop à définir où est appelé isAvailable
  96. if ($checkCart && !$orderShop) {
  97. throw new \Exception("Attention : définir le orderShop à l'endroit où est appelé isAvailable");
  98. }
  99. $productFamily = $product->getProductFamily();
  100. $quantityAsked = $quantityOrder;
  101. if ($productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE) {
  102. if (!$quantityOrder) {
  103. $quantityAsked = $this->getQuantityOrderByProduct($orderShop, $product, true);
  104. } else {
  105. $quantityAsked = ($product->getQuantityInherited() / $product->getUnitInherited()->getCoefficient()) * $quantityOrder;
  106. }
  107. if ($checkCart) {
  108. $quantityAsked += $this->getQuantityOrderByProduct($orderShop, $product, true);
  109. }
  110. }
  111. if (($productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY
  112. || $productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT)) {
  113. if (!$quantityOrder) {
  114. $quantityAsked = $this->getQuantityOrderByProduct($orderShop, $product);
  115. }
  116. if ($checkCart) {
  117. $quantityAsked += $this->getQuantityOrderByProduct($orderShop, $product);
  118. }
  119. }
  120. if ($product->getAvailableQuantityInherited() >= $quantityAsked
  121. || $productFamily->getBehaviorCountStock() == ProductFamilyModel::BEHAVIOR_COUNT_STOCK_UNLIMITED) {
  122. return true;
  123. } else {
  124. return false;
  125. }
  126. }
  127. public function isOneProductAvailableAddCart(OrderShopInterface $orderShop, $products): bool
  128. {
  129. foreach ($products as $product) {
  130. if ($this->isProductAvailable($product, 1, true, $orderShop)) {
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. public function getTotalOrderPayments(OrderShopInterface $orderShop, $mergeComplementaryOrderShop = false): float
  137. {
  138. $totalAmount = floatval(0);
  139. foreach ($orderShop->getOrderPayments() as $orderPayment) {
  140. $totalAmount = $orderPayment->getAmount() + $totalAmount;
  141. }
  142. if ($mergeComplementaryOrderShop) {
  143. foreach ($orderShop->getComplementaryOrderShops() as $complementaryOrderShop) {
  144. foreach ($complementaryOrderShop->getOrderPayments() as $orderPayment) {
  145. $totalAmount = $orderPayment->getAmount() + $totalAmount;
  146. }
  147. }
  148. }
  149. return $totalAmount;
  150. }
  151. public function getTotalRemainingToBePaid(OrderShopInterface $orderShop): float
  152. {
  153. return $this->priceSolver->getTotalWithTax($orderShop) - $this->getTotalOrderPayments($orderShop);
  154. }
  155. public function getOrderStatusHistory(OrderShopInterface $orderShop, OrderStatusInterface $status)
  156. {
  157. $orderStatusHistories = $orderShop->getOrderStatusHistories();
  158. if (count($orderStatusHistories) > 0) {
  159. foreach ($orderStatusHistories as $orderStatusHistory) {
  160. if ($orderStatusHistory->getOrderStatus() === $status) {
  161. return $orderStatusHistory;
  162. }
  163. }
  164. }
  165. return null;
  166. }
  167. public function getDocumentInvoice(OrderShopInterface $orderShop): ?DocumentInterface
  168. {
  169. foreach ($orderShop->getDocuments() as $document) {
  170. if ($document->getType() == DocumentModel::TYPE_INVOICE) {
  171. return $document;
  172. }
  173. }
  174. return null;
  175. }
  176. public function isDeliveryHome(OrderShopInterface $orderShop): bool
  177. {
  178. return $orderShop->getDeliveryType() == OrderShopModel::DELIVERY_TYPE_HOME;
  179. }
  180. public function isDeliveryPointSale(OrderShopInterface $orderShop): bool
  181. {
  182. return $orderShop->getDeliveryType() == OrderShopModel::DELIVERY_TYPE_POINTSALE;
  183. }
  184. public function isComplementaryOrderShop(OrderShopInterface $orderShop): bool
  185. {
  186. return (bool) $orderShop->getMainOrderShop();
  187. }
  188. public function mergeComplentaryOrderShops(
  189. OrderShopInterface $orderShop,
  190. bool $combineProducts = true
  191. ): OrderShopInterface {
  192. $this->entityManager->refresh($orderShop);
  193. if ($orderShop->getComplementaryOrderShops()) {
  194. foreach ($orderShop->getComplementaryOrderShops() as $complementaryOrderShop) {
  195. foreach ($complementaryOrderShop->getOrderProducts() as $orderProductAdd) {
  196. $updated = false;
  197. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  198. if ($combineProducts && $orderProduct->getProduct()->getId() == $orderProductAdd->getProduct(
  199. )->getId()
  200. && (string)$orderProduct->getPrice() == (string)$orderProductAdd->getPrice()
  201. ) {
  202. $orderProduct->setUpdatedOnMergeComplementaryOrderShop(true);
  203. $orderProduct->setQuantityOrder(
  204. $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder()
  205. );
  206. $updated = true;
  207. }
  208. }
  209. if (!$updated) {
  210. $orderProductAdd->setOnMergeComplementaryOrderShop($complementaryOrderShop);
  211. $orderProductAdd->setCreatedOnMergeComplementaryOrderShop(true);
  212. $orderShop->addOrderProduct($orderProductAdd);
  213. }
  214. }
  215. }
  216. }
  217. return $orderShop;
  218. }
  219. public function isReductionCreditAddedToOrder(
  220. OrderShopInterface $orderShop,
  221. ReductionCreditInterface $reductionCredit
  222. ) {
  223. foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) {
  224. if ($orderReductionCredit->getReductionCredit() == $reductionCredit) {
  225. return true;
  226. }
  227. }
  228. return false;
  229. }
  230. public function hasOrderProductAlreadyInCart(
  231. OrderShopInterface $orderShop,
  232. OrderProductInterface $orderProductTest
  233. ): ?OrderProductInterface {
  234. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  235. if ($orderProduct->getProduct() == $orderProductTest->getProduct()) {
  236. return $orderProduct;
  237. }
  238. }
  239. return null;
  240. }
  241. public function isValid(OrderShopInterface $orderShop): bool
  242. {
  243. if ($orderShop->getOrderStatus() && in_array(
  244. $orderShop->getOrderStatus()->getAlias(),
  245. OrderStatusModel::$statusAliasAsValid
  246. ) > 0) {
  247. return true;
  248. }
  249. return false;
  250. }
  251. public function isCart(OrderShopInterface $orderShop): bool
  252. {
  253. if ($orderShop->getOrderStatus() && in_array(
  254. $orderShop->getOrderStatus()->getAlias(),
  255. OrderStatusModel::$statusAliasAsCart
  256. ) > 0) {
  257. return true;
  258. }
  259. return false;
  260. }
  261. // isOrderShopPositiveAmount
  262. public function isPositiveAmount(OrderShopInterface $orderShop): bool
  263. {
  264. return $this->priceSolver->getTotalWithTax($orderShop) >= 0;
  265. }
  266. public function isPaid(OrderShopInterface $orderShop, $mergeComplementaryOrderShop = false): bool
  267. {
  268. $totalOrderPayments = $this->getTotalOrderPayments($orderShop, $mergeComplementaryOrderShop);
  269. $totalOrder = $this->priceSolver->getTotalWithTax($orderShop);
  270. if ((abs($totalOrderPayments - $totalOrder) < 0.00001
  271. || $totalOrderPayments >= $totalOrder)
  272. && $totalOrder > 0) {
  273. return true;
  274. } else {
  275. return false;
  276. }
  277. }
  278. // isOrderShopPositiveAmountRemainingToBePaid
  279. public function isPositiveAmountRemainingToBePaid(OrderShopInterface $orderShop): bool
  280. {
  281. return $this->getTotalRemainingToBePaid($orderShop) > 0;
  282. }
  283. public function isCartAllowToBeOrder(OrderShopInterface $orderShop): bool
  284. {
  285. return true;
  286. }
  287. }