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.

647 lines
21KB

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