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.

OrderShopStore.php 21KB

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