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.

601 lines
20KB

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