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.

632 lines
21KB

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