Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

299 lines
9.9KB

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