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.

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