Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

696 lines
23KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Repository\Order;
  3. use App\Builder\Distribution\DistributionBuilder;
  4. use App\Entity\Distribution\Distribution;
  5. use App\Entity\User\User;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Lc\CaracoleBundle\Builder\File\DocumentBuilder;
  8. use Lc\CaracoleBundle\Model\Distribution\DistributionInterface;
  9. use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
  10. use Lc\CaracoleBundle\Model\Order\OrderStatusModel;
  11. use Lc\CaracoleBundle\Model\Product\ProductFamilyInterface;
  12. use Lc\CaracoleBundle\Model\Product\ProductInterface;
  13. use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface;
  14. use Lc\CaracoleBundle\Model\Reduction\ReductionCreditInterface;
  15. use Lc\CaracoleBundle\Model\Reduction\ReductionCreditModel;
  16. use Lc\CaracoleBundle\Model\User\VisitorInterface;
  17. use Lc\CaracoleBundle\Repository\Merchant\MerchantStore;
  18. use Lc\CaracoleBundle\Repository\MerchantStoreTrait;
  19. use Lc\CaracoleBundle\Repository\Reduction\ReductionCartStore;
  20. use Lc\CaracoleBundle\Repository\Reduction\ReductionCreditStore;
  21. use Lc\CaracoleBundle\Repository\Section\SectionStore;
  22. use Lc\CaracoleBundle\Resolver\OpeningResolver;
  23. use Lc\CaracoleBundle\Repository\SectionStoreTrait;
  24. use Lc\CaracoleBundle\Solver\Order\OrderShopSolver;
  25. use Lc\CaracoleBundle\Solver\Price\PriceSolver;
  26. use Lc\CaracoleBundle\Solver\Reduction\ReductionCartSolver;
  27. use Lc\SovBundle\Model\User\UserInterface;
  28. use Lc\CaracoleBundle\Repository\AbstractStore;
  29. use Lc\SovBundle\Repository\RepositoryQueryInterface;
  30. use Lc\SovBundle\Solver\Setting\SettingSolver;
  31. use Lc\SovBundle\Translation\FlashBagTranslator;
  32. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  33. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  34. class OrderShopStore extends AbstractStore
  35. {
  36. use SectionStoreTrait;
  37. use MerchantStoreTrait;
  38. protected OrderShopRepositoryQuery $query;
  39. protected EntityManagerInterface $entityManager;
  40. protected PriceSolver $priceSolver;
  41. protected DocumentBuilder $documentBuilder;
  42. protected ReductionCreditStore $reductionCreditStore;
  43. protected ReductionCartSolver $reductionCartSolver;
  44. protected SectionStore $sectionStore;
  45. protected OrderProductStore $orderProductStore;
  46. protected MerchantStore $merchantStore;
  47. protected FlashBagTranslator $flashBagTranslator;
  48. protected OpeningResolver $openingResolver;
  49. protected ParameterBagInterface $parameterBag;
  50. protected UrlGeneratorInterface $router;
  51. protected OrderShopSolver $orderShopSolver;
  52. protected ReductionCartStore $reductionCartStore;
  53. protected DistributionBuilder $distributionBuilder;
  54. protected SettingSolver $settingSolver;
  55. public function __construct(
  56. OrderShopRepositoryQuery $query,
  57. EntityManagerInterface $entityManager,
  58. PriceSolver $priceSolver,
  59. DocumentBuilder $documentBuilder,
  60. ReductionCreditStore $reductionCreditStore,
  61. ReductionCartSolver $reductionCartSolver,
  62. SectionStore $sectionStore,
  63. OrderProductStore $orderProductStore,
  64. MerchantStore $merchantStore,
  65. FlashBagTranslator $flashBagTranslator,
  66. ParameterBagInterface $parameterBag,
  67. UrlGeneratorInterface $router,
  68. OrderShopSolver $orderShopSolver,
  69. ReductionCartStore $reductionCartStore,
  70. DistributionBuilder $distributionBuilder,
  71. SettingSolver $settingSolver
  72. )
  73. {
  74. $this->query = $query;
  75. $this->entityManager = $entityManager;
  76. $this->priceSolver = $priceSolver;
  77. $this->documentBuilder = $documentBuilder;
  78. $this->reductionCreditStore = $reductionCreditStore;
  79. $this->reductionCartSolver = $reductionCartSolver;
  80. $this->sectionStore = $sectionStore;
  81. $this->orderProductStore = $orderProductStore;
  82. $this->merchantStore = $merchantStore;
  83. $this->flashBagTranslator = $flashBagTranslator;
  84. $this->parameterBag = $parameterBag;
  85. $this->router = $router;
  86. $this->orderShopSolver = $orderShopSolver;
  87. $this->reductionCartStore = $reductionCartStore;
  88. $this->distributionBuilder = $distributionBuilder;
  89. $this->settingSolver = $settingSolver;
  90. }
  91. public function orderByDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  92. {
  93. //$query->orderBy('id', 'DESC');
  94. return $query;
  95. }
  96. public function filtersDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  97. {
  98. $this
  99. ->addFilterBySectionOptionnal($query)
  100. ->addFilterByMerchantViaSectionOptionnal($query);
  101. return $query;
  102. }
  103. public function relationsDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  104. {
  105. $query->joinOrderProducts(true);
  106. return $query;
  107. }
  108. // getOrderShopsOfWeek
  109. //getByCurrentCycle
  110. public function getByCurrentDistribution($params = [], $query = null)
  111. {
  112. return $this->getBy(
  113. array_merge(
  114. [
  115. 'distribution' => $this->distributionBuilder->guessCurrentDistributionOrder(
  116. $this->section
  117. ),
  118. 'isValid' => true,
  119. ],
  120. $params
  121. ),
  122. $query
  123. );
  124. }
  125. // getOrderShopsOfWeekByUser
  126. //getByCurrentCycleAndUser
  127. public function getByCurrentDistributionAndUser(UserInterface $user = null, array $params = [], $query = null)
  128. {
  129. return $this->getByCurrentDistribution(
  130. array_merge(
  131. [
  132. 'user' => $user,
  133. 'excludeComplementaryOrderShops' => true
  134. ],
  135. $params
  136. ),
  137. $query
  138. );
  139. }
  140. //public $countOrderShopsOfWeek = null;
  141. // public function countByCurrentCycle(bool $excludeComplementaryOrderShops = true, $query = null)
  142. //countByCurrentCycle
  143. public function countByCurrentDistribution(array $params, $query = null)
  144. {
  145. return $this->countBy(
  146. array_merge(
  147. [
  148. 'distribution' => $this->distributionBuilder->guessCurrentDistributionOrder(
  149. $this->section
  150. ),
  151. 'excludeComplementaryOrderShops' => isset($params['excludeComplementaryOrderShops']) ?? true,
  152. ],
  153. $params
  154. ),
  155. $query
  156. );
  157. // @TODO : optimisation à remettre en place
  158. /*if (is_null($this->countOrderShopsOfWeek)) {
  159. $this->countOrderShopsOfWeek = $this->getByCurrentCycle(
  160. $section,
  161. [
  162. 'count' => true,
  163. 'excludeComplementaryOrderShops' => $excludeComplementaryOrderShops
  164. ]
  165. );
  166. }
  167. return $this->countOrderShopsOfWeek;*/
  168. }
  169. // getNextWeekId
  170. public function getNextCycleId(Distribution $distribution, $query = null): int
  171. {
  172. $lastOrder = $this->getOneLastValidByDistribution($distribution, $query);
  173. if ($lastOrder) {
  174. return intval($lastOrder->getCycleId() + 1);
  175. } else {
  176. return 1;
  177. }
  178. }
  179. public function getNextIdValidOrder($query = null): int
  180. {
  181. $lastOrder = $this->getOneLastValid($query);
  182. if ($lastOrder) {
  183. return intval($lastOrder->getIdValidOrder() + 1);
  184. } else {
  185. return 1;
  186. }
  187. }
  188. public function countValidByUserAllMerchant($user, $query = null): int
  189. {
  190. $this->resetContext();
  191. return $this->countBy(
  192. [
  193. 'user' => $user,
  194. 'isValid' => true,
  195. 'excludeComplementaryOrderShops' => true
  196. ],
  197. $query
  198. );
  199. }
  200. public function countValidByUser(UserInterface $user = null, $query = null): int
  201. {
  202. return $this->countBy(
  203. [
  204. 'user' => $user,
  205. 'isValid' => true,
  206. 'excludeComplementaryOrderShops' => true
  207. ],
  208. $query
  209. );
  210. }
  211. //countValidByCurrentCycle
  212. public function countValidByCurrentDistribution($query = null): int
  213. {
  214. return $this->countBy(
  215. [
  216. 'distribution' => $this->distributionBuilder->guessCurrentDistributionOrder($this->section),
  217. 'isValid' => true,
  218. 'excludeComplementaryOrderShops' => true
  219. ],
  220. $query
  221. );
  222. }
  223. // countValidOrderWithReductionCredit
  224. public function countValidWithReductionCredit(
  225. ReductionCreditInterface $reductionCredit,
  226. UserInterface $user = null,
  227. $query = null
  228. ): int
  229. {
  230. //TODO vérifier que ne pas utiliser createDefaultQuery est pertinent
  231. $query = $this->createQuery($query);
  232. if ($user) {
  233. $query->filterByUser($user);
  234. }
  235. $query
  236. ->selectCount()
  237. ->filterByReductionCredit($reductionCredit)
  238. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  239. return $query->count();
  240. }
  241. // countValidOrderWithReductionCart
  242. public function countValidWithReductionCart(
  243. ReductionCartInterface $reductionCart,
  244. $query = null
  245. ): int
  246. {
  247. $query = $this->createQuery($query);
  248. $query
  249. ->selectCount()
  250. ->filterByReductionCart($reductionCart)
  251. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  252. return $query->count();
  253. }
  254. // countValidOrderWithReductionCartPerUser
  255. public function countValidWithReductionCartByUser(
  256. ReductionCartInterface $reductionCart,
  257. UserInterface $user,
  258. $query = null
  259. ): int
  260. {
  261. $query = $this->createDefaultQuery($query);
  262. $query
  263. ->selectCount()
  264. ->filterByUser($user)
  265. ->filterByReductionCart($reductionCart)
  266. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  267. return $query->count();
  268. }
  269. // findCartCurrent
  270. public function getOneCartCurrent(
  271. UserInterface $user = null,
  272. VisitorInterface $visitor = null,
  273. $query = null
  274. ): ?OrderShopInterface
  275. {
  276. if (is_null($user) && is_null($visitor)) {
  277. return null;
  278. }
  279. $query = $this->createDefaultQuery($query);
  280. if (!is_null($user)) {
  281. $query->filterByUser($user);
  282. } else {
  283. if (!is_null($visitor)) {
  284. $query->filterByVisitor($visitor);
  285. }
  286. }
  287. $query
  288. ->selectOrderReductionCarts()
  289. ->filterByStatus(OrderStatusModel::$statusAliasAsCart);
  290. return $query->findOne();
  291. }
  292. // findLastOrderValidOfWeek
  293. //getOneLastValidByCycle
  294. public function getOneLastValidByDistribution(
  295. DistributionInterface $distribution,
  296. $query = null
  297. ): ?OrderShopInterface
  298. {
  299. $query = $this->createDefaultQuery($query);
  300. $query
  301. ->filterByDistribution($distribution)
  302. ->filterByStatus(OrderStatusModel::$statusAliasAsValid)
  303. ->filterIsNotComplementaryOrderShop()
  304. ->orderBy('.cycleId', 'DESC');
  305. return $query->findOne();
  306. }
  307. //findLastOrderValid
  308. public function getOneLastValid($query = null): ?OrderShopInterface
  309. {
  310. $query = $this->createDefaultQuery($query);
  311. $query
  312. ->filterByStatus(OrderStatusModel::$statusAliasAsValid)
  313. ->filterIsNotComplementaryOrderShop()
  314. ->orderBy('.idValidOrder', 'DESC');
  315. return $query->findOne();
  316. }
  317. public function countBy(array $params = [], $query = null)
  318. {
  319. $query = $this->createDefaultQuery($query);
  320. $query->selectCount();
  321. $this->applyGetByFilters($params, $query);
  322. return $query->count();
  323. }
  324. public function getBy(array $params = [], $query = null): array
  325. {
  326. $query = $this->createDefaultQuery($query);
  327. $this->applyGetByFilters($params, $query);
  328. $orderShops = $query->find();
  329. if (isset($params['mergeComplementaryOrderShops']) && $params['mergeComplementaryOrderShops'] == true) {
  330. $mergeComplementaryOrderShopsSameSection = isset($params['mergeComplementaryOrderShopsSameSection'])
  331. ? $params['mergeComplementaryOrderShopsSameSection'] : false;
  332. foreach ($orderShops as $orderShop) {
  333. $this->orderShopSolver->mergeComplentaryOrderShops($orderShop, true, $mergeComplementaryOrderShopsSameSection);
  334. }
  335. }
  336. return $orderShops;
  337. }
  338. protected function applyGetByFilters(array $params, $query)
  339. {
  340. if (isset($params['isDeliveryHome']) && $params['isDeliveryHome']) {
  341. $query->filterIsDeliveryHome();
  342. }
  343. if (isset($params['isDeliveryPointSale']) && $params['isDeliveryPointSale']) {
  344. $query->filterIsDeliveryPointSale();
  345. }
  346. if (isset($params['isMerchantOnline'])) {
  347. $query->filterIsMerchantOnline();
  348. }
  349. if (isset($params['select'])) {
  350. $query->selectParam($params['select']);
  351. }
  352. if (isset($params['dateStart']) || isset($params['dateEnd'])) {
  353. $params['dateField'] = isset($params['dateField']) ? $params['dateField'] : 'validationDate';
  354. }
  355. if (isset($params['dateStart'])) {
  356. $query->filterByDateStart($params['dateField'], $params['dateStart']);
  357. }
  358. if (isset($params['dateEnd'])) {
  359. $query->filterByDateEnd($params['dateField'], $params['dateEnd']);
  360. }
  361. if (isset($params['distribution'])) {
  362. $query->filterByDistribution($params['distribution']);
  363. }
  364. if (isset($params['distributions'])) {
  365. $query->filterByDistributions($params['distributions']);
  366. }
  367. if (isset($params['isCart'])) {
  368. $query->filterByStatus(OrderStatusModel::$statusAliasAsCart);
  369. }
  370. if (isset($params['isValid'])) {
  371. $query->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  372. }
  373. if (isset($params['isWaitingDelivery'])) {
  374. $query->filterByStatus(OrderStatusModel::$statusAliasWaitingDelivery);
  375. }
  376. if (isset($params['orderStatus'])) {
  377. $query->filterByStatus([$params['orderStatus']]);
  378. }
  379. if (isset($params['user'])) {
  380. $query->filterByUser($params['user']);
  381. }
  382. if (isset($params['address'])) {
  383. $query->filterByAddress($params['address']);
  384. }
  385. if (isset($params['minimumTomorrowDelivery'])) {
  386. $query->filterMinimumTomorrowDelivery();
  387. }
  388. if (isset($params['mergeComplementaryOrderShops']) && $params['mergeComplementaryOrderShops']) {
  389. $query
  390. ->joinComplementaryOrderShops();
  391. }
  392. if (isset($params['isComplementaryOrderShop']) && $params['isComplementaryOrderShop']) {
  393. $query->filterIsComplementaryOrderShop();
  394. if (isset($params['sectionMainOrderShop']) && $params['sectionMainOrderShop']) {
  395. $query->filterSectionMainOrderShop($params['sectionMainOrderShop']);
  396. }
  397. }
  398. if ((isset($params['excludeComplementaryOrderShops']) && $params['excludeComplementaryOrderShops'])
  399. || (isset($params['mergeComplementaryOrderShops']) && $params['mergeComplementaryOrderShops'])) {
  400. $query->filterIsNullMainOrderShop();
  401. }
  402. if (isset($params['joinProductFamily'])) {
  403. $query->joinProductFamily(true);
  404. }
  405. if (isset($params['orderBy'])) {
  406. $sort = isset($params['orderByDirection']) ? $params['orderByDirection'] : 'DESC';
  407. $query->orderBy($params['orderBy'], $sort);
  408. } else {
  409. $query->orderBy('.id', 'DESC');
  410. }
  411. if (isset($params['groupBy'])) {
  412. $query->groupBy($params['groupBy']);
  413. }
  414. return $query;
  415. }
  416. public function isReductionGiftUsed(ReductionCreditInterface $reductionGift, $query = null)
  417. {
  418. if ($this->countValidWithReductionCredit($reductionGift, null, $query)) {
  419. return true;
  420. } else {
  421. return false;
  422. }
  423. }
  424. public function isReductionCreditUsed(
  425. ReductionCreditInterface $reductionCredit,
  426. UserInterface $user = null,
  427. $query = null
  428. )
  429. {
  430. if ($this->countValidWithReductionCredit($reductionCredit, $user, $query)) {
  431. return true;
  432. } else {
  433. return false;
  434. }
  435. }
  436. public function getReductionCreditsAvailableByUser(UserInterface $user): array
  437. {
  438. $reductionCredits = $this->reductionCreditStore
  439. ->setMerchant($this->merchant)
  440. ->getByTypeAndUser(ReductionCreditModel::TYPE_CREDIT, $user);
  441. $reductionCreditsArray = [];
  442. foreach ($reductionCredits as $reductionCredit) {
  443. if (!$this->countValidWithReductionCredit($reductionCredit, $user)) {
  444. $reductionCreditsArray[] = $reductionCredit;
  445. }
  446. }
  447. return $reductionCreditsArray;
  448. }
  449. public function getReductionGiftsAvailableByUser(UserInterface $user): array
  450. {
  451. $reductionGifts = $this->reductionCreditStore
  452. ->setMerchant($this->merchant)
  453. ->getByTypeAndUser(ReductionCreditModel::TYPE_GIFT, $user);
  454. $reductionGiftsArray = [];
  455. foreach ($reductionGifts as $reductionGift) {
  456. if (!$this->countValidWithReductionCredit($reductionGift, $user)) {
  457. $reductionGiftsArray[] = $reductionGift;
  458. }
  459. }
  460. return $reductionGiftsArray;
  461. }
  462. // getReductionCartRemainingQuantity
  463. public function getReductionCartRemainingQuantity(ReductionCartInterface $reductionCart): float
  464. {
  465. return $reductionCart->getAvailableQuantity() - $this->countValidWithReductionCart(
  466. $reductionCart
  467. );
  468. }
  469. // getReductionCartUsedQuantityPerUser
  470. public function getReductionCartUsedQuantityByUser(
  471. ReductionCartInterface $reductionCart,
  472. UserInterface $user
  473. ): float
  474. {
  475. return $this->countValidWithReductionCartByUser($reductionCart, $user);
  476. }
  477. // getReductionCartUsedQuantity
  478. public function getReductionCartUsedQuantity(ReductionCartInterface $reductionCart): float
  479. {
  480. return $this->countValidWithReductionCart($reductionCart);
  481. }
  482. // getReductionCartRemainingQuantityPerUser
  483. public function getReductionCartRemainingQuantityByUser(
  484. ReductionCartInterface $reductionCart,
  485. UserInterface $user
  486. ): float
  487. {
  488. if ($reductionCart->getAvailableQuantityPerUser()) {
  489. return $reductionCart->getAvailableQuantityPerUser() - $this->countValidWithReductionCartByUser(
  490. $reductionCart,
  491. $user
  492. );
  493. }
  494. return false;
  495. }
  496. // findAllAvailableForUser / getReductionCartsAvailableByUser
  497. public function getReductionCartAvailableByUser(UserInterface $user, $query = null)
  498. {
  499. $reductionCarts = $this->reductionCartStore
  500. ->setMerchant($this->merchant)
  501. ->getOnline();
  502. $reductionCartsArray = [];
  503. foreach ($reductionCarts as $reductionCart) {
  504. if ($this->reductionCartSolver->matchWithUser($reductionCart, $user)
  505. && $this->reductionCartSolver->matchWithGroupUser($reductionCart, $user)
  506. && $this->getReductionCartRemainingQuantityByUser($reductionCart, $user)
  507. && ($reductionCart->getUsers()->count() > 0 || $reductionCart->getGroupUsers()->count() > 0)
  508. && (!$this->merchant || $reductionCart->getMerchant() == $this->merchant)) {
  509. $reductionCartsArray[] = $reductionCart;
  510. }
  511. }
  512. return $reductionCartsArray;
  513. }
  514. //countValidOrderProductsOfCyclesByProducts
  515. public function countValidOrderProductsOfDistributionsByProducts(
  516. array $distributions,
  517. array $products,
  518. ProductFamilyInterface $productFamily,
  519. $query = null
  520. ): array
  521. {
  522. $query = $this->createDefaultQuery($query);
  523. $query
  524. ->filterByAlias(OrderStatusModel::$statusAliasAsValid)
  525. ->filterByDistributions($distributions)
  526. ->filterByProducts($products)
  527. ->selectSum()
  528. ->groupBy('distribution.cycleNumber, product.id');
  529. //TODO vérifier ou est utilisé cette fonction ???
  530. return $query->find();
  531. }
  532. //countValidOrderProductsOfCycleByProduct
  533. public function countValidOrderProductsOfDistributionByProduct(
  534. DistributionInterface $distribution,
  535. ProductInterface $product,
  536. $query = null
  537. ): float
  538. {
  539. //TODO attention à vérifier
  540. $query = $this->createQuery($query);
  541. $query
  542. ->filterByAlias(OrderStatusModel::$statusAliasAsValid)
  543. ->filterByDistribution($distribution)
  544. ->filterByProduct($product)
  545. ->selectSumQuantityOrder()
  546. ->joinDistribution()
  547. ->groupBy('distribution.cycleNumber, product.id');
  548. $result = $query->findOne();
  549. if ($result) {
  550. return $result['quantity'];
  551. }
  552. return 0;
  553. }
  554. public function isReductionCreditAllowAddToOrder(
  555. OrderShopInterface $orderShop,
  556. ReductionCreditInterface $reductionCredit
  557. )
  558. {
  559. $user = $orderShop->getUser();
  560. // appartient à l'utilisateur
  561. if (!$reductionCredit->getUsers()->contains($user)) {
  562. // @TODO : déplacer la gestion du flash message
  563. $this->flashBagTranslator->add('error', 'userNotAllow', 'ReductionCredit');
  564. return false;
  565. }
  566. // n'a pas été utilisé
  567. if ($reductionCredit->getType() == ReductionCreditModel::TYPE_CREDIT) {
  568. if ($this->countValidWithReductionCredit($reductionCredit, $user) > 0) {
  569. // @TODO : déplacer la gestion du flash message
  570. $this->flashBagTranslator->add('error', 'alreadyUse', 'ReductionCredit');
  571. return false;
  572. }
  573. } else {
  574. if ($this->countValidWithReductionCredit($reductionCredit) > 0) {
  575. // @TODO : déplacer la gestion du flash message
  576. $this->flashBagTranslator->add('error', 'alreadyUse', 'ReductionCredit');
  577. return false;
  578. }
  579. }
  580. return true;
  581. }
  582. public function getCartAlone($query = null)
  583. {
  584. $query = $this->createQuery($query);
  585. $query->filterByAlias(OrderStatusModel::$statusAliasAsCart);
  586. $query->filterByUserIsNull();
  587. $query->filterByVisitorIsNull();
  588. return $query->limit(10000)->find();
  589. }
  590. }