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.

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