您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

301 行
10.0KB

  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->isMaximumOrderDistributionAchieved($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. //isMaximumOrderCycleAchieved
  124. public function isMaximumOrderDistributionAchieved(SectionInterface $section)
  125. {
  126. $countOrderShopCycle = $this->orderShopStore
  127. ->setSection($section)
  128. ->countValidByCurrentDistribution();
  129. $orderMaximumPerCycle = $this->settingSolver->getSettingValue(
  130. $section,
  131. SectionSettingDefinition::SETTING_ORDER_MAXIMUM_PER_CYCLE
  132. );
  133. if ($orderMaximumPerCycle && $countOrderShopCycle >= $orderMaximumPerCycle) {
  134. return true;
  135. }
  136. return false;
  137. }
  138. public function isDateMatchWithOpening(\DateTime $date, OpeningInterface $opening): bool
  139. {
  140. $day = $date->format('N');
  141. $dayOpening = $opening->getDay();
  142. if ($opening->getTimeStart()) {
  143. $dateOpeningStart = clone $date;
  144. $dateOpeningStart->setTime(
  145. $opening->getTimeStart()->format('H'),
  146. $opening->getTimeStart()->format('i')
  147. );
  148. }
  149. if ($opening->getTimeEnd()) {
  150. $dateOpeningEnd = clone $date;
  151. $dateOpeningEnd->setTime(
  152. $opening->getTimeEnd()->format('H'),
  153. $opening->getTimeEnd()->format('i')
  154. );
  155. }
  156. if ($day == $dayOpening) {
  157. // Commandes ouvertes toute la journée
  158. if (!$opening->getTimeStart() && !$opening->getTimeEnd()) {
  159. return true;
  160. } // Commandes ouvertes à partir de timeStart
  161. elseif ($opening->getTimeStart() && !$opening->getTimeEnd() && $date >= $dateOpeningStart) {
  162. return true;
  163. } // Commandes ouvertes jusqu'à timeEnd
  164. elseif (!$opening->getTimeStart() && $opening->getTimeEnd() && $date < $dateOpeningEnd) {
  165. return true;
  166. } // Commandes ouvertes de timeStart à timeEnd
  167. elseif ($opening->getTimeStart() && $opening->getTimeEnd()
  168. && $date >= $dateOpeningStart && $date < $dateOpeningEnd) {
  169. return true;
  170. }
  171. }
  172. return false;
  173. }
  174. // getDateEndCurrentSale
  175. public function getFormatedDateClosingCurrentSale(
  176. SectionInterface $section = null,
  177. $formatDate = '',
  178. $delimiterDayTime = 'à'
  179. ) {
  180. if (is_null($section)) {
  181. $section = $this->sectionResolver->getCurrent();
  182. }
  183. $date = new \DateTime();
  184. $openingArray = $this->openingStore
  185. ->setSection($section)
  186. ->get();
  187. if ($this->isOpenSale($section)) {
  188. $openingClosing = $this->openingSolver->getNextOpeningOfClosing($date, $openingArray);
  189. if ($openingClosing) {
  190. return $this->openingSolver->getFormatedDateByFormatAndDelimiterDayTime(
  191. $date,
  192. $openingClosing->getTimeEnd(),
  193. $formatDate,
  194. $delimiterDayTime
  195. );
  196. }
  197. }
  198. return '';
  199. }
  200. // getDateBeginNextSale
  201. public function getFormatedDateOpeningNextSale(
  202. SectionInterface $section = null,
  203. $formatDate = '',
  204. $delimiterDayTime = 'à'
  205. ) {
  206. if (is_null($section)) {
  207. $section = $this->sectionResolver->getCurrent();
  208. }
  209. $date = new \DateTime();
  210. $openingArray = $this->openingStore
  211. ->setSection($section)
  212. ->get();
  213. if (!$this->isOpenSale($section)) {
  214. $opening = $this->openingSolver->getNextOpeningOfOpening($date, $openingArray);
  215. if ($opening) {
  216. return $this->openingSolver->getFormatedDateByFormatAndDelimiterDayTime(
  217. $date,
  218. $opening->getTimeStart() ?: (new \DateTime())->setTime(0, 0),
  219. $formatDate,
  220. $delimiterDayTime
  221. );
  222. }
  223. }
  224. return '';
  225. }
  226. public function isOpenSaleOnlyComplementaryOrders(Section $section = null, UserInterface $user = null)
  227. {
  228. if (is_null($section)) {
  229. $section = $this->sectionResolver->getCurrent();
  230. }
  231. if (is_null($user)) {
  232. $user = $this->security->getUser();
  233. }
  234. // @TODO : ajouter une option dans les sections (permettre les commandes complémentaires ou non)
  235. $orderShopsUser = $this->orderShopStore->setSection($section)->getByCurrentDistributionAndUser($user);
  236. return $this->isOpenSale($section, $user)
  237. && $this->isMaximumOrderDistributionAchieved($section)
  238. && count($orderShopsUser) > 0;
  239. }
  240. public function getMessages(): array
  241. {
  242. return $this->messages;
  243. }
  244. public function addMessage(string $message): void
  245. {
  246. $this->messages[] = $message;
  247. }
  248. }