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.

653 line
22KB

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