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.

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