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.

317 lines
11KB

  1. <?php
  2. namespace Lc\CaracoleBundle\Resolver;
  3. use Lc\CaracoleBundle\Definition\SectionSettingDefinition;
  4. use Lc\CaracoleBundle\Model\Section\OpeningInterface;
  5. use Lc\CaracoleBundle\Model\Section\SectionInterface;
  6. use Lc\CaracoleBundle\Repository\Order\OrderShopStore;
  7. use Lc\CaracoleBundle\Repository\Section\OpeningStore;
  8. use Lc\CaracoleBundle\Solver\Section\OpeningSolver;
  9. use Lc\SovBundle\Model\User\UserInterface;
  10. use Lc\SovBundle\Solver\Setting\SettingSolver;
  11. use Symfony\Component\Security\Core\Security;
  12. class OpeningResolver
  13. {
  14. const OPENING_CONTEXT_FRONTEND = 'frontend';
  15. const OPENING_CONTEXT_BACKEND = 'backend';
  16. protected array $messages = [];
  17. protected SectionResolver $sectionResolver;
  18. protected Security $security;
  19. protected OrderShopStore $orderShopStore;
  20. protected SettingSolver $settingSolver;
  21. protected OpeningStore $openingStore;
  22. protected OpeningSolver $openingSolver;
  23. public function __construct(
  24. SectionResolver $sectionResolver,
  25. Security $security,
  26. OrderShopStore $orderShopStore,
  27. SettingSolver $settingSolver,
  28. OpeningStore $openingStore,
  29. OpeningSolver $openingSolver
  30. ) {
  31. $this->sectionResolver = $sectionResolver;
  32. $this->security = $security;
  33. $this->orderShopStore = $orderShopStore;
  34. $this->settingSolver = $settingSolver;
  35. $this->openingStore = $openingStore;
  36. $this->openingSolver = $openingSolver;
  37. }
  38. public function isOpenSale(
  39. SectionInterface $section = null,
  40. UserInterface $user = null,
  41. string $context = null
  42. ): bool {
  43. // Initialisation
  44. $this->messages = [];
  45. if (is_null($section)) {
  46. $section = $this->sectionResolver->getCurrent(true);
  47. }
  48. if (is_null($user)) {
  49. $user = $this->security->getUser();
  50. }
  51. $date = new \DateTime();
  52. // État des prise de commande (voir configuration de section)
  53. $orderState = $this->settingSolver->getSettingValue($section, SectionSettingDefinition::SETTING_ORDER_STATE);
  54. if ($orderState == SectionSettingDefinition::VALUE_ORDER_STATE_OPEN) {
  55. $this->addMessage('Les commandes sont ouvertes (configuration de la section).');
  56. return true;
  57. }
  58. if ($orderState == SectionSettingDefinition::VALUE_ORDER_STATE_CLOSED) {
  59. $this->addMessage('Les commandes sont fermées (configuration de la section).');
  60. return false;
  61. }
  62. // Nombre maximum de commandes par cycle (voir configuration de section)
  63. if ($this->isMaximumOrderDistributionAchieved($section)) {
  64. $this->addMessage('Le nombre maximum de commande a été atteint.');
  65. return false;
  66. }
  67. // Période de fermeture des commandes issue de la configuration de la section (congés)
  68. if ($this->isClosingPeriod($section, $date)) {
  69. $this->addMessage(
  70. 'Les commandes sont fermées (période de fermeture des commandes dans la configuration de la section).'
  71. );
  72. return false;
  73. }
  74. // Période d'ouverture des commandes
  75. $openings = $section->getOpenings();
  76. foreach ($openings as $opening) {
  77. if (!$opening->getGroupUser() || ($opening->getGroupUser() && $user && $user->getGroupUsers()->contains(
  78. $opening->getGroupUser()
  79. ))) {
  80. if ($this->isDateMatchWithOpening($date, $opening)) {
  81. $this->addMessage('Les commandes sont ouvertes (périodes d\'ouverture classique des commandes).');
  82. return true;
  83. }
  84. }
  85. }
  86. $this->addMessage('Les commandes sont fermées (périodes d\'ouverture classique des commandes).');
  87. return false;
  88. }
  89. public function isOpenFullTime(SectionInterface $section = null)
  90. {
  91. if (is_null($section)) {
  92. $section = $this->sectionResolver->getCurrent();
  93. }
  94. $orderState = $this->settingSolver->getSettingValue($section, SectionSettingDefinition::SETTING_ORDER_STATE);
  95. if ($orderState == SectionSettingDefinition::VALUE_ORDER_STATE_OPEN) {
  96. return true;
  97. }
  98. return false;
  99. }
  100. // isHolidays
  101. public function isClosingPeriod(SectionInterface $section = null)
  102. {
  103. if (is_null($section)) {
  104. $section = $this->sectionResolver->getCurrent();
  105. }
  106. $date = new \DateTime();
  107. $orderClosedStart = $this->settingSolver->getSettingValue(
  108. $section,
  109. SectionSettingDefinition::SETTING_ORDER_CLOSED_START
  110. );
  111. $orderClosedEnd = $this->settingSolver->getSettingValue(
  112. $section,
  113. SectionSettingDefinition::SETTING_ORDER_CLOSED_END
  114. );
  115. if ($orderClosedStart && $orderClosedEnd && $date >= $orderClosedStart && $date <= $orderClosedEnd) {
  116. return true;
  117. }
  118. return false;
  119. }
  120. // isMaximumOrderWeekAchieved
  121. //isMaximumOrderCycleAchieved
  122. public function isMaximumOrderDistributionAchieved(SectionInterface $section)
  123. {
  124. $countOrderShopCycle = $this->orderShopStore
  125. ->setSection($section)
  126. ->countValidByCurrentDistribution();
  127. $orderMaximumPerCycle = $this->settingSolver->getSettingValue(
  128. $section,
  129. SectionSettingDefinition::SETTING_ORDER_MAXIMUM_PER_CYCLE
  130. );
  131. if ($orderMaximumPerCycle && $countOrderShopCycle >= $orderMaximumPerCycle) {
  132. return true;
  133. }
  134. return false;
  135. }
  136. public function isDateMatchWithOpening(\DateTime $date, OpeningInterface $opening): bool
  137. {
  138. $day = $date->format('N');
  139. $dayOpening = $opening->getDay();
  140. if ($opening->getTimeStart()) {
  141. $dateOpeningStart = clone $date;
  142. $dateOpeningStart->setTime(
  143. $opening->getTimeStart()->format('H'),
  144. $opening->getTimeStart()->format('i')
  145. );
  146. }
  147. if ($opening->getTimeEnd()) {
  148. $dateOpeningEnd = clone $date;
  149. $dateOpeningEnd->setTime(
  150. $opening->getTimeEnd()->format('H'),
  151. $opening->getTimeEnd()->format('i')
  152. );
  153. }
  154. if ($day == $dayOpening) {
  155. // Commandes ouvertes toute la journée
  156. if (!$opening->getTimeStart() && !$opening->getTimeEnd()) {
  157. return true;
  158. } // Commandes ouvertes à partir de timeStart
  159. elseif ($opening->getTimeStart() && !$opening->getTimeEnd() && $date >= $dateOpeningStart) {
  160. return true;
  161. } // Commandes ouvertes jusqu'à timeEnd
  162. elseif (!$opening->getTimeStart() && $opening->getTimeEnd() && $date < $dateOpeningEnd) {
  163. return true;
  164. } // Commandes ouvertes de timeStart à timeEnd
  165. elseif ($opening->getTimeStart() && $opening->getTimeEnd()
  166. && $date >= $dateOpeningStart && $date < $dateOpeningEnd) {
  167. return true;
  168. }
  169. }
  170. return false;
  171. }
  172. // getDateEndCurrentSale
  173. public function getFormatedDateClosingCurrentSale(
  174. SectionInterface $section = null,
  175. $formatDate = '',
  176. $delimiterDayTime = 'à'
  177. ) {
  178. if (is_null($section)) {
  179. $section = $this->sectionResolver->getCurrent();
  180. }
  181. $date = new \DateTime();
  182. $openingArray = $this->openingStore
  183. ->setSection($section)
  184. ->get();
  185. if ($this->isOpenSale($section)) {
  186. $openingClosing = $this->openingSolver->getNextOpeningOfClosing($date, $openingArray);
  187. if ($openingClosing) {
  188. return $this->openingSolver->getFormatedDateByFormatAndDelimiterDayTime(
  189. $date,
  190. $openingClosing->getTimeEnd(),
  191. $formatDate,
  192. $delimiterDayTime
  193. );
  194. }
  195. }
  196. return '';
  197. }
  198. // getDateBeginNextSale
  199. public function getFormatedDateOpeningNextSale(
  200. SectionInterface $section = null,
  201. $formatDate = '',
  202. $delimiterDayTime = 'à'
  203. ) {
  204. if (is_null($section)) {
  205. $section = $this->sectionResolver->getCurrent();
  206. }
  207. $date = new \DateTime();
  208. $openingArray = $this->openingStore
  209. ->setSection($section)
  210. ->get();
  211. if (!$this->isOpenSale($section)) {
  212. $opening = $this->openingSolver->getNextOpeningOfOpening($date, $openingArray);
  213. if ($opening) {
  214. return $this->openingSolver->getFormatedDateByFormatAndDelimiterDayTime(
  215. $date,
  216. $opening->getTimeStart() ?: (new \DateTime())->setTime(0, 0),
  217. $formatDate,
  218. $delimiterDayTime
  219. );
  220. }
  221. }
  222. return '';
  223. }
  224. public function isOpenSaleOnlyComplementaryOrders(SectionInterface $section = null, UserInterface $user = null)
  225. {
  226. if (is_null($section)) {
  227. $section = $this->sectionResolver->getCurrent();
  228. }
  229. if (is_null($user)) {
  230. $user = $this->security->getUser();
  231. }
  232. // @TODO : ajouter une option dans les sections (permettre les commandes complémentaires ou non)
  233. $orderShopsUser = $this->orderShopStore->setSection($section)->getByCurrentDistributionAndUser($user);
  234. return $this->isOpenSale($section, $user)
  235. && $this->isMaximumOrderDistributionAchieved($section)
  236. && count($orderShopsUser) > 0;
  237. }
  238. public function getMessageOpeningNextSale(SectionInterface $section): ?string
  239. {
  240. $openingTextClosed = $this->settingSolver->getSettingValue(
  241. $section,
  242. SectionSettingDefinition::SETTING_OPENING_TEXT_CLOSED
  243. );
  244. if ($openingTextClosed && strlen($openingTextClosed) > 0) {
  245. return $openingTextClosed ;
  246. }
  247. $dateOpeningNextSale = $this->getFormatedDateOpeningNextSale($section);
  248. if ($dateOpeningNextSale && strlen($dateOpeningNextSale) > 0) {
  249. return 'Réouverture aux commandes le <u>'.$dateOpeningNextSale.'</u>' ;
  250. }
  251. return null;
  252. }
  253. public function getMessages(): array
  254. {
  255. return $this->messages;
  256. }
  257. public function addMessage(string $message): void
  258. {
  259. $this->messages[] = $message;
  260. }
  261. }