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.

663 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\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. $mergeComplementaryOrderShopsSameSection = isset($params['mergeComplementaryOrderShopsSameSection'])
  326. ? $params['mergeComplementaryOrderShopsSameSection'] : false;
  327. foreach ($orderShops as $orderShop) {
  328. $this->orderShopSolver->mergeComplentaryOrderShops($orderShop, true, $mergeComplementaryOrderShopsSameSection);
  329. }
  330. }
  331. return $orderShops;
  332. }
  333. protected function applyGetByFilters(array $params, $query)
  334. {
  335. if (isset($params['isMerchantOnline'])) {
  336. $query->filterIsMerchantOnline();
  337. }
  338. if (isset($params['select'])) {
  339. $query->selectParam($params['select']);
  340. }
  341. if (isset($params['dateStart']) || isset($params['dateEnd'])) {
  342. $params['dateField'] = isset($params['dateField']) ? $params['dateField'] : 'validationDate';
  343. }
  344. if (isset($params['dateStart'])) {
  345. $query->filterByDateStart($params['dateField'], $params['dateStart']);
  346. }
  347. if (isset($params['dateEnd'])) {
  348. $query->filterByDateEnd($params['dateField'], $params['dateEnd']);
  349. }
  350. if (isset($params['distribution'])) {
  351. $query->filterByDistribution($params['distribution']);
  352. }
  353. if (isset($params['distributions'])) {
  354. $query->filterByDistributions($params['distributions']);
  355. }
  356. if (isset($params['isCart'])) {
  357. $query->filterByStatus(OrderStatusModel::$statusAliasAsCart);
  358. }
  359. if (isset($params['isValid'])) {
  360. $query->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  361. }
  362. if (isset($params['isWaitingDelivery'])) {
  363. $query->filterByStatus(OrderStatusModel::$statusAliasWaitingDelivery);
  364. }
  365. if (isset($params['orderStatus'])) {
  366. $query->filterByStatus([$params['orderStatus']]);
  367. }
  368. if (isset($params['user'])) {
  369. $query->filterByUser($params['user']);
  370. }
  371. if (isset($params['address'])) {
  372. $query->filterByAddress($params['address']);
  373. }
  374. if (isset($params['minimumTomorrowDelivery'])) {
  375. $query->filterMinimumTomorrowDelivery();
  376. }
  377. if (isset($params['mergeComplementaryOrderShops']) && $params['mergeComplementaryOrderShops']) {
  378. $query
  379. ->joinComplementaryOrderShops();
  380. }
  381. if (isset($params['isComplementaryOrderShop']) && $params['isComplementaryOrderShop']) {
  382. $query->filterIsComplementaryOrderShop();
  383. if(isset($params['sectionMainOrderShop']) && $params['sectionMainOrderShop']) {
  384. $query->filterSectionMainOrderShop($params['sectionMainOrderShop']);
  385. }
  386. }
  387. if ((isset($params['excludeComplementaryOrderShops']) && $params['excludeComplementaryOrderShops'])
  388. || (isset($params['mergeComplementaryOrderShops']) && $params['mergeComplementaryOrderShops'])) {
  389. $query->filterIsNullMainOrderShop();
  390. }
  391. if (isset($params['joinProductFamily'])) {
  392. $query->joinProductFamily(true);
  393. }
  394. if (isset($params['orderBy'])) {
  395. $sort = isset($params['orderByDirection']) ? $params['orderByDirection'] : 'DESC';
  396. $query->orderBy($params['orderBy'], $sort);
  397. } else {
  398. $query->orderBy('.id', 'DESC');
  399. }
  400. if (isset($params['groupBy'])) {
  401. $query->groupBy($params['groupBy']);
  402. }
  403. return $query;
  404. }
  405. public function isReductionGiftUsed(ReductionCreditInterface $reductionGift, $query = null)
  406. {
  407. if ($this->countValidWithReductionCredit($reductionGift, null, $query)) {
  408. return true;
  409. } else {
  410. return false;
  411. }
  412. }
  413. public function isReductionCreditUsed(
  414. ReductionCreditInterface $reductionCredit,
  415. UserInterface $user = null,
  416. $query = null
  417. ) {
  418. if ($this->countValidWithReductionCredit($reductionCredit, $user, $query)) {
  419. return true;
  420. } else {
  421. return false;
  422. }
  423. }
  424. public function getReductionCreditsAvailableByUser(UserInterface $user): array
  425. {
  426. $reductionCredits = $this->reductionCreditStore
  427. ->setMerchant($this->merchant)
  428. ->getByTypeAndUser(ReductionCreditModel::TYPE_CREDIT, $user);
  429. $reductionCreditsArray = [];
  430. foreach ($reductionCredits as $reductionCredit) {
  431. if (!$this->countValidWithReductionCredit($reductionCredit, $user)) {
  432. $reductionCreditsArray[] = $reductionCredit;
  433. }
  434. }
  435. return $reductionCreditsArray;
  436. }
  437. public function getReductionGiftsAvailableByUser(UserInterface $user): array
  438. {
  439. $reductionGifts = $this->reductionCreditStore
  440. ->setMerchant($this->merchant)
  441. ->getByTypeAndUser(ReductionCreditModel::TYPE_GIFT, $user);
  442. $reductionGiftsArray = [];
  443. foreach ($reductionGifts as $reductionGift) {
  444. if (!$this->countValidWithReductionCredit($reductionGift, $user)) {
  445. $reductionGiftsArray[] = $reductionGift;
  446. }
  447. }
  448. return $reductionGiftsArray;
  449. }
  450. // getReductionCartRemainingQuantity
  451. public function getReductionCartRemainingQuantity(ReductionCartInterface $reductionCart): float
  452. {
  453. return $reductionCart->getAvailableQuantity() - $this->countValidWithReductionCart(
  454. $reductionCart
  455. );
  456. }
  457. // getReductionCartUsedQuantityPerUser
  458. public function getReductionCartUsedQuantityByUser(
  459. ReductionCartInterface $reductionCart,
  460. UserInterface $user
  461. ): float {
  462. return $this->countValidWithReductionCartByUser($reductionCart, $user);
  463. }
  464. // getReductionCartUsedQuantity
  465. public function getReductionCartUsedQuantity(ReductionCartInterface $reductionCart): float
  466. {
  467. return $this->countValidWithReductionCart($reductionCart);
  468. }
  469. // getReductionCartRemainingQuantityPerUser
  470. public function getReductionCartRemainingQuantityByUser(
  471. ReductionCartInterface $reductionCart,
  472. UserInterface $user
  473. ): float {
  474. if ($reductionCart->getAvailableQuantityPerUser()) {
  475. return $reductionCart->getAvailableQuantityPerUser() - $this->countValidWithReductionCartByUser(
  476. $reductionCart,
  477. $user
  478. );
  479. }
  480. return false;
  481. }
  482. // findAllAvailableForUser / getReductionCartsAvailableByUser
  483. public function getReductionCartAvailableByUser(UserInterface $user, $query = null)
  484. {
  485. $reductionCarts = $this->reductionCartStore
  486. ->setMerchant($this->merchant)
  487. ->getOnline();
  488. $reductionCartsArray = [];
  489. foreach ($reductionCarts as $reductionCart) {
  490. if ($this->reductionCartSolver->matchWithUser($reductionCart, $user)
  491. && $this->reductionCartSolver->matchWithGroupUser($reductionCart, $user)
  492. && $this->getReductionCartRemainingQuantityByUser($reductionCart, $user)
  493. && ($reductionCart->getUsers()->count() > 0 || $reductionCart->getGroupUsers()->count() > 0)
  494. && (!$this->merchant || $reductionCart->getMerchant() == $this->merchant)) {
  495. $reductionCartsArray[] = $reductionCart;
  496. }
  497. }
  498. return $reductionCartsArray;
  499. }
  500. //countValidOrderProductsOfCyclesByProducts
  501. public function countValidOrderProductsOfDistributionsByProducts(
  502. array $distributions,
  503. array $products,
  504. $query = null
  505. ): array {
  506. $query = $this->createDefaultQuery($query);
  507. $query
  508. ->filterByAlias(OrderStatusModel::$statusAliasAsValid)
  509. ->filterByDistributions($distributions)
  510. ->filterByProducts($products)
  511. ->selectSum()
  512. ->groupBy('distribution.cycleNumber, product.id');
  513. return $query->find();
  514. }
  515. //countValidOrderProductsOfCycleByProduct
  516. public function countValidOrderProductsOfDistributionByProduct(
  517. DistributionInterface $distribution,
  518. ProductInterface $product,
  519. $query = null
  520. ): ?string {
  521. //TODO attention à vérifier
  522. $query = $this->createQuery($query);
  523. $query
  524. ->filterByAlias(OrderStatusModel::$statusAliasAsValid)
  525. ->filterByDistribution($distribution)
  526. ->filterByProduct($product)
  527. ->selectSumQuantityOrder()
  528. ->joinDistribution()
  529. ->groupBy('distribution.cycleNumber, product.id');
  530. $result = $query->findOne();
  531. if ($result) {
  532. return $result['quantity'];
  533. }
  534. return null;
  535. }
  536. public function isReductionCreditAllowAddToOrder(
  537. OrderShopInterface $orderShop,
  538. ReductionCreditInterface $reductionCredit
  539. ) {
  540. $user = $orderShop->getUser();
  541. // appartient à l'utilisateur
  542. if (!$reductionCredit->getUsers()->contains($user)) {
  543. // @TODO : déplacer la gestion du flash message
  544. $this->flashBagTranslator->add('error', 'userNotAllow', 'ReductionCredit');
  545. return false;
  546. }
  547. // n'a pas été utilisé
  548. if ($reductionCredit->getType() == ReductionCreditModel::TYPE_CREDIT) {
  549. if ($this->countValidWithReductionCredit($reductionCredit, $user) > 0) {
  550. // @TODO : déplacer la gestion du flash message
  551. $this->flashBagTranslator->add('error', 'alreadyUse', 'ReductionCredit');
  552. return false;
  553. }
  554. } else {
  555. if ($this->countValidWithReductionCredit($reductionCredit) > 0) {
  556. // @TODO : déplacer la gestion du flash message
  557. $this->flashBagTranslator->add('error', 'alreadyUse', 'ReductionCredit');
  558. return false;
  559. }
  560. }
  561. return true;
  562. }
  563. }