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.

579 lines
19KB

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