diff --git a/app/DoctrineMigrations/Version20230729100654.php b/app/DoctrineMigrations/Version20230729100654.php new file mode 100644 index 000000000..2757a1aac --- /dev/null +++ b/app/DoctrineMigrations/Version20230729100654.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE membership ADD flying TINYINT(1) DEFAULT \'0\' NOT NULL'); + $this->addSql('UPDATE membership LEFT OUTER JOIN beneficiary ON beneficiary.id = membership.main_beneficiary_id SET membership.flying=beneficiary.flying WHERE beneficiary.flying = 1'); + $this->addSql('ALTER TABLE beneficiary DROP flying'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE beneficiary ADD flying TINYINT(1) DEFAULT \'0\' NOT NULL'); + $this->addSql('ALTER TABLE membership DROP flying'); + } +} diff --git a/app/Resources/views/beneficiary/_partial/info.html.twig b/app/Resources/views/beneficiary/_partial/info.html.twig index bdf7c0637..78764e5da 100644 --- a/app/Resources/views/beneficiary/_partial/info.html.twig +++ b/app/Resources/views/beneficiary/_partial/info.html.twig @@ -61,16 +61,6 @@ {% endif %}) {% endif %} - {% if use_fly_and_fixed %} -
- accessibility - {% if beneficiary.flying %} -
Equipe volante
- {% else %} -
Equipe fixe
- {% endif %} -
- {% endif %} {% if beneficiary.formations | length %}
assignment_ind diff --git a/app/Resources/views/member/show.html.twig b/app/Resources/views/member/show.html.twig index 5a3330baa..cf334f14e 100644 --- a/app/Resources/views/member/show.html.twig +++ b/app/Resources/views/member/show.html.twig @@ -219,72 +219,6 @@ {% endif %} - - {% if is_granted("ROLE_USER_MANAGER") and is_granted("close",member) %} -
  • - -
    - {% if not member.withdrawn %} - - closeFermer le compte - - {{ form_start(close_form) }} - - {{ form_end(close_form) }} - {% else %} - {% if member.withdrawnDate %} -

    - Compte fermé le {{ member.withdrawnDate | date_fr }} - {% if member.withdrawnBy %} - par {% include "admin/member/_partial/member_or_user_link.html.twig" with { user: member.withdrawnBy, target_blank: true } %}. - {% endif %} -

    - {% endif %} - - checkRé-ouvrir le compte - - {{ form_start(open_form) }} - - {{ form_end(open_form) }} - {% endif %} -
    -
  • - {% endif %} - {% if is_granted("ROLE_ADMIN") %}
  • @@ -346,6 +280,53 @@
  • {% endif %} + + + + {% endblock %} {% block javascripts %} diff --git a/app/Resources/views/period/_partial/position_shifter_display.html.twig b/app/Resources/views/period/_partial/position_shifter_display.html.twig index 30421abff..da99ccceb 100644 --- a/app/Resources/views/period/_partial/position_shifter_display.html.twig +++ b/app/Resources/views/period/_partial/position_shifter_display.html.twig @@ -17,7 +17,7 @@ Réservé
    {% else %} - {% set warning = beneficiary_service.hasWarningStatus(shifter) %} + {% set warning = membership_service.hasWarningStatus(shifter.membership) %} diff --git a/src/AppBundle/Command/ImportUsersCommand.php b/src/AppBundle/Command/ImportUsersCommand.php index 4223365fc..eb01c81f6 100644 --- a/src/AppBundle/Command/ImportUsersCommand.php +++ b/src/AppBundle/Command/ImportUsersCommand.php @@ -168,7 +168,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $dispatcher->dispatch(BeneficiaryCreatedEvent::NAME, new BeneficiaryCreatedEvent($beneficiary)); $beneficiary->setEmail($email); - $beneficiary->setFlying(false); $em->persist($beneficiary); } diff --git a/src/AppBundle/Controller/MailController.php b/src/AppBundle/Controller/MailController.php index b2bf86481..9957f0205 100644 --- a/src/AppBundle/Controller/MailController.php +++ b/src/AppBundle/Controller/MailController.php @@ -119,7 +119,6 @@ public function sendAction(Request $request, \Swift_Mailer $mailer) $user = $em->getRepository(User::class)->findOneBy(array('email' => $nonMember)); if (is_object($user)) { $fake_beneficiary = new Beneficiary(); - $fake_beneficiary->setFlying(false); $fake_beneficiary->setUser($user); $fake_beneficiary->setFirstname($user->getUsername()); $fake_beneficiary->setLastname(' '); diff --git a/src/AppBundle/Controller/MembershipController.php b/src/AppBundle/Controller/MembershipController.php index 62355ac22..38da0e08e 100644 --- a/src/AppBundle/Controller/MembershipController.php +++ b/src/AppBundle/Controller/MembershipController.php @@ -90,8 +90,8 @@ public function showAction(Membership $member) $freezeForm = $this->createFreezeForm($member); $unfreezeForm = $this->createUnfreezeForm($member); $freezeChangeForm = $this->createFreezeChangeForm($member); - $closeForm = $this->createCloseForm($member); - $openForm = $this->createOpenForm($member); + $flyingForm = $this->createFlyingForm($member); + $withdrawnForm = $this->createWithdrawnForm($member); $deleteForm = $this->createDeleteForm($member); $note = new Note(); @@ -197,8 +197,8 @@ public function showAction(Membership $member) 'freeze_form' => $freezeForm->createView(), 'unfreeze_form' => $unfreezeForm->createView(), 'freeze_change_form' => $freezeChangeForm->createView(), - 'close_form' => $closeForm->createView(), - 'open_form' => $openForm->createView(), + 'flying_form' => $flyingForm->createView(), + 'withdrawn_form' => $withdrawnForm->createView(), 'delete_form' => $deleteForm->createView(), 'time_log_new_form' => $timeLogNewForm->createView(), 'time_log_delete_forms' => $timeLogDeleteForms, @@ -501,61 +501,94 @@ public function activeUserAccountAction(Request $request) /** - * Close member + * Close/Reopen member * - * @Route("/{id}/close", name="member_close", methods={"POST"}) + * @Route("/{id}/withdrawn", name="member_withdrawn", methods={"POST"}) * @param Request $request * @param Membership $member * @return \Symfony\Component\HttpFoundation\RedirectResponse */ - public function closeAction(Request $request, Membership $member) + public function withdrawnAction(Request $request, Membership $member) { - $this->denyAccessUnlessGranted('close', $member); $current_user = $this->get('security.token_storage')->getToken()->getUser(); $session = new Session(); - $form = $this->createCloseForm($member); + $form = $this->createWithdrawnForm($member); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { + $withdrawn = $form->get("withdrawn")->getData(); + if ($withdrawn) { + $this->denyAccessUnlessGranted('close', $member); + if ($member->isWithdrawn()) { + $session->getFlashBag()->add('error', 'Ce compte est déjà fermé'); + return $this->redirectToShow($member); + } + $member->setWithdrawnDate(new \DateTime('now')); + $member->setWithdrawnBy($current_user); + } else { + $this->denyAccessUnlessGranted('open', $member); + if (!$member->isWithdrawn()) { + $session->getFlashBag()->add('error', 'Ce compte est déjà ouvert'); + return $this->redirectToShow($member); + } + } + $member->setWithdrawn($withdrawn); $em = $this->getDoctrine()->getManager(); - $member->setWithdrawn(true); - $member->setWithdrawnDate(new \DateTime('now')); - $member->setWithdrawnBy($current_user); $em->persist($member); $em->flush(); - $session->getFlashBag()->add('success', 'Compte fermé !'); + if ($withdrawn) { + $session->getFlashBag()->add('success', 'Compte fermé !'); + } else { + $session->getFlashBag()->add('success', 'Compte ré-ouvert !'); + } } return $this->redirectToShow($member); } /** - * Open member + * Change flying status member * - * @Route("/{id}/open", name="member_open", methods={"POST"}) + * @Route("/{id}/flying", name="member_flying", methods={"POST"}) * @param Request $request * @param Membership $member * @return \Symfony\Component\HttpFoundation\RedirectResponse */ - public function openAction(Request $request, Membership $member) + public function flyingAction(Request $request, Membership $member) { - $this->denyAccessUnlessGranted('open', $member); + $this->denyAccessUnlessGranted('flying', $member); + $current_user = $this->get('security.token_storage')->getToken()->getUser(); + $session = new Session(); - $form = $this->createOpenForm($member); + $form = $this->createFlyingForm($member); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $session = new Session(); + $flying = $form->get("flying")->getData(); + if ($flying) { + if ($member->isFlying()) { + $session->getFlashBag()->add('error', 'Ce compte est déjà volant'); + return $this->redirectToShow($member); + } + } else { + if (!$member->isFlying()) { + $session->getFlashBag()->add('error', 'Ce compte est déjà fixe'); + return $this->redirectToShow($member); + } + } + $member->setFlying($flying); $em = $this->getDoctrine()->getManager(); - - $member->setWithdrawn(false); $em->persist($member); $em->flush(); - $session->getFlashBag()->add('success', 'Compte ré-ouvert !'); + if ($flying) { + $session->getFlashBag()->add('success', 'Le compte est volant !'); + } else { + $session->getFlashBag()->add('success', 'Le compte est fixe !'); + } } return $this->redirectToShow($member); @@ -732,7 +765,6 @@ public function newAction(Request $request) $user->setEmail($a_beneficiary->getEmail()); $beneficiary = new Beneficiary(); $beneficiary->setUser($user); - $beneficiary->setFlying(false); $member->setMainBeneficiary($beneficiary); } @@ -880,7 +912,6 @@ public function addBeneficiaryAction(Request $request) $beneficiary = new Beneficiary(); $beneficiary->setUser(new User()); - $beneficiary->setFlying(false); $beneficiary->setEmail($a_beneficiary->getEmail()); $form->get('beneficiary')->setData($beneficiary); @@ -1118,29 +1149,31 @@ private function createFreezeChangeForm(Membership $member) } /** - * Creates a form to close a member entity. + * Creates a form to close or open a member entity. * * @param Membership $member * @return \Symfony\Component\Form\FormInterface */ - private function createCloseForm(Membership $member) + private function createWithdrawnForm(Membership $member) { return $this->createFormBuilder() - ->setAction($this->generateUrl('member_close', array('id' => $member->getId()))) + ->setAction($this->generateUrl('member_withdrawn', array('id' => $member->getId()))) + ->add('withdrawn', HiddenType::class, ['data' => $member->isWithdrawn() ? 0 : 1]) ->setMethod('POST') ->getForm(); } /** - * Creates a form to open a member entity. + * Creates a form to set flying for a member entity. * * @param Membership $member * @return \Symfony\Component\Form\FormInterface */ - private function createOpenForm(Membership $member) + private function createFlyingForm(Membership $member) { return $this->createFormBuilder() - ->setAction($this->generateUrl('member_open', array('id' => $member->getId()))) + ->setAction($this->generateUrl('member_flying', array('id' => $member->getId()))) + ->add('flying', HiddenType::class, ['data' => $member->isFlying() ? 0 : 1]) ->setMethod('POST') ->getForm(); } diff --git a/src/AppBundle/Controller/NoteController.php b/src/AppBundle/Controller/NoteController.php index f32f1849b..deef52dfe 100644 --- a/src/AppBundle/Controller/NoteController.php +++ b/src/AppBundle/Controller/NoteController.php @@ -11,7 +11,6 @@ use AppBundle\Entity\Shift; use AppBundle\Entity\TimeLog; use AppBundle\Entity\User; -use AppBundle\Form\BeneficiaryType; use AppBundle\Form\NoteType; use Symfony\Component\Form\Form; use Symfony\Component\HttpFoundation\Session\Session; diff --git a/src/AppBundle/Controller/RegistrationsController.php b/src/AppBundle/Controller/RegistrationsController.php index a45379e4d..9ed08f800 100644 --- a/src/AppBundle/Controller/RegistrationsController.php +++ b/src/AppBundle/Controller/RegistrationsController.php @@ -12,7 +12,6 @@ use AppBundle\Entity\Formation; use AppBundle\Entity\User; use AppBundle\Event\HelloassoEvent; -use AppBundle\Form\BeneficiaryType; use AppBundle\Form\RegistrationType; use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\ORM\QueryBuilder; diff --git a/src/AppBundle/Controller/UserController.php b/src/AppBundle/Controller/UserController.php index e2c9f263b..2d1c7366c 100644 --- a/src/AppBundle/Controller/UserController.php +++ b/src/AppBundle/Controller/UserController.php @@ -14,7 +14,6 @@ use AppBundle\Event\AnonymousBeneficiaryCreatedEvent; use AppBundle\Event\AnonymousBeneficiaryRecallEvent; use AppBundle\Form\AnonymousBeneficiaryType; -use AppBundle\Form\BeneficiaryType; use AppBundle\Form\NoteType; use AppBundle\Form\UserAdminType; use FOS\UserBundle\Event\UserEvent; diff --git a/src/AppBundle/Entity/Beneficiary.php b/src/AppBundle/Entity/Beneficiary.php index cda866685..9f6ee8e11 100644 --- a/src/AppBundle/Entity/Beneficiary.php +++ b/src/AppBundle/Entity/Beneficiary.php @@ -59,13 +59,6 @@ class Beneficiary */ private $address; - /** - * @var bool - * - * @ORM\Column(name="flying", type="boolean", options={"default" : 0}, nullable=false) - */ - private $flying; - /** * @ORM\OneToOne(targetEntity="User", inversedBy="beneficiary", cascade={"persist", "remove"}) * @ORM\JoinColumn(name="user_id", referencedColumnName="id",nullable=false) @@ -658,20 +651,6 @@ public function setAddress($address) $this->address = $address; } - /** - * @return bool - */ - public function isFlying(): ?bool { - return $this->flying; - } - - /** - * @param bool $flying - */ - public function setFlying(?bool $flying): void { - $this->flying = $flying; - } - /** * Get createdAt * diff --git a/src/AppBundle/Entity/Membership.php b/src/AppBundle/Entity/Membership.php index 78ad07876..76fbb8fed 100644 --- a/src/AppBundle/Entity/Membership.php +++ b/src/AppBundle/Entity/Membership.php @@ -70,6 +70,13 @@ class Membership */ private $frozen_change; + /** + * @var bool + * + * @ORM\Column(name="flying", type="boolean", options={"default" : 0}, nullable=false) + */ + private $flying; + /** * @ORM\OneToMany(targetEntity="Registration", mappedBy="membership",cascade={"persist", "remove"}) * @OrderBy({"date" = "DESC"}) @@ -489,6 +496,20 @@ public function getFrozenChange() return $this->frozen_change; } + /** + * @return bool + */ + public function isFlying(): ?bool { + return $this->flying; + } + + /** + * @param bool $flying + */ + public function setFlying(?bool $flying): void { + $this->flying = $flying; + } + /** * Get lastRegistration * diff --git a/src/AppBundle/Entity/Period.php b/src/AppBundle/Entity/Period.php index caef236f1..89db5ad1c 100644 --- a/src/AppBundle/Entity/Period.php +++ b/src/AppBundle/Entity/Period.php @@ -414,7 +414,7 @@ public function getPositionsPerWeekCycle(): array return $positionsPerWeekCycle; } - /** + /** * Get periodPositions grouped per week cycle * * @param String|null $weekCycle a string of the week to keep or null if no filter @@ -475,7 +475,7 @@ public function isProblematic(?String $weekCycle=null): bool foreach ($this->positions as $position) { if($shifter = $position->getShifter()){ if((($weekCycle && $position->getWeekCycle()==$weekCycle) or !$weekCycle) - and ($shifter->isFlying() + and ($shifter->getMembership()->isFlying() or $shifter->getMembership()->isFrozen() or $shifter->getMembership()->isWithdrawn())){ return true; diff --git a/src/AppBundle/Form/BeneficiaryType.php b/src/AppBundle/Form/BeneficiaryType.php index 40b7897f8..e060ef632 100644 --- a/src/AppBundle/Form/BeneficiaryType.php +++ b/src/AppBundle/Form/BeneficiaryType.php @@ -66,14 +66,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($user) { $form = $event->getForm(); if (is_object($user)&&($user->hasRole('ROLE_USER_MANAGER') || $user->hasRole('ROLE_ADMIN') || $user->hasRole('ROLE_SUPER_ADMIN'))) { - $form->add('flying', ChoiceType::class, array( - 'choices' => array( - 'Oui' => true, - 'Non' => false, - ), - 'required' => true, - 'label' => 'Equipe volante' - )); $form->add('commissions', EntityType::class, array( 'class' => 'AppBundle:Commission', 'choice_label' => 'name', diff --git a/src/AppBundle/Security/MembershipVoter.php b/src/AppBundle/Security/MembershipVoter.php index 190e5fe56..6f0d7b54e 100644 --- a/src/AppBundle/Security/MembershipVoter.php +++ b/src/AppBundle/Security/MembershipVoter.php @@ -20,6 +20,7 @@ class MembershipVoter extends Voter const CLOSE = 'close'; const FREEZE = 'freeze'; const FREEZE_CHANGE = 'freeze_change'; + const FLYING = "flying"; const ROLE_REMOVE = 'role_remove'; const ROLE_ADD = 'role_add'; const ANNOTATE = 'annotate'; @@ -46,6 +47,7 @@ protected function supports($attribute, $subject) self::ROLE_ADD, self::FREEZE, self::FREEZE_CHANGE, + self::FLYING, self::CREATE, self::ANNOTATE, self::ACCESS_TOOLS, @@ -103,6 +105,7 @@ protected function voteOnAttribute($attribute, $subject, TokenInterface $token) case self::ROLE_ADD: case self::ROLE_REMOVE: case self::EDIT: + case self::FLYING: return $this->canEdit($subject, $token); } @@ -153,4 +156,4 @@ private function isLocationOk() $ips = explode(',', $ips); return (isset($checkIps) and !$checkIps) or (isset($ip) and in_array($ip, $ips)); } -} \ No newline at end of file +} diff --git a/src/AppBundle/Service/BeneficiaryService.php b/src/AppBundle/Service/BeneficiaryService.php index 6b6fe6eea..62776ffd8 100644 --- a/src/AppBundle/Service/BeneficiaryService.php +++ b/src/AppBundle/Service/BeneficiaryService.php @@ -64,20 +64,6 @@ public function getDisplayNameWithMemberNumberAndStatusIcon(Beneficiary $benefic return $label; } - /** - * Return true if the beneficiary is in a "warning" status - */ - public function hasWarningStatus(Beneficiary $beneficiary): bool - { - $hasWarningStatus = $this->membershipService->hasWarningStatus($beneficiary->getMembership()); - - if ($this->container->getParameter('use_fly_and_fixed')) { - $hasWarningStatus = $hasWarningStatus || $beneficiary->isFlying(); - } - - return $hasWarningStatus; - } - /** * Return a string with emoji between brackets depending on the * beneficiary status, if she/he is inactive (withdrawn), frozen or flying @@ -96,7 +82,7 @@ public function getStatusIcon(Beneficiary $beneficiary): string if ($beneficiary->getMembership()->getFrozen()) { $symbols[] = $this->container->getParameter('member_frozen_icon'); } - if ($beneficiary->isFlying()) { + if ($beneficiary->getMembership()->isFlying()) { $symbols[] = $this->container->getParameter('beneficiary_flying_icon');; } if ($beneficiary->getMembership()->isCurrentlyExemptedFromShifts()) { diff --git a/src/AppBundle/Service/MembershipService.php b/src/AppBundle/Service/MembershipService.php index 94055605d..ab764a501 100644 --- a/src/AppBundle/Service/MembershipService.php +++ b/src/AppBundle/Service/MembershipService.php @@ -194,10 +194,16 @@ public function getCycleShiftFreedCount(Membership $member, $date, $less_than_mi */ public function hasWarningStatus(Membership $member): bool { - return $member->getWithdrawn() || + $hasWarningStatus = $member->getWithdrawn() || $member->getFrozen() || $member->isCurrentlyExemptedFromShifts() || !$this->isUptodate($member); + + if ($this->container->getParameter('use_fly_and_fixed')) { + $hasWarningStatus = $hasWarningStatus || $member->isFlying(); + } + + return $hasWarningStatus; } public function getShiftFreeLogs(Membership $member) diff --git a/src/AppBundle/Service/SearchUserFormHelper.php b/src/AppBundle/Service/SearchUserFormHelper.php index ed639c0a1..065a382ba 100644 --- a/src/AppBundle/Service/SearchUserFormHelper.php +++ b/src/AppBundle/Service/SearchUserFormHelper.php @@ -635,7 +635,7 @@ public function processSearchFormData($form, &$qb) { if ($this->use_fly_and_fixed) { if ($form->get('flying')->getData() > 0) { - $qb = $qb->andWhere('b.flying = :flying') + $qb = $qb->andWhere('m.flying = :flying') ->setParameter('flying', $form->get('flying')->getData()-1); } if ($form->has('has_period_position')) { @@ -711,7 +711,6 @@ public function processSearchFormData($form, &$qb) { ->setParameter('subQueryformations', $subQuery); } } - return $qb; } }