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.

455 line
21KB

  1. <?php
  2. namespace Lc\ShopBundle\Services;
  3. use App\Entity\OrderProductReductionCatalog;
  4. use App\Entity\OrderShop;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Lc\ShopBundle\Context\DocumentInterface;
  7. use Lc\ShopBundle\Context\MerchantUtilsInterface;
  8. use Lc\ShopBundle\Context\OrderPaymentInterface;
  9. use Lc\ShopBundle\Context\OrderReductionCartInterface;
  10. use Lc\ShopBundle\Context\OrderProductInterface;
  11. use Lc\ShopBundle\Context\OrderReductionCreditInterface;
  12. use Lc\ShopBundle\Context\OrderShopInterface;
  13. use Lc\ShopBundle\Context\OrderStatusHistoryInterface;
  14. use Lc\ShopBundle\Context\OrderStatusInterface;
  15. use Lc\ShopBundle\Context\ProductFamilyUtilsInterface;
  16. use Lc\ShopBundle\Context\ReductionCartInterface;
  17. use Lc\ShopBundle\Context\ReductionCreditInterface;
  18. use Lc\ShopBundle\Context\UserInterface;
  19. use Lc\ShopBundle\Model\Document;
  20. use Lc\ShopBundle\Form\Backend\Order\OrderReductionCreditType;
  21. use Lc\ShopBundle\Model\Product;
  22. use Lc\ShopBundle\Model\ProductFamily;
  23. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  24. use Symfony\Component\Security\Core\Security;
  25. class OrderUtils
  26. {
  27. use OrderUtilsReductionTrait;
  28. protected $em;
  29. protected $security;
  30. protected $userUtils;
  31. protected $merchantUtils;
  32. protected $orderShopRepo;
  33. protected $priceUtils;
  34. protected $productFamilyUtils;
  35. protected $documentUtils;
  36. protected $session;
  37. public function __construct(EntityManagerInterface $em, Security $security, UserUtils $userUtils,
  38. MerchantUtilsInterface $merchantUtils, PriceUtils $priceUtils, ProductFamilyUtilsInterface $productFamilyUtils,
  39. DocumentUtils $documentUtils, SessionInterface $session)
  40. {
  41. $this->em = $em;
  42. $this->security = $security;
  43. $this->userUtils = $userUtils;
  44. $this->merchantUtils = $merchantUtils;
  45. $this->orderShopRepo = $this->em->getRepository($this->em->getClassMetadata(OrderShopInterface::class)->getName());
  46. $this->priceUtils = $priceUtils;
  47. $this->productFamilyUtils = $productFamilyUtils;
  48. $this->documentUtils = $documentUtils;
  49. $this->session = $session;
  50. }
  51. public function getCartCurrent()
  52. {
  53. $paramsSearchOrderShop = [];
  54. $user = $this->security->getUser();
  55. $visitor = $this->userUtils->getVisitorCurrent();
  56. $orderShop = null;
  57. $orderShopUser = null;
  58. $orderShopVisitor = null;
  59. if ($user) {
  60. $orderShopUser = $this->orderShopRepo->findCartCurrent([
  61. 'user' => $user
  62. ]);
  63. }
  64. if ($visitor) {
  65. $orderShopVisitor = $this->orderShopRepo->findCartCurrent([
  66. 'visitor' => $visitor
  67. ]);
  68. }
  69. if ($orderShopUser || $orderShopVisitor) {
  70. // merge
  71. if ($orderShopUser && $orderShopVisitor && $orderShopUser != $orderShopVisitor
  72. && $orderShopVisitor->getOrderProducts() && count($orderShopVisitor->getOrderProducts())) {
  73. $orderShop = $this->mergeOrderShops($orderShopUser, $orderShopVisitor);
  74. $this->session->getFlashBag()->add('success', "Votre panier visiteur vient d'être fusionné avec votre panier client.");
  75. } else {
  76. $orderShop = ($orderShopUser) ? $orderShopUser : $orderShopVisitor;
  77. }
  78. // set user
  79. if ($orderShop && $user && !$orderShop->getUser()) {
  80. $orderShop->setUser($user);
  81. $this->em->persist($orderShop);
  82. $this->em->flush();
  83. }
  84. }
  85. return $orderShop;
  86. }
  87. public function createOrderShop($params)
  88. {
  89. $orderShop = new OrderShop();
  90. $orderShopBelongTo = false;
  91. if (isset($params['user']) && $params['user']) {
  92. $orderShopBelongTo = true;
  93. $orderShop->setUser($params['user']);
  94. }
  95. if (isset($params['visitor']) && $params['visitor']) {
  96. $orderShopBelongTo = true;
  97. $orderShop->setVisitor($params['visitor']);
  98. }
  99. if (!$orderShopBelongTo) {
  100. throw new \ErrorException('La commande doit être liée à un utilisateur ou à un visiteur.');
  101. }
  102. if (isset($params['merchant']) && $params['merchant']) {
  103. $orderShop->setMerchant($params['merchant']);
  104. } else {
  105. throw new \ErrorException('La commande doit être liée à un merchant.');
  106. }
  107. $orderShop = $this->changeOrderStatus('cart', $orderShop);
  108. return $orderShop;
  109. }
  110. public function addOrderProduct($orderShop, $orderProductAdd, $persist = true)
  111. {
  112. $return = false;
  113. $user = $this->security->getUser();
  114. $visitor = $this->userUtils->getVisitorCurrent();
  115. if (!$orderShop) {
  116. $orderShop = $this->createOrderShop([
  117. 'user' => $user,
  118. 'visitor' => $visitor,
  119. 'merchant' => $this->merchantUtils->getMerchantCurrent()
  120. ]);
  121. }
  122. if ($orderProductAdd->getQuantityOrder() > 0) {
  123. $updated = false;
  124. $orderProductAdd->setTitle($orderProductAdd->getTitleOrderShop());
  125. $orderProductAdd->setPrice($this->priceUtils->getPrice($orderProductAdd->getProduct()));
  126. $orderProductAdd->setUnit($orderProductAdd->getProduct()->getUnitInherited());
  127. $orderProductAdd->setTaxRate($orderProductAdd->getProduct()->getTaxRateInherited());
  128. $orderProductAdd->setQuantityProduct($orderProductAdd->getProduct()->getQuantityInherited());
  129. $productFamily = $this->productFamilyUtils->getProductFamilyBySlug($orderProductAdd->getProduct()->getProductFamily()->getSlug());
  130. $reductionCatalog = $productFamily->getReductionCatalog();
  131. if ($reductionCatalog) {
  132. $orderProductReductionCatalog = new OrderProductReductionCatalog();
  133. $orderProductReductionCatalog->setTitle($reductionCatalog->getTitle());
  134. $orderProductReductionCatalog->setValue($reductionCatalog->getValue());
  135. $orderProductReductionCatalog->setUnit($reductionCatalog->getUnit());
  136. $orderProductReductionCatalog->setBehaviorTaxRate($reductionCatalog->getBehaviorTaxRate());
  137. $orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog);
  138. }
  139. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  140. if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId()
  141. && (string)$this->priceUtils->getPrice($orderProduct) == (string)$this->priceUtils->getPrice($orderProductAdd)
  142. && $this->compareOrderProductReductionCatalog($orderProduct->getOrderProductReductionCatalog(), $orderProductAdd->getOrderProductReductionCatalog())) {
  143. $orderProduct->setQuantityOrder($orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder());
  144. if ($persist) {
  145. $this->em->persist($orderProduct);
  146. }
  147. $updated = true;
  148. $return = true;
  149. break;
  150. }
  151. }
  152. if (!$updated) {
  153. $orderShop->addOrderProduct($orderProductAdd);
  154. if (isset($orderProductReductionCatalog)) {
  155. $this->em->persist($orderProductReductionCatalog);
  156. if ($persist) {
  157. if (isset($orderProductReductionCatalog)) {
  158. $this->em->persist($orderProductReductionCatalog);
  159. }
  160. $this->em->persist($orderProductAdd);
  161. $this->em->persist($orderShop);
  162. }
  163. }
  164. if ($persist) {
  165. $this->em->flush();
  166. }
  167. $return = true;
  168. }
  169. }
  170. return $return;
  171. }
  172. public function countQuantities($orderShop)
  173. {
  174. return $this->countQuantitiesByOrderProducts($orderShop->getOrderProducts());
  175. }
  176. public function countQuantitiesByOrderProducts($orderProducts = [])
  177. {
  178. $count = 0;
  179. foreach ($orderProducts as $orderProduct) {
  180. $count += $orderProduct->getQuantityOrder();
  181. }
  182. return $count;
  183. }
  184. public function getOrderProductsByParentCategory($orderShop = null)
  185. {
  186. $categoriesArray = [];
  187. if ($orderShop) {
  188. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  189. $productCategories = $orderProduct->getProduct()->getProductFamily()->getProductCategories();
  190. $category = $productCategories[0]->getParentCategory();
  191. $labelCategory = $category->getTitle();
  192. if (!isset($categoriesArray[$labelCategory])) {
  193. $categoriesArray[$labelCategory] = [];
  194. }
  195. $categoriesArray[$labelCategory][] = $orderProduct;
  196. }
  197. }
  198. return $categoriesArray;
  199. }
  200. public function getOrderDatas($order = null)
  201. {
  202. $data = [];
  203. if (!$order) {
  204. $order = $this->getCartCurrent();
  205. }
  206. $data['order'] = $order;
  207. if ($order) {
  208. $data['count'] = $this->countQuantities($order);
  209. $data['total_with_tax'] = $this->priceUtils->getTotalWithTaxAndReduction($order);
  210. $data['order_products_by_category'] = $this->getOrderProductsByParentCategory($order);
  211. }
  212. return $data;
  213. }
  214. public function getOrderAsJsonObject(OrderShopInterface $order)
  215. {
  216. $data['id'] = $order->getId();
  217. $data['user'] = $order->getUser()->getSummary();
  218. $data['orderStatus'] = $order->getOrderStatus()->__tosString();
  219. $data['deliveryAddress'] = $order->getDeliveryAddress()->getSummary();
  220. $data['invoiceAddress'] = $order->getInvoiceAddress()->getSummary();
  221. $data['total'] = $this->priceUtils->getTotal($order);
  222. $data['totalWithTax'] = $this->priceUtils->getTotalWithTax($order);
  223. $data['totalWithTaxAndReduction'] = $this->priceUtils->getTotalWithTax($order);
  224. $i = 0;
  225. foreach ($this->getOrderProductsByParentCategory($order) as $labelCategory => $orderProducts) {
  226. foreach ($orderProducts as $orderProduct) {
  227. $data['orderProducts'][$i]['id'] = $orderProduct->getId();
  228. $data['orderProducts'][$i]['product'] = $orderProduct->getProduct()->getId();
  229. $data['orderProducts'][$i]['quantityOrder'] = $orderProduct->getQuantityOrder();
  230. $data['orderProducts'][$i]['labelCategory'] = $labelCategory;
  231. $data['orderProducts'][$i]['title'] = $orderProduct->getTitle();
  232. $data['orderProducts'][$i]['price'] = $this->priceUtils->getPrice($orderProduct);
  233. $data['orderProducts'][$i]['priceWithTax'] = $this->priceUtils->getPriceWithTax($orderProduct);
  234. $data['orderProducts'][$i]['priceWithTaxAndReduction'] = $this->priceUtils->getPriceWithTaxAndReduction($orderProduct);
  235. $data['orderProducts'][$i]['quantity'] = $orderProduct->getQuantityOrder();
  236. $data['orderProducts'][$i]['totalWithTaxAndReduction'] = $this->priceUtils->getTotalOrderProductsWithTaxAndReduction(array($orderProduct));
  237. $i++;
  238. }
  239. }
  240. return $data;
  241. }
  242. public function newOrderStatusHistory($order, $status, $origin = 'user')
  243. {
  244. $orderStatusHistoryClass = $this->em->getClassMetadata(OrderStatusHistoryInterface::class);
  245. $orderStatusHistory = new $orderStatusHistoryClass->name;
  246. $orderStatusHistory->setOrderShop($order);
  247. $orderStatusHistory->setOrderStatus($status);
  248. $orderStatusHistory->setOrigin($origin);
  249. $this->em->persist($orderStatusHistory);
  250. }
  251. public function mergeOrderShops($orderShop1, $orderShop2)
  252. {
  253. if ($orderShop1 && $orderShop2) {
  254. foreach ($orderShop2->getOrderProducts() as $orderProduct) {
  255. $this->addOrderProduct($orderShop1, $orderProduct);
  256. $this->em->remove($orderProduct);
  257. }
  258. $this->em->remove($orderShop2);
  259. $this->em->persist($orderShop1);
  260. $this->em->flush();
  261. return $orderShop1;
  262. }
  263. }
  264. public function createDocumentInvoice(OrderShopInterface $orderShop)
  265. {
  266. $merchantAddress = $orderShop->getMerchant()->getAddress();
  267. $buyerAddress = $orderShop->getInvoiceAddress();
  268. $document = $this->documentUtils->createDocument([
  269. 'type' => Document::TYPE_INVOICE,
  270. 'title' => '',
  271. 'status' => 1,
  272. 'order_shops' => [$orderShop],
  273. 'merchant_address' => $merchantAddress,
  274. 'buyer_address' => $buyerAddress,
  275. 'created_by' => $orderShop->getUser()
  276. ]);
  277. return $document;
  278. }
  279. public function groupOrderProductsByProductFamily($orderProducts)
  280. {
  281. $orderProductsByProductFamily = [];
  282. foreach ($orderProducts as $orderProduct) {
  283. if ($orderProduct->getProduct() && $orderProduct->getProduct()->getProductFamily()) {
  284. $productFamily = $orderProduct->getProduct()->getProductFamily();
  285. if (!isset($orderProductsByProductFamily[$productFamily->getId()])) {
  286. $orderProductsByProductFamily[$productFamily->getId()] = [
  287. 'order_products' => [],
  288. 'total_quantity_weight' => 0,
  289. ];
  290. }
  291. $orderProductsByProductFamily[$productFamily->getId()]['order_products'][] = $orderProduct;
  292. $orderProductsByProductFamily[$productFamily->getId()]['total_quantity_weight'] += ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient()) * $orderProduct->getQuantityOrder();
  293. }
  294. }
  295. return $orderProductsByProductFamily;
  296. }
  297. public function createOrderPayment($orderShop, $type, $amount, $reference = null, $comment = null, $paidAt = null)
  298. {
  299. $classOrderPayment = $this->em->getClassMetadata(OrderPaymentInterface::class)->getName();
  300. $orderPayment = new $classOrderPayment;
  301. $orderPayment->setOrderShop($orderShop);
  302. $orderPayment->setType($type);
  303. $orderPayment->setAmount($amount);
  304. $orderPayment->setReference($reference);
  305. $orderPayment->setComment($comment);
  306. if ($paidAt) {
  307. $orderPayment->setPaidAt($paidAt);
  308. } else {
  309. $orderPayment->setPaidAt(new \DateTime('now'));
  310. }
  311. $this->em->persist($orderPayment);
  312. $this->em->flush();
  313. }
  314. public function isOrderPaid($orderShop)
  315. {
  316. if ($this->getTotalOrderPayments($orderShop) >= $this->priceUtils->getTotalWithTaxAndReduction($orderShop)) {
  317. return true;
  318. } else {
  319. return false;
  320. }
  321. }
  322. public function getTotalOrderPayments($orderShop): float
  323. {
  324. $totalAmount = floatval(0);
  325. foreach ($orderShop->getOrderPayments() as $orderPayment) {
  326. $totalAmount = $orderPayment->getAmount() + $totalAmount;
  327. }
  328. return $totalAmount;
  329. }
  330. public function deductAvailabilityProduct(\Lc\ShopBundle\Model\OrderShop $orderShop)
  331. {
  332. foreach ($orderShop->getOrderProducts() as $orderProduct) {
  333. switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) {
  334. case ProductFamily::BEHAVIOR_COUNT_STOCK_BY_MEASURE :
  335. //Disponibilité par unité de référence
  336. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  337. $newAvailability = $oldAvailability - ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient());
  338. $orderProduct->getProduct()->getProductFamily()->setAvailableQuantity($newAvailability);
  339. $this->em->persist($orderProduct->getProduct()->getProductFamily());
  340. break;
  341. case ProductFamily::BEHAVIOR_COUNT_STOCK_BY_PRODUCT_FAMILY :
  342. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  343. $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
  344. $orderProduct->getProduct()->getProductFamily()->setAvailableQuantity($newAvailability);
  345. $this->em->persist($orderProduct->getProduct()->getProductFamily());
  346. break;
  347. case ProductFamily::BEHAVIOR_COUNT_STOCK_BY_PRODUCT :
  348. $oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited();
  349. $newAvailability = $oldAvailability - $orderProduct->getQuantityOrder();
  350. $orderProduct->getProduct()->setAvailableQuantity($newAvailability);
  351. $this->em->persist($orderProduct->getProduct());
  352. break;
  353. }
  354. $this->em->flush();
  355. }
  356. }
  357. public function isProductAvailable(Product $product, $quanityOrder)
  358. {
  359. $quanityAsked = $quanityOrder;
  360. if($product->getProductFamily()->getBehaviorCountStock() == ProductFamily::BEHAVIOR_COUNT_STOCK_BY_MEASURE) {
  361. $quanityAsked = ($product->getQuantityInherited() / $product->getUnitInherited()->getCoefficient()) * $quanityOrder;
  362. }
  363. if ($product->getAvailableQuantityInherited() >= $quanityAsked) {
  364. return true;
  365. } else {
  366. return false;
  367. }
  368. }
  369. }