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.

602 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. if(isset($this->section) && $this->section) {
  85. $query->filterBySection($this->section);
  86. }
  87. if(isset($this->merchant) && $this->merchant) {
  88. $query->filterByMerchant($this->merchant);
  89. }
  90. return $query;
  91. }
  92. public function relationsDefault(RepositoryQueryInterface $query): RepositoryQueryInterface
  93. {
  94. $query->joinOrderProduct();
  95. return $query;
  96. }
  97. // getOrderShopsOfWeek
  98. public function getByCurrentCycle($params = [], $query = null)
  99. {
  100. return $this->getBy(
  101. array_merge(
  102. [
  103. 'cycleNumber' => $this->orderShopSolver->getCycleNumberCurrentOrder($this->section),
  104. 'isValid' => true,
  105. ],
  106. $params
  107. ),
  108. $query
  109. );
  110. }
  111. // getOrderShopsOfWeekByUser
  112. public function getByCurrentCycleAndUser(UserInterface $user = null, array $params = [], $query = null)
  113. {
  114. return $this->getByCurrentCycle(
  115. array_merge(
  116. [
  117. 'user' => $user,
  118. 'cycleNumber' => $this->orderShopSolver->getCycleNumberCurrentOrder($this->section),
  119. 'excludeComplementaryOrderShops' => true
  120. ],
  121. $params
  122. ),
  123. $query
  124. );
  125. }
  126. //public $countOrderShopsOfWeek = null;
  127. // public function countByCurrentCycle(bool $excludeComplementaryOrderShops = true, $query = null)
  128. public function countByCurrentCycle(array $params, $query = null)
  129. {
  130. return $this->countBy(
  131. array_merge(
  132. [
  133. 'cycleNumber' => $this->orderShopSolver->getCycleNumberCurrentOrder($this->section),
  134. 'excludeComplementaryOrderShops' => isset($params['excludeComplementaryOrderShops']) ?? true,
  135. ],
  136. $params
  137. ),
  138. $query
  139. );
  140. // @TODO : optimisation à remettre en place
  141. /*if (is_null($this->countOrderShopsOfWeek)) {
  142. $this->countOrderShopsOfWeek = $this->getByCurrentCycle(
  143. $section,
  144. [
  145. 'count' => true,
  146. 'excludeComplementaryOrderShops' => $excludeComplementaryOrderShops
  147. ]
  148. );
  149. }
  150. return $this->countOrderShopsOfWeek;*/
  151. }
  152. // getNextWeekId
  153. public function getNextCycleId(int $cycleNumber, $query = null): int
  154. {
  155. $lastOrder = $this->getOneLastValidByCycle($cycleNumber, $query);
  156. if ($lastOrder) {
  157. return intval($lastOrder->getCycleId() + 1);
  158. } else {
  159. return 1;
  160. }
  161. }
  162. public function getNextIdValidOrder($query = null): int
  163. {
  164. $lastOrder = $this->getOneLastValid($query);
  165. if ($lastOrder) {
  166. return intval($lastOrder->getIdValidOrder() + 1);
  167. } else {
  168. return 1;
  169. }
  170. }
  171. // countValidOrderShopByUserAllMerchant
  172. public function countValidByUserAllMerchant($user, $query = null): int
  173. {
  174. return $this->countBy(
  175. [
  176. 'user' => $user,
  177. 'isValid' => true,
  178. // @TODO : à tester
  179. 'isMerchantOnline' => true,
  180. 'excludeComplementaryOrderShops' => true
  181. ],
  182. $query
  183. );
  184. }
  185. public function countValidByUser(UserInterface $user = null, $query = null): int
  186. {
  187. return $this->countBy(
  188. [
  189. 'user' => $user,
  190. 'isValid' => true,
  191. 'excludeComplementaryOrderShops' => true
  192. ],
  193. $query
  194. );
  195. }
  196. public function countValidByCurrentCycle($query = null): int
  197. {
  198. return $this->countBy(
  199. [
  200. 'cycleNumber' => $this->orderShopSolver->getCycleNumberCurrentOrder($this->section),
  201. 'isValid' => true,
  202. 'excludeComplementaryOrderShops' => true
  203. ],
  204. $query
  205. );
  206. }
  207. // countValidOrderWithReductionCredit
  208. public function countValidWithReductionCredit(
  209. ReductionCreditInterface $reductionCredit,
  210. UserInterface $user = null,
  211. $query = null
  212. ): int {
  213. $query = $this->createDefaultQuery($query);
  214. if ($user) {
  215. $query->filterByUser($user);
  216. }
  217. $query
  218. ->selectCount()
  219. ->filterByReductionCredit($reductionCredit)
  220. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  221. return $query->count();
  222. }
  223. // countValidOrderWithReductionCart
  224. public function countValidWithReductionCart(
  225. ReductionCartInterface $reductionCart,
  226. $query = null
  227. ): int {
  228. $query = $this->createDefaultQuery($query);
  229. $query
  230. ->selectCount()
  231. ->filterByReductionCart($reductionCart)
  232. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  233. return $query->count();
  234. }
  235. // countValidOrderWithReductionCartPerUser
  236. public function countValidWithReductionCartByUser(
  237. ReductionCartInterface $reductionCart,
  238. UserInterface $user,
  239. $query = null
  240. ): int {
  241. $query = $this->createDefaultQuery($query);
  242. $query
  243. ->selectCount()
  244. ->filterByUser($user)
  245. ->filterByReductionCart($reductionCart)
  246. ->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  247. return $query->count();
  248. }
  249. // findCartCurrent
  250. public function getOneCartCurrent(UserInterface $user = null, VisitorInterface $visitor = null, $query = null): ?OrderShopInterface
  251. {
  252. $query = $this->createDefaultQuery($query);
  253. if (!is_null($user)) {
  254. $query->filterByUser($user);
  255. }
  256. else {
  257. if (!is_null($visitor)) {
  258. $query->filterByVisitor($visitor);
  259. }
  260. }
  261. $query
  262. ->selectOrderReductionCarts()
  263. ->filterByStatus(OrderStatusModel::$statusAliasAsCart);
  264. return $query->findOne();
  265. }
  266. // findLastOrderValidOfWeek
  267. public function getOneLastValidByCycle(int $cycleNumber, $query = null): ?OrderShopInterface
  268. {
  269. $query = $this->createDefaultQuery($query);
  270. $query
  271. ->filterByCycleNumber($cycleNumber)
  272. ->filterByStatus(OrderStatusModel::$statusAliasAsValid)
  273. ->filterIsNotComplementaryOrderShop()
  274. ->orderBy('.cycleId', 'DESC');
  275. return $query->findOne();
  276. }
  277. //findLastOrderValid
  278. public function getOneLastValid($query = null): ?OrderShopInterface
  279. {
  280. $query = $this->createDefaultQuery($query);
  281. $query
  282. ->filterByStatus(OrderStatusModel::$statusAliasAsValid)
  283. ->filterIsNotComplementaryOrderShop()
  284. ->orderBy('.idValidOrder', 'DESC');
  285. return $query->findOne();
  286. }
  287. public function countBy(array $params = [], $query = null)
  288. {
  289. $query = $this->createDefaultQuery($query);
  290. $query->selectCount();
  291. $this->applyGetByFilters($params, $query);
  292. return $query->count();
  293. }
  294. public function getBy(array $params = [], $query = null): array
  295. {
  296. $query = $this->createDefaultQuery($query);
  297. $this->applyGetByFilters($params, $query);
  298. $orderShops = $query->find();
  299. if (isset($params['mergeComplementaryOrderShops'])) {
  300. foreach ($orderShops as $orderShop) {
  301. $this->orderShopSolver->mergeComplentaryOrderShops($orderShop);
  302. }
  303. }
  304. return $orderShops;
  305. }
  306. protected function applyGetByFilters(array $params, $query)
  307. {
  308. if (isset($params['isMerchantOnline'])) {
  309. $query->filterIsMerchantOnline();
  310. }
  311. if (isset($params['select'])) {
  312. $query->selectParam($params['select']);
  313. }
  314. if (isset($params['dateStart']) || isset($params['dateEnd'])) {
  315. $params['dateField'] = isset($params['dateField']) ? $params['dateField'] : 'validationDate';
  316. }
  317. if (isset($params['dateStart'])) {
  318. $query->filterByDateStart($params['dateField'], $params['dateStart']);
  319. }
  320. if (isset($params['dateEnd'])) {
  321. $query->filterByDateEnd($params['dateField'], $params['dateEnd']);
  322. }
  323. if (isset($params['cycleNumber'])) {
  324. $query->filterByCycleNumber($params['cycleNumber']);
  325. }
  326. if (isset($params['isCart'])) {
  327. $query->filterByStatus(OrderStatusModel::$statusAliasAsCart);
  328. }
  329. if (isset($params['isValid'])) {
  330. $query->filterByStatus(OrderStatusModel::$statusAliasAsValid);
  331. }
  332. if (isset($params['isWaitingDelivery'])) {
  333. $query->filterByStatus(OrderStatusModel::$statusAliasWaitingDelivery);
  334. }
  335. if (isset($params['orderStatus'])) {
  336. $query->filterByStatus($params['orderStatus']);
  337. }
  338. if (isset($params['user'])) {
  339. $query->filterByUser($params['user']);
  340. }
  341. if (isset($params['address'])) {
  342. $query->filterByAddress($params['address']);
  343. }
  344. if (isset($params['mergeComplementaryOrderShops'])) {
  345. $query
  346. ->joinComplementaryOrderShops();
  347. }
  348. if (isset($params['excludeComplementaryOrderShops']) || isset($params['mergeComplementaryOrderShops'])) {
  349. $query->filterIsNullMainOrderShop();
  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. && (!$this->merchant || $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. }