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.

OrderShopBuilder.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <?php
  2. namespace Lc\CaracoleBundle\Builder\Order;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Lc\CaracoleBundle\Builder\File\DocumentBuilder;
  5. use Lc\CaracoleBundle\Event\Order\OrderShopChangeStatusEvent;
  6. use Lc\CaracoleBundle\Factory\File\DocumentFactory;
  7. use Lc\CaracoleBundle\Factory\Order\OrderPaymentFactory;
  8. use Lc\CaracoleBundle\Factory\Order\OrderProductReductionCatalogFactory;
  9. use Lc\CaracoleBundle\Factory\Order\OrderReductionCartFactory;
  10. use Lc\CaracoleBundle\Factory\Order\OrderReductionCreditFactory;
  11. use Lc\CaracoleBundle\Factory\Order\OrderShopFactory;
  12. use Lc\CaracoleBundle\Factory\Order\OrderStatusHistoryFactory;
  13. use Lc\CaracoleBundle\Model\File\DocumentModel;
  14. use Lc\CaracoleBundle\Model\Order\OrderProductInterface;
  15. use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
  16. use Lc\CaracoleBundle\Model\Order\OrderStatusInterface;
  17. use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
  18. use Lc\CaracoleBundle\Model\Product\ProductFamilyModel;
  19. use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface;
  20. use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
  21. use Lc\CaracoleBundle\Model\Section\SectionInterface;
  22. use Lc\CaracoleBundle\Model\User\VisitorInterface;
  23. use Lc\CaracoleBundle\Repository\Order\OrderProductStore;
  24. use Lc\CaracoleBundle\Repository\Order\OrderShopStore;
  25. use Lc\CaracoleBundle\Repository\Order\OrderStatusStore;
  26. use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore;
  27. use Lc\CaracoleBundle\Resolver\Price\PriceResolver;
  28. use Lc\SovBundle\Model\User\UserInterface;
  29. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  30. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  31. class OrderShopBuilder
  32. {
  33. protected EntityManagerInterface $entityManager;
  34. protected OrderStatusStore $orderStatusStore;
  35. protected OrderProductStore $orderProductStore;
  36. protected ProductFamilyStore $productFamilyStore;
  37. protected PriceResolver $priceResolver;
  38. protected OrderProductBuilder $orderProductBuilder;
  39. protected DocumentBuilder $documentBuilder;
  40. protected EventDispatcherInterface $eventDispatcher;
  41. protected FlashBagInterface $flashBag;
  42. public function __construct(
  43. EntityManagerInterface $entityManager,
  44. OrderShopStore $orderShopStore,
  45. OrderStatusStore $orderStatusStore,
  46. OrderProductStore $orderProductStore,
  47. ProductFamilyStore $productFamilyStore,
  48. OrderProductBuilder $orderProductBuilder,
  49. DocumentBuilder $documentBuilder,
  50. PriceResolver $priceResolver,
  51. EventDispatcherInterface $eventDispatcher,
  52. FlashBagInterface $flashBag
  53. ) {
  54. $this->entityManager = $entityManager;
  55. $this->orderShopStore = $orderShopStore;
  56. $this->orderStatusStore = $orderStatusStore;
  57. $this->orderProductStore = $orderProductStore;
  58. $this->productFamilyStore = $productFamilyStore;
  59. $this->orderProductBuilder = $orderProductBuilder;
  60. $this->documentBuilder = $documentBuilder;
  61. $this->priceResolver = $priceResolver;
  62. $this->eventDispatcher = $eventDispatcher;
  63. $this->flashBag = $flashBag;
  64. }
  65. public function create(
  66. SectionInterface $section,
  67. UserInterface $user = null,
  68. VisitorInterface $visitor = null
  69. ) {
  70. $orderShopFactory = new OrderShopFactory();
  71. $orderShop = $orderShopFactory->create($section, $user, $visitor);
  72. $this->changeOrderStatus($orderShop, OrderStatusModel::ALIAS_CART);
  73. return $orderShop;
  74. }
  75. public function createIfNotExist(
  76. SectionInterface $section,
  77. UserInterface $user = null,
  78. VisitorInterface $visitor = null
  79. ) {
  80. $cart = $this->orderShopStore->getCartBy(
  81. [
  82. 'section' => $section,
  83. 'user' => $user,
  84. 'visitor' => $visitor
  85. ]
  86. );
  87. if (!$cart) {
  88. $cart = $this->create($section, $user, $visitor);
  89. }
  90. return $cart;
  91. }
  92. public function changeOrderStatus(OrderShopInterface $orderShop, string $alias, bool $forceByAdmin = false)
  93. {
  94. $orderStatus = $this->orderStatusStore->getRepositoryQuery()->findOneByAlias($alias);
  95. if ($orderStatus) {
  96. if ($orderShop->getOrderStatus() === null
  97. || $orderShop->getOrderStatus()->getNextStatusAllowed()->contains($orderStatus)) {
  98. $this->applyChangeOrderStatus($orderShop, $orderStatus, $forceByAdmin);
  99. }
  100. } else {
  101. throw new \ErrorException('La statut demandé n\'existe pas.');
  102. }
  103. return $orderShop;
  104. }
  105. public function applyChangeOrderStatus(
  106. OrderShopInterface $orderShop,
  107. OrderStatusInterface $orderStatus,
  108. bool $forceByAdmin = false
  109. ) {
  110. $this->eventDispatcher->dispatch(
  111. new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin),
  112. OrderShopChangeStatusEvent::PRE_CHANGE_STATUS
  113. );
  114. $orderShop->setOrderStatusProtected($orderStatus);
  115. $orderStatusHistoryFactory = new OrderStatusHistoryFactory();
  116. $orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus);
  117. $orderShop->addOrderStatusHistory($orderStatusHistory);
  118. $this->eventDispatcher->dispatch(
  119. new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin),
  120. OrderShopChangeStatusEvent::POST_CHANGE_STATUS
  121. );
  122. }
  123. public function addOrderProduct(
  124. OrderShopInterface $orderShop,
  125. OrderProductInterface $orderProductAdd,
  126. bool $persist = true
  127. ) {
  128. $return = false;
  129. if ($this->orderProductStore->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) {
  130. if ($orderProductAdd->getQuantityOrder() > 0) {
  131. $updated = false;
  132. $this->orderProductBuilder->init($orderProductAdd);
  133. $productFamily = $this->productFamilyStore->getOneBySlug(
  134. $orderProductAdd->getProduct()->getProductFamily()->getSlug()
  135. );
  136. if ($productFamily) {
  137. $reductionCatalog = $productFamily->getReductionCatalog();
  138. if ($reductionCatalog) {
  139. $orderProductReductionCatalogFactory = new OrderProductReductionCatalogFactory();
  140. $orderProductReductionCatalog = $orderProductReductionCatalogFactory->create(
  141. $reductionCatalog->getTitle(),
  142. $reductionCatalog->getValue(),
  143. $reductionCatalog->getUnit(),
  144. $reductionCatalog->getBehaviorTaxRate()
  145. );
  146. $orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog);
  147. }
  148. }
  149. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  150. if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId()
  151. && $orderProduct->getRedelivery() == $orderProductAdd->getRedelivery()
  152. && (string)$this->priceResolver->getPrice($orderProduct)
  153. == (string)$this->priceResolver->getPrice($orderProductAdd)
  154. && $orderProduct->getOrderProductReductionCatalog()->compare(
  155. $orderProductAdd->getOrderProductReductionCatalog()
  156. )) {
  157. $orderProduct->setQuantityOrder(
  158. $orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder()
  159. );
  160. if ($persist) {
  161. $this->entityManager->persist($orderProduct);
  162. }
  163. $updated = true;
  164. $return = true;
  165. break;
  166. }
  167. }
  168. if (!$updated) {
  169. $orderShop->addOrderProduct($orderProductAdd);
  170. if ($persist) {
  171. if (isset($orderProductReductionCatalog)) {
  172. $this->entityManager->persist($orderProductReductionCatalog);
  173. }
  174. $this->entityManager->persist($orderProductAdd);
  175. $this->entityManager->persist($orderShop);
  176. }
  177. $return = true;
  178. }
  179. if ($persist) {
  180. $this->entityManager->flush();
  181. }
  182. // @TODO : dispatch event cart change
  183. //$this->eventCartChange($orderShop);
  184. }
  185. } else {
  186. // @TODO : retourner le message d'erreur et faire le addFlash dans le contrôleur
  187. /*$availableQuantity = $orderProductAdd->getProduct()->getAvailableQuantityInherited();
  188. $textError = "Le produit <strong>" . $orderProductAdd->getTitleOrderShop(
  189. ) . "</strong> n'est pas disponible";
  190. if ($availableQuantity !== false && $availableQuantity > 0) {
  191. $unit = '';
  192. if ($orderProductAdd->getProduct()->getProductFamily()->getBehaviorCountStock(
  193. ) == ProductFamily::BEHAVIOR_COUNT_STOCK_BY_MEASURE) {
  194. $unit = $orderProductAdd->getProduct()->getUnitInherited()->getUnitReference()->getUnit();
  195. }
  196. $textError .= ' dans cette quantité ';
  197. $user = $this->security->getUser();
  198. if ($user && $user->hasRole('ROLE_USER')) {
  199. $textError .= '<br />' . $availableQuantity . $unit . ' disponible(s) dont ' . $this->getQuantityOrderByProduct(
  200. $orderShop,
  201. $orderProductAdd->getProduct()
  202. ) . $unit . ' déjà dans votre panier.';
  203. }
  204. }
  205. $this->utils->addFlash('error', $textError);*/
  206. }
  207. return $return;
  208. }
  209. public function merge(OrderShopInterface $orderShop1, OrderShopInterface $orderShop2, $persist = true)
  210. {
  211. if ($orderShop1 && $orderShop2) {
  212. foreach ($orderShop2->getOrderProducts() as $orderProduct) {
  213. $orderProductAlreadyInCart = $orderShop1->hasOrderProductAlreadyInCart($orderProduct);
  214. if ($orderProductAlreadyInCart) {
  215. if ($orderProduct->getQuantityOrder() > $orderProductAlreadyInCart->getQuantityOrder()) {
  216. $orderShop1->removeOrderProduct($orderProductAlreadyInCart);
  217. $this->addOrderProduct($orderShop1, $orderProduct);
  218. }
  219. } else {
  220. $this->addOrderProduct($orderShop1, $orderProduct);
  221. }
  222. if ($persist) {
  223. $this->entityManager->remove($orderProduct);
  224. }
  225. }
  226. if ($persist) {
  227. $this->entityManager->remove($orderShop2);
  228. $this->entityManager->persist($orderShop1);
  229. $this->entityManager->flush();
  230. }
  231. return $orderShop1;
  232. }
  233. }
  234. public function addPayment(OrderShopInterface $orderShop, $meanPayment, $amount)
  235. {
  236. $orderPaymentFactory = new OrderPaymentFactory();
  237. $orderPayment = $orderPaymentFactory->create($orderShop, $meanPayment, $amount);
  238. $orderShop->addOrderPayment($orderPayment);
  239. if ($this->isOrderPaid($orderShop)) {
  240. $nextStatus = OrderStatusModel::ALIAS_PAID;
  241. } else {
  242. $nextStatus = OrderStatusModel::ALIAS_PARTIAL_PAYMENT;
  243. }
  244. if ($orderShop->getOrderStatus()->getAlias() != $nextStatus) {
  245. $orderShop = $this->changeOrderStatus($orderShop, $nextStatus);
  246. }
  247. $this->entityManager->persist($orderPayment);
  248. $this->entityManager->update($orderShop);
  249. $this->entityManager->flush();
  250. return $orderShop;
  251. }
  252. public function createDocumentInvoice(OrderShopInterface $orderShop)
  253. {
  254. $documentFactory = new DocumentFactory();
  255. $document = $documentFactory->create(DocumentModel::TYPE_INVOICE);
  256. $this->documentBuilder->initFromOrderShop($orderShop);
  257. return $document;
  258. }
  259. public function addReductionCart(OrderShopInterface $orderShop, ReductionCartInterface $reductionCart)
  260. {
  261. $orderReductionCartFactory = new OrderReductionCartFactory();
  262. $orderReductionCart = $orderReductionCartFactory->create($orderShop, $reductionCart);
  263. $orderShop->addOrderReductionCart($orderReductionCart);
  264. if ($this->orderShopStore->isPositiveAmount($orderShop)
  265. && $this->isPositiveAmountRemainingToBePaid($orderShop)) {
  266. $this->entityManager->persist($orderReductionCart);
  267. $this->entityManager->flush();
  268. return $orderReductionCart;
  269. } else {
  270. $orderShop->removeOrderReductionCart($orderReductionCart);
  271. return false;
  272. }
  273. }
  274. // createOrderReductionCredit
  275. public function addReductionCredit(OrderShopInterface $orderShop, ReductionCreditInterface $reductionCredit)
  276. {
  277. $orderReductionCreditFactory = new OrderReductionCreditFactory();
  278. $orderReductionCredit = $orderReductionCreditFactory->create($orderShop, $reductionCredit);
  279. $orderShop->addOrderReductionCredit($orderReductionCredit);
  280. if ($this->isOrderShopPositiveAmount($orderShop)
  281. && $this->isOrderShopPositiveAmountRemainingToBePaid($orderShop)) {
  282. $this->entityManager->persist($orderReductionCredit);
  283. $this->entityManager->flush();
  284. return $orderReductionCredit;
  285. } else {
  286. $orderShop->removeOrderReductionCredit($orderReductionCredit);
  287. return false;
  288. }
  289. }
  290. public function deductAvailabilityProduct(OrderShopInterface $orderShop)
  291. {
  292. // @TODO : à refactorer en plaçant dans src tout ce qui est spécifique à PDL
  293. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  294. //Si ce n'esrt pas une relivraison OU si c'est une relivraison + relivraison + ce n'est pas une erruer producteur
  295. if (!$orderProduct->isRedelivery() || ($orderProduct->isRedelivery(
  296. ) && $orderProduct->isRedeliverySupplierOrder(
  297. ) && !$orderProduct->isRedeliverySupplierMistake())) {
  298. switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) {
  299. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE :
  300. //Disponibilité par unité de référence
  301. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  302. $newAvailability = $oldAvailability - ($orderProduct->getQuantityOrder(
  303. ) * ($orderProduct->getQuantityProduct() / $orderProduct->getUnit(
  304. )->getCoefficient()));
  305. $productFamily = $orderProduct->getProduct()->getProductFamily();
  306. $productFamily->setAvailableQuantity($newAvailability);
  307. $productFamily->setUpdatedBy($orderShop->getUser());
  308. $this->entityManager->persist($productFamily);
  309. break;
  310. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :
  311. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  312. $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
  313. $productFamily = $orderProduct->getProduct()->getProductFamily();
  314. $productFamily->setAvailableQuantity($newAvailability);
  315. $productFamily->setUpdatedBy($orderShop->getUser());
  316. $this->entityManager->persist($productFamily);
  317. break;
  318. case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
  319. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  320. $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
  321. $product = $orderProduct->getProduct();
  322. $product->setAvailableQuantity($newAvailability);
  323. $product->setUpdatedBy($orderShop->getUser());
  324. $this->entityManager->persist($product);
  325. break;
  326. }
  327. $this->entityManager->flush();
  328. }
  329. }
  330. }
  331. }