From 813ecb0201adaf8ddb0cb2b622eafa5e1983e767 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 26 Mar 2021 21:44:59 +0100 Subject: [PATCH 01/22] cleaning --- .../AccompanyingPeriodController.php | 167 ++++++++++-------- 1 file changed, 93 insertions(+), 74 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index 2f6925373..0db5e170f 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -63,15 +63,16 @@ class AccompanyingPeriodController extends AbstractController $person = $this->_getPerson($person_id); - $event = new PrivacyEvent($person, array( + $event = new PrivacyEvent($person, [ 'element_class' => AccompanyingPeriod::class, 'action' => 'list' - )); + ]); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig', - array('accompanying_periods' => $person->getAccompanyingPeriodsOrdered(), - 'person' => $person)); + return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig', [ + 'accompanying_periods' => $person->getAccompanyingPeriodsOrdered(), + 'person' => $person + ]); } /** @@ -95,8 +96,7 @@ class AccompanyingPeriodController extends AbstractController $form = $this->createForm( AccompanyingPeriodType::class, - $accompanyingPeriod, - [ + $accompanyingPeriod, [ 'period_action' => 'create', 'center' => $person->getCenter() ]); @@ -106,7 +106,7 @@ class AccompanyingPeriodController extends AbstractController $errors = $this->_validatePerson($person); $flashBag = $this->get('session')->getFlashBag(); - if ($form->isValid(array('Default', 'closed')) + if ($form->isValid(['Default', 'closed']) && count($errors) === 0) { $em = $this->getDoctrine()->getManager(); @@ -116,8 +116,11 @@ class AccompanyingPeriodController extends AbstractController $this->get('translator')->trans( 'A period has been created.')); - return $this->redirect($this->generateUrl('chill_person_accompanying_period_list', - array('person_id' => $person->getId()))); + return $this->redirect( + $this->generateUrl('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ])); + } else { $flashBag->add('error', $this->get('translator') ->trans('Error! Period not created!')); @@ -128,13 +131,11 @@ class AccompanyingPeriodController extends AbstractController } } - return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', - array( - 'form' => $form->createView(), - 'person' => $person, - 'accompanying_period' => $accompanyingPeriod - ) - ); + return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [ + 'form' => $form->createView(), + 'person' => $person, + 'accompanying_period' => $accompanyingPeriod + ]); } /** @@ -160,25 +161,31 @@ class AccompanyingPeriodController extends AbstractController 'You are not allowed to update this person'); $form = $this->createForm(AccompanyingPeriodType::class, - $accompanyingPeriod, array('period_action' => 'update', - 'center' => $person->getCenter())); + $accompanyingPeriod, [ + 'period_action' => 'update', + 'center' => $person->getCenter() + ]); if ($request->getMethod() === 'POST') { $form->handleRequest($request); $errors = $this->_validatePerson($person); $flashBag = $this->get('session')->getFlashBag(); - if ($form->isValid(array('Default', 'closed')) + if ($form->isValid(['Default', 'closed']) && count($errors) === 0) { + $em->flush(); $flashBag->add('success', - $this->get('translator')->trans( - 'An accompanying period has been updated.')); + $this->get('translator')->trans('An accompanying period has been updated.')); - return $this->redirect($this->generateUrl('chill_person_accompanying_period_list', - array('person_id' => $person->getId()))); + return $this->redirect( + $this->generateUrl('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ])); + } else { + $flashBag->add('error', $this->get('translator') ->trans('Error when updating the period')); @@ -188,12 +195,11 @@ class AccompanyingPeriodController extends AbstractController } } - return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', - array( - 'form' => $form->createView(), - 'person' => $person, - 'accompanying_period' => $accompanyingPeriod - ) ); + return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [ + 'form' => $form->createView(), + 'person' => $person, + 'accompanying_period' => $accompanyingPeriod + ]); } /** @@ -207,27 +213,27 @@ class AccompanyingPeriodController extends AbstractController $person = $this->_getPerson($person_id); - $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, - 'You are not allowed to update this person'); + $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, 'You are not allowed to update this person'); if ($person->isOpen() === false) { + $this->get('session')->getFlashBag() ->add('error', $this->get('translator') - ->trans('Beware period is closed', - array('%name%' => $person->__toString()))); + ->trans('Beware period is closed', ['%name%' => $person->__toString()] + )); return $this->redirect( - $this->generateUrl('chill_person_accompanying_period_list', array( - 'person_id' => $person->getId() - ))); + $this->generateUrl('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ])); } $current = $person->getCurrentAccompanyingPeriod(); - $form = $this->createForm(AccompanyingPeriodType::class, $current, array( + $form = $this->createForm(AccompanyingPeriodType::class, $current, [ 'period_action' => 'close', 'center' => $person->getCenter() - )); + ]); if ($request->getMethod() === 'POST') { $form->handleRequest($request); @@ -239,16 +245,18 @@ class AccompanyingPeriodController extends AbstractController if (count($errors) === 0) { $this->get('session')->getFlashBag() ->add('success', $this->get('translator') - ->trans('An accompanying period has been closed.', - array('%name%' => $person->__toString()))); + ->trans('An accompanying period has been closed.', [ + '%name%' => $person->__toString() + ])); $this->getDoctrine()->getManager()->flush(); return $this->redirect( - $this->generateUrl('chill_person_accompanying_period_list', array( - 'person_id' => $person->getId() - )) - ); + $this->generateUrl('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ]) + ); + } else { $this->get('session')->getFlashBag() ->add('error', $this->get('translator') @@ -259,6 +267,7 @@ class AccompanyingPeriodController extends AbstractController ->add('info', $error->getMessage()); } } + } else { //if form is not valid $this->get('session')->getFlashBag() ->add('error', @@ -273,12 +282,11 @@ class AccompanyingPeriodController extends AbstractController } } - return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', - array( - 'form' => $form->createView(), - 'person' => $person, - 'accompanying_period' => $current - )); + return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [ + 'form' => $form->createView(), + 'person' => $person, + 'accompanying_period' => $current + ]); } /** @@ -287,9 +295,9 @@ class AccompanyingPeriodController extends AbstractController */ private function _validatePerson(Person $person) { $errors = $this->get('validator')->validate($person, null, - array('Default')); + ['Default']); $errors_accompanying_period = $this->get('validator')->validate($person, null, - array('accompanying_period_consistent')); + ['accompanying_period_consistent']); foreach($errors_accompanying_period as $error ) { $errors->add($error); @@ -314,19 +322,22 @@ class AccompanyingPeriodController extends AbstractController $this->get('session')->getFlashBag() ->add('error', $this->get('translator') ->trans('Error! Period %name% is not closed ; it can be open', - array('%name%' => $person->__toString()))); + ['%name%' => $person->__toString()] + )); return $this->redirect( - $this->generateUrl('chill_person_accompanying_period_list', array( - 'person_id' => $person->getId() - ))); + $this->generateUrl('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ])); } $accompanyingPeriod = new AccompanyingPeriod(new \DateTime()); $form = $this->createForm(AccompanyingPeriodType::class, - $accompanyingPeriod, array('period_action' => 'open', - 'center' => $person->getCenter())); + $accompanyingPeriod, [ + 'period_action' => 'open', + 'center' => $person->getCenter() + ]); if ($request->getMethod() === 'POST') { $form->handleRequest($request); @@ -338,16 +349,18 @@ class AccompanyingPeriodController extends AbstractController if (count($errors) <= 0) { $this->get('session')->getFlashBag() - ->add('success', $this->get('translator') - ->trans('An accompanying period has been opened.', - array('%name%' => $person->__toString()))); + ->add('success', $this->get('translator') + ->trans('An accompanying period has been opened.', + ['%name%' => $person->__toString()] + )); $this->getDoctrine()->getManager()->flush(); return $this->redirect( - $this->generateUrl('chill_person_accompanying_period_list', array( + $this->generateUrl('chill_person_accompanying_period_list', [ 'person_id' => $person->getId() - ))); + ])); + } else { $this->get('session')->getFlashBag() ->add('error', $this->get('translator') @@ -358,17 +371,20 @@ class AccompanyingPeriodController extends AbstractController ->add('info', $error->getMessage()); } } + } else { // if errors in forms $this->get('session')->getFlashBag() - ->add('error', $this->get('translator') - ->trans('Period not opened : form is invalid')); + ->add('error', $this->get('translator') + ->trans('Period not opened : form is invalid') + ); } } - return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', - array('form' => $form->createView(), - 'person' => $person, - 'accompanying_period' => $accompanyingPeriod)); + return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [ + 'form' => $form->createView(), + 'person' => $person, + 'accompanying_period' => $accompanyingPeriod + ]); } /** @@ -405,13 +421,16 @@ class AccompanyingPeriodController extends AbstractController $this->addFlash('success', $this->get('translator')->trans( 'The period has been re-opened')); - return $this->redirectToRoute('chill_person_accompanying_period_list', - array('person_id' => $person->getId())); + return $this->redirectToRoute('chill_person_accompanying_period_list', [ + 'person_id' => $person->getId() + ]); + } elseif ($confirm === false && $period->canBeReOpened()) { - return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', array( + return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', [ 'period' => $period, 'person' => $person - )); + ]); + } else { return (new Response()) ->setStatusCode(Response::HTTP_BAD_REQUEST) From f6801c0c4f75aeb2bc1813cf92ea4f45a2cf72b9 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 26 Mar 2021 21:54:58 +0100 Subject: [PATCH 02/22] make new relation many-to-many between Person and AccompagnyingPeriod --- .../AccompanyingPeriodController.php | 53 +++++----- .../Entity/AccompanyingPeriod.php | 97 ++++++++++++------- .../ChillPersonBundle/Entity/Person.php | 62 ++++++------ .../views/AccompanyingPeriod/list.html.twig | 2 +- .../migrations/Version20210326113045.php | 76 +++++++++++++++ .../translations/validators.fr.yml | 2 +- 6 files changed, 196 insertions(+), 96 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index 0db5e170f..21ea358e7 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -3,7 +3,7 @@ /* * Chill is a software for social workers * - * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, + * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS, * , * * This program is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ namespace Chill\PersonBundle\Controller; use Chill\PersonBundle\Privacy\PrivacyEvent; +use Doctrine\DBAL\Exception; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\AccompanyingPeriodType; @@ -56,10 +57,10 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id * @return Response */ - public function listAction($person_id){ + public function listAction(int $person_id) + { $person = $this->_getPerson($person_id); @@ -76,11 +77,9 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id - * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response */ - public function createAction($person_id, Request $request) + public function createAction(int $person_id, Request $request) { $person = $this->_getPerson($person_id); @@ -139,23 +138,24 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id - * @param $period_id - * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response|\Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ - public function updateAction($person_id, $period_id, Request $request){ + public function updateAction(int $person_id, int $period_id, Request $request){ $em = $this->getDoctrine()->getManager(); - $accompanyingPeriod = $em->getRepository('ChillPersonBundle:AccompanyingPeriod') - ->find($period_id); + /** @var AccompanyingPeriod $accompanyingPeriod */ + $accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($period_id); if ($accompanyingPeriod === null) { - return $this->createNotFoundException("Period with id ".$period_id. - " is not found"); + throw $this->createNotFoundException("Period with id " . $period_id . " is not found"); } - $person = $accompanyingPeriod->getPerson(); + /** @var Person $person */ + $person = $em->getRepository(Person::class)->find($person_id); + + if (! $accompanyingPeriod->containsPerson($person)) { + throw new Exception("Accompanying period " . $period_id . " does not contain person " . $person_id); + } $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, 'You are not allowed to update this person'); @@ -203,12 +203,10 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id - * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response * @throws \Exception */ - public function closeAction($person_id, Request $request) + public function closeAction(int $person_id, Request $request) { $person = $this->_getPerson($person_id); @@ -290,7 +288,6 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param Person $person * @return \Symfony\Component\Validator\ConstraintViolationListInterface */ private function _validatePerson(Person $person) { @@ -307,8 +304,6 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id - * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response */ public function openAction($person_id, Request $request) { @@ -388,13 +383,11 @@ class AccompanyingPeriodController extends AbstractController } /** - * @param $person_id - * @param $period_id - * @param Request $request * @return object|\Symfony\Component\HttpFoundation\RedirectResponse|Response */ - public function reOpenAction($person_id, $period_id, Request $request) + public function reOpenAction(int $person_id, int $period_id, Request $request) { + /** @var Person $person */ $person = $this->_getPerson($person_id); $criteria = Criteria::create(); @@ -411,7 +404,7 @@ class AccompanyingPeriodController extends AbstractController $confirm = $request->query->getBoolean('confirm', false); - if ($confirm === true && $period->canBeReOpened()) { + if ($confirm === true && $period->canBeReOpened($person)) { $period->reOpen(); $this->_validatePerson($person); @@ -425,7 +418,7 @@ class AccompanyingPeriodController extends AbstractController 'person_id' => $person->getId() ]); - } elseif ($confirm === false && $period->canBeReOpened()) { + } elseif ($confirm === false && $period->canBeReOpened($person)) { return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', [ 'period' => $period, 'person' => $person @@ -439,12 +432,10 @@ class AccompanyingPeriodController extends AbstractController } /** - * - * @param int $id - * @return Person * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the person is not found */ - private function _getPerson($id) { + private function _getPerson(int $id) : Person + { $person = $this->getDoctrine()->getManager() ->getRepository('ChillPersonBundle:Person')->find($id); diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 255cf056f..63a8b67d3 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -3,7 +3,7 @@ /* * Chill is a software for social workers * - * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, + * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS, * , * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,8 @@ namespace Chill\PersonBundle\Entity; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Chill\MainBundle\Entity\User; @@ -65,14 +67,13 @@ class AccompanyingPeriod private $remark = ''; /** - * @var Person + * @var Collection * - * @ORM\ManyToOne( + * @ORM\ManyToMany( * targetEntity="Chill\PersonBundle\Entity\Person", - * inversedBy="accompanyingPeriods", - * cascade={"refresh"}) + * mappedBy="accompanyingPeriods") */ - private $person; + private $persons; /** * @var AccompanyingPeriod\ClosingMotive @@ -101,12 +102,13 @@ class AccompanyingPeriod */ public function __construct(\DateTime $dateOpening) { $this->setOpeningDate($dateOpening); + $this->persons = new ArrayCollection(); } /** * Get id * - * @return integer + * @return integer */ public function getId() { @@ -129,7 +131,7 @@ class AccompanyingPeriod /** * Get openingDate * - * @return \DateTime + * @return \DateTime */ public function getOpeningDate() { @@ -138,12 +140,12 @@ class AccompanyingPeriod /** * Set closingDate - * + * * For closing a Person file, you should use Person::setClosed instead. * * @param \DateTime $dateClosing * @return AccompanyingPeriod - * + * */ public function setClosingDate($closingDate) { @@ -155,7 +157,7 @@ class AccompanyingPeriod /** * Get closingDate * - * @return \DateTime + * @return \DateTime */ public function getClosingDate() { @@ -165,7 +167,7 @@ class AccompanyingPeriod /** * @return boolean */ - public function isOpen(): bool + public function isOpen(): bool { if ($this->getOpeningDate() > new \DateTime('now')) { return false; @@ -198,7 +200,7 @@ class AccompanyingPeriod /** * Get remark * - * @return string + * @return string */ public function getRemark() { @@ -206,29 +208,53 @@ class AccompanyingPeriod } /** - * Set person. + * Set persons + */ + public function setPersons($persons) : AccompanyingPeriod + { + $this->persons = $persons; + + return $this; + } + + /** + * Get Persons + */ + public function getPersons() : Collection + { + return $this->persons; + } + + /** + * Return true if a given Person is associated + */ + public function containsPerson(Person $person) : bool + { + foreach ($this->persons as $p) { + if ($p === $person) { return true; } + } + return false; + } + + /** + * Add person. * * For consistency, you should use Person::addAccompanyingPeriod instead. - * - * @param Person $person - * @return AccompanyingPeriod * @see Person::addAccompanyingPeriod */ - public function setPerson(Person $person = null) + public function addPerson(Person $person = null) : AccompanyingPeriod { - $this->person = $person; + $this->persons[] = $person; return $this; } - + /** - * Get person - * - * @return Person + * Remove person. */ - public function getPerson() + public function removePerson(Person $person) : void { - return $this->person; + $this->persons->removeElement($person); } /** @@ -251,21 +277,24 @@ class AccompanyingPeriod /** * If the period can be reopened. - * - * This function test if the period is closed and if the period is the last - * for the associated person - * - * @return boolean + * + * This function test if the period is closed and if the period is the last + * for the given person */ - public function canBeReOpened() + public function canBeReOpened(Person $person) : bool { if ($this->isOpen() === true) { return false; } - $periods = $this->getPerson()->getAccompanyingPeriodsOrdered(); + dump('parcours fermé: '. $this->getId()); - return end($periods) === $this; + foreach ($this->getPersons() as $p) { + if ($p === $person) { + $periods = $p->getAccompanyingPeriodsOrdered(); + return end($periods) === $this; // retourne TRUE si cette période est la dernière + } + } } /** @@ -294,7 +323,7 @@ class AccompanyingPeriod /** * Returns true if the closing date is after the opening date. - * + * * @return boolean */ public function isClosingAfterOpening() diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 36993ce3b..e0bc73990 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -206,10 +206,13 @@ class Person implements HasCenterInterface * The person's accompanying periods (when the person was accompanied by the center) * @var ArrayCollection * - * @ORM\OneToMany( + * @ORM\ManyToMany( * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", - * mappedBy="person", + * inversedBy="persons", * cascade={"persist", "remove", "merge", "detach"}) + * @ORM\JoinTable( + * name="persons_accompanying_periods" + * ) */ private $accompanyingPeriods; //TO-CHANGE in accompanyingHistory @@ -277,19 +280,20 @@ class Person implements HasCenterInterface } /** - * @param AccompanyingPeriod $accompanyingPeriod - * @uses AccompanyingPeriod::setPerson + * Add AccompanyingPeriod + * + * @uses AccompanyingPeriod::addPerson */ - public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) + public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void { - $accompanyingPeriod->setPerson($this); + $accompanyingPeriod->addPerson($this); $this->accompanyingPeriods->add($accompanyingPeriod); } /** - * @param AccompanyingPeriod $accompanyingPeriod + * Remove AccompanyingPeriod */ - public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) + public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void { $this->accompanyingPeriods->remove($accompanyingPeriod); } @@ -303,10 +307,8 @@ class Person implements HasCenterInterface * For closing a file, @see this::close * * To check if the Person and its accompanying period is consistent, use validation. - * - * @param AccompanyingPeriod $accompanyingPeriod */ - public function open(AccompanyingPeriod $accompanyingPeriod) + public function open(AccompanyingPeriod $accompanyingPeriod) : void { $this->proxyAccompanyingPeriodOpenState = true; $this->addAccompanyingPeriod($accompanyingPeriod); @@ -320,20 +322,17 @@ class Person implements HasCenterInterface * * To check if the Person and its accompanying period are consistent, use validation. * - * @param accompanyingPeriod * @throws \Exception if two lines of the accompanying period are open. */ - public function close(AccompanyingPeriod $accompanyingPeriod = null) + public function close(AccompanyingPeriod $accompanyingPeriod = null) : void { $this->proxyAccompanyingPeriodOpenState = false; } /** * Return the opened accompanying period. - * - * @return AccompanyingPeriod */ - public function getOpenedAccompanyingPeriod() + public function getOpenedAccompanyingPeriod() : AccompanyingPeriod { if ($this->isOpen() === false) { return null; @@ -349,29 +348,25 @@ class Person implements HasCenterInterface /** * Returns the opened accompanying period. * - * @return AccompanyingPeriod * @deprecated since 1.1 use `getOpenedAccompanyingPeriod instead */ - public function getCurrentAccompanyingPeriod() + public function getCurrentAccompanyingPeriod() : AccompanyingPeriod { return $this->getOpenedAccompanyingPeriod(); } /** - * @return ArrayCollection + * Get AccompanyingPeriods Collection */ - public function getAccompanyingPeriods() + public function getAccompanyingPeriods() : Collection { return $this->accompanyingPeriods; } /** - * Get the accompanying periods of a give person with the - * chronological order. - * - * @return AccompanyingPeriod[] + * Get the accompanying periods of a give person with the chronological order. */ - public function getAccompanyingPeriodsOrdered() + public function getAccompanyingPeriodsOrdered() : array { $periods = $this->getAccompanyingPeriods()->toArray(); @@ -406,11 +401,9 @@ class Person implements HasCenterInterface } /** - * check if the person is opened - * - * @return boolean + * Check if the person is opened */ - public function isOpen() + public function isOpen() : bool { foreach ($this->getAccompanyingPeriods() as $period) { if ($period->isOpen()) { @@ -1051,4 +1044,15 @@ class Person implements HasCenterInterface return true; } + + public function getFullnameCanonical() : string + { + return $this->fullnameCanonical; + } + + public function setFullnameCanonical($fullnameCanonical) : Person + { + $this->fullnameCanonical = $fullnameCanonical; + return $this; + } } diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig index 4d82813d0..54b03162b 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig @@ -63,7 +63,7 @@ {% endif %} - {% if accompanying_period.canBeReOpened == true %} + {% if accompanying_period.canBeReOpened(person) == true %}
  • {{'Re-open accompanying period'|trans }} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php new file mode 100644 index 000000000..6db7e1521 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php @@ -0,0 +1,76 @@ +connection->prepare($query); + $data->execute(); + foreach ($data as $row) + { + $personId = $row['person_id']; + $accompagnyingPeriodId = $row['accompagnying_period_id']; + $this->datas[] = "($personId, $accompagnyingPeriodId)"; + } + } + + public function up(Schema $schema) : void + { + // create join table + $this->addSql('CREATE TABLE persons_accompanying_periods (person_id INT NOT NULL, accompanyingperiod_id INT NOT NULL, PRIMARY KEY(person_id, accompanyingperiod_id))'); + $this->addSql('CREATE INDEX IDX_49A3871F217BBB47 ON persons_accompanying_periods (person_id)'); + $this->addSql('CREATE INDEX IDX_49A3871F550B0C53 ON persons_accompanying_periods (accompanyingperiod_id)'); + $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT FK_49A3871F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT FK_49A3871F550B0C53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + + // drop column + $this->addSql('DROP INDEX idx_64a4a621217bbb47'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT fk_64a4a621217bbb47'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP person_id'); + } + + public function postUp(Schema $schema) : void + { + // insert datas in new join table + $SQL = "INSERT INTO persons_accompanying_periods (person_id, accompanyingperiod_id) VALUES " . implode(', ', $this->datas); + $this->connection->executeQuery($SQL); + } + + + public function down(Schema $schema) : void + { + // drop join table + //$this->addSql('DROP TABLE persons_accompanying_periods'); + + // INFO this dangerous query is commented, then if you go down you must manually : + // * insert datas in TABLE chill_person_accompanying_period COLUMN person_id ; + // * drop join TABLE persons_accompanying_periods when you are sure it works + + // add column + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD person_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT fk_64a4a621217bbb47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX idx_64a4a621217bbb47 ON chill_person_accompanying_period (person_id)'); + } +} diff --git a/src/Bundle/ChillPersonBundle/translations/validators.fr.yml b/src/Bundle/ChillPersonBundle/translations/validators.fr.yml index 22cb4c719..9f2030f02 100644 --- a/src/Bundle/ChillPersonBundle/translations/validators.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/validators.fr.yml @@ -10,7 +10,7 @@ 'Opening date can not be null': 'La date d''ouverure ne peut être nulle' 'Closing date is not valid': 'La date de fermeture n''est pas valide' 'Closing date can not be null': 'La date de fermeture ne peut être nulle' -The date of closing is before the date of opening: La période de fermeture est après la période d'ouverture +The date of closing is before the date of opening: La période de fermeture est avant la période d'ouverture The birthdate must be before %date%: La date de naissance doit être avant le %date% 'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33123456789': 'Numéro de téléphone invalide: il doit commencer par le préfixe international précédé de "+", ne comporter que des chiffres et faire moins de 20 caractères. Ex: +31623456789' 'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33623456789': 'Numéro de téléphone invalide: il doit commencer par le préfixe international précédé de "+", ne comporter que des chiffres et faire moins de 20 caractères. Ex: +33623456789' From dcc6969310e2b654dd92181ce7a69460142bbf8d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Sat, 27 Mar 2021 11:30:50 +0100 Subject: [PATCH 03/22] add migration down query to preserve datas --- .../migrations/Version20210326113045.php | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php index 6db7e1521..5113ccce2 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php @@ -22,6 +22,13 @@ final class Version20210326113045 extends AbstractMigration return 'Change model relation between Person and AccompagnyingPeriod, without losing datas when going up'; } + /** + * === UP ===> + * + * Preup and postup functions backup datas and transform them + * before injecting them in the new many-to-many join table. + * In these direction, there is no loss. + */ public function preUp(Schema $schema) : void { // extract datas @@ -59,18 +66,47 @@ final class Version20210326113045 extends AbstractMigration } + /** + * <=== DOWN === + * + * In predown and postdown we backup datas from jointable, and transform them + * before injecting them back in the many-to-one column 'person_id'. + * + * The distinct clause makes that for each group of duplicates, it keeps only the first row in the returned result set. + * Then we have only few lost datas. Lost datas: when many persons for one AccompanyingPeriod (keep only first person) + */ + + public function preDown(Schema $schema) : void + { + // extract datas + $query = "SELECT DISTINCT ON (accompanyingperiod_id) accompanyingperiod_id AS id, person_id FROM persons_accompanying_periods ORDER BY id, person_id ASC"; + $data = $this->connection->prepare($query); + $data->execute(); + foreach ($data as $row) + { + $id = $row['id']; + $personId = $row['person_id']; + $this->datas[$id] = "$personId"; + } + } + public function down(Schema $schema) : void { // drop join table - //$this->addSql('DROP TABLE persons_accompanying_periods'); - - // INFO this dangerous query is commented, then if you go down you must manually : - // * insert datas in TABLE chill_person_accompanying_period COLUMN person_id ; - // * drop join TABLE persons_accompanying_periods when you are sure it works + $this->addSql('DROP TABLE persons_accompanying_periods'); // add column $this->addSql('ALTER TABLE chill_person_accompanying_period ADD person_id INT DEFAULT NULL'); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT fk_64a4a621217bbb47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('CREATE INDEX idx_64a4a621217bbb47 ON chill_person_accompanying_period (person_id)'); } + + public function postDown(Schema $schema) : void + { + // insert datas in existing table + foreach ($this->datas as $id => $personId) { + $SQL = "UPDATE chill_person_accompanying_period SET person_id='$personId' WHERE id='$id'"; + $this->connection->executeQuery($SQL); // CHECK if we have to execute query out of foreach loop. how ? + } + } } From 0d9f3d7dbada5a20a858fec408ac5ef894df85fd Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Sat, 27 Mar 2021 11:50:03 +0100 Subject: [PATCH 04/22] fix inconsistency in fixtures --- .../DataFixtures/ORM/LoadPeople.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php index 0977eef2c..cd3126b72 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php @@ -279,8 +279,8 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con private $peoples = array( array( - 'FirstName' => "Depardieu", - 'LastName' => "Gérard", + 'LastName' => "Depardieu", + 'FirstName' => "Gérard", 'Birthdate' => "1948-12-27", 'PlaceOfBirth' => "Châteauroux", 'Gender' => Person::MALE_GENDER, @@ -291,8 +291,8 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con ), array( //to have a person with same firstname as Gérard Depardieu - 'FirstName' => "Depardieu", - 'LastName' => "Jean", + 'LastName' => "Depardieu", + 'FirstName' => "Jean", 'Birthdate' => "1960-10-12", 'CountryOfBirth' => 'FR', 'Nationality' => 'FR', @@ -301,24 +301,24 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con ), array( //to have a person with same birthdate of Gérard Depardieu - 'FirstName' => 'Van Snick', - 'LastName' => 'Bart', + 'LastName' => 'Van Snick', + 'FirstName' => 'Bart', 'Birthdate' => '1948-12-27', 'center' => 'centerA', 'maritalStatus' => 'ms_legalco' ), array( //to have a woman with Depardieu as FirstName - 'FirstName' => 'Depardieu', - 'LastName' => 'Charline', + 'LastName' => 'Depardieu', + 'FirstName' => 'Charline', 'Gender' => Person::FEMALE_GENDER, 'center' => 'centerA', 'maritalStatus' => 'ms_legalco' ), array( //to have a special character in lastName - 'FirstName' => 'Manço', - 'LastName' => 'Étienne', + 'LastName' => 'Manço', + 'FirstName' => 'Étienne', 'center' => 'centerA', 'maritalStatus' => 'ms_unknown' ) From 0a17011cc3e30eff9c6ac6d91b2c0a80429177a0 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Sat, 27 Mar 2021 12:10:00 +0100 Subject: [PATCH 05/22] add fixtures to test duplicate person --- .../DataFixtures/ORM/LoadPeople.php | 70 ++++++++++++------- .../DataFixtures/ORM/LoadPersonACL.php | 12 ++++ 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php index cd3126b72..1419aa47a 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php @@ -289,8 +289,8 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con 'center' => 'centerA', 'maritalStatus' => 'ms_divorce' ), - array( - //to have a person with same firstname as Gérard Depardieu + array( + //to have a person with same firstname as Gérard Depardieu 'LastName' => "Depardieu", 'FirstName' => "Jean", 'Birthdate' => "1960-10-12", @@ -299,28 +299,48 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con 'center' => 'centerA', 'maritalStatus' => 'ms_divorce' ), - array( - //to have a person with same birthdate of Gérard Depardieu - 'LastName' => 'Van Snick', - 'FirstName' => 'Bart', - 'Birthdate' => '1948-12-27', - 'center' => 'centerA', - 'maritalStatus' => 'ms_legalco' - ), - array( - //to have a woman with Depardieu as FirstName - 'LastName' => 'Depardieu', - 'FirstName' => 'Charline', - 'Gender' => Person::FEMALE_GENDER, - 'center' => 'centerA', - 'maritalStatus' => 'ms_legalco' - ), - array( - //to have a special character in lastName - 'LastName' => 'Manço', - 'FirstName' => 'Étienne', - 'center' => 'centerA', - 'maritalStatus' => 'ms_unknown' - ) + array( + //to have a person with same birthdate of Gérard Depardieu + 'LastName' => 'Van Snick', + 'FirstName' => 'Bart', + 'Birthdate' => '1948-12-27', + 'center' => 'centerA', + 'maritalStatus' => 'ms_legalco' + ), + array( + //to have a woman with Depardieu as FirstName + 'LastName' => 'Depardieu', + 'FirstName' => 'Charline', + 'Gender' => Person::FEMALE_GENDER, + 'center' => 'centerA', + 'maritalStatus' => 'ms_legalco' + ), + array( + //to have a special character in lastName + 'LastName' => 'Manço', + 'FirstName' => 'Étienne', + 'center' => 'centerA', + 'maritalStatus' => 'ms_unknown' + ), + array( + //to have true duplicate person + 'LastName' => "Depardieu", + 'FirstName' => "Jean", + 'Birthdate' => "1960-10-12", + 'CountryOfBirth' => 'FR', + 'Nationality' => 'FR', + 'center' => 'centerA', + 'maritalStatus' => 'ms_divorce' + ), + array( + //to have false duplicate person + 'LastName' => "Depardieu", + 'FirstName' => "Jeanne", + 'Birthdate' => "1966-11-13", + 'CountryOfBirth' => 'FR', + 'Nationality' => 'FR', + 'center' => 'centerA', + 'maritalStatus' => 'ms_legalco' + ), ); } diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPersonACL.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPersonACL.php index 0e3cb6dc9..a3f42ced9 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPersonACL.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPersonACL.php @@ -50,24 +50,36 @@ class LoadPersonACL extends AbstractFixture implements OrderedFixtureInterface case 'social': case 'direction': printf("Adding CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE to %s permission group \n", $permissionsGroup->getName()); + $roleScopeUpdate = (new RoleScope()) ->setRole('CHILL_PERSON_UPDATE') ->setScope(null); $permissionsGroup->addRoleScope($roleScopeUpdate); + $roleScopeCreate = (new RoleScope()) ->setRole('CHILL_PERSON_CREATE') ->setScope(null); $permissionsGroup->addRoleScope($roleScopeCreate); + + $roleScopeDuplicate = (new RoleScope()) + ->setRole('CHILL_PERSON_DUPLICATE') + ->setScope(null); + $permissionsGroup->addRoleScope($roleScopeDuplicate); + $roleScopeList = (new RoleScope()) ->setRole(PersonVoter::LISTS) ->setScope(null); $permissionsGroup->addRoleScope($roleScopeList); + $roleScopeStats = (new RoleScope()) ->setRole(PersonVoter::STATS) ->setScope(null); $permissionsGroup->addRoleScope($roleScopeStats); + $manager->persist($roleScopeUpdate); $manager->persist($roleScopeCreate); + $manager->persist($roleScopeDuplicate); + break; case 'administrative': printf("Adding CHILL_PERSON_SEE to %s permission group \n", $permissionsGroup->getName()); From ea4e3c715e1854333aa8da3ab14c1d5077a59a0e Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Sat, 27 Mar 2021 13:37:37 +0100 Subject: [PATCH 06/22] fix syntax php7 --- .../AccompanyingPeriodController.php | 40 ++++++------------- .../Entity/AccompanyingPeriod.php | 26 ++++++------ 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index 21ea358e7..90dae7db6 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -33,6 +33,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Validator\ConstraintViolationListInterface; /** * Class AccompanyingPeriodController @@ -56,12 +57,8 @@ class AccompanyingPeriodController extends AbstractController $this->eventDispatcher = $eventDispatcher; } - /** - * @return Response - */ - public function listAction(int $person_id) + public function listAction(int $person_id): Response { - $person = $this->_getPerson($person_id); $event = new PrivacyEvent($person, [ @@ -76,12 +73,8 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response - */ - public function createAction(int $person_id, Request $request) + public function createAction(int $person_id, Request $request): Response { - $person = $this->_getPerson($person_id); $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, @@ -138,9 +131,10 @@ class AccompanyingPeriodController extends AbstractController } /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response|\Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * @throws Exception */ - public function updateAction(int $person_id, int $period_id, Request $request){ + public function updateAction(int $person_id, int $period_id, Request $request): Response + { $em = $this->getDoctrine()->getManager(); /** @var AccompanyingPeriod $accompanyingPeriod */ @@ -203,10 +197,9 @@ class AccompanyingPeriodController extends AbstractController } /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response * @throws \Exception */ - public function closeAction(int $person_id, Request $request) + public function closeAction(int $person_id, Request $request): Response { $person = $this->_getPerson($person_id); @@ -287,10 +280,8 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @return \Symfony\Component\Validator\ConstraintViolationListInterface - */ - private function _validatePerson(Person $person) { + private function _validatePerson(Person $person): ConstraintViolationListInterface + { $errors = $this->get('validator')->validate($person, null, ['Default']); $errors_accompanying_period = $this->get('validator')->validate($person, null, @@ -303,10 +294,8 @@ class AccompanyingPeriodController extends AbstractController return $errors; } - /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response - */ - public function openAction($person_id, Request $request) { + public function openAction(int $person_id, Request $request): Response + { $person = $this->_getPerson($person_id); $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, @@ -382,10 +371,7 @@ class AccompanyingPeriodController extends AbstractController ]); } - /** - * @return object|\Symfony\Component\HttpFoundation\RedirectResponse|Response - */ - public function reOpenAction(int $person_id, int $period_id, Request $request) + public function reOpenAction(int $person_id, int $period_id, Request $request): Response { /** @var Person $person */ $person = $this->_getPerson($person_id); @@ -432,7 +418,7 @@ class AccompanyingPeriodController extends AbstractController } /** - * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the person is not found + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ private function _getPerson(int $id) : Person { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 63a8b67d3..de7efb124 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -169,15 +169,15 @@ class AccompanyingPeriod */ public function isOpen(): bool { - if ($this->getOpeningDate() > new \DateTime('now')) { + if ($this->getOpeningDate() > new \DateTimeImmutable('now')) { return false; } if ($this->getClosingDate() === null) { return true; - } else { - return false; } + + return false; } /** @@ -210,7 +210,7 @@ class AccompanyingPeriod /** * Set persons */ - public function setPersons($persons) : AccompanyingPeriod + public function setPersons($persons): AccompanyingPeriod { $this->persons = $persons; @@ -220,7 +220,7 @@ class AccompanyingPeriod /** * Get Persons */ - public function getPersons() : Collection + public function getPersons(): Collection { return $this->persons; } @@ -228,7 +228,7 @@ class AccompanyingPeriod /** * Return true if a given Person is associated */ - public function containsPerson(Person $person) : bool + public function containsPerson(Person $person): bool { foreach ($this->persons as $p) { if ($p === $person) { return true; } @@ -242,7 +242,7 @@ class AccompanyingPeriod * For consistency, you should use Person::addAccompanyingPeriod instead. * @see Person::addAccompanyingPeriod */ - public function addPerson(Person $person = null) : AccompanyingPeriod + public function addPerson(Person $person = null): AccompanyingPeriod { $this->persons[] = $person; @@ -252,7 +252,7 @@ class AccompanyingPeriod /** * Remove person. */ - public function removePerson(Person $person) : void + public function removePerson(Person $person): void { $this->persons->removeElement($person); } @@ -281,25 +281,25 @@ class AccompanyingPeriod * This function test if the period is closed and if the period is the last * for the given person */ - public function canBeReOpened(Person $person) : bool + public function canBeReOpened(Person $person): bool { if ($this->isOpen() === true) { return false; } - dump('parcours fermé: '. $this->getId()); - foreach ($this->getPersons() as $p) { if ($p === $person) { $periods = $p->getAccompanyingPeriodsOrdered(); - return end($periods) === $this; // retourne TRUE si cette période est la dernière + return end($periods) === $this; } } + + return false; } /** */ - public function reOpen() + public function reOpen(): void { $this->setClosingDate(null); $this->setClosingMotive(null); From 365a3987435a579e963654621414c98b08fafd71 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Sat, 27 Mar 2021 13:51:57 +0100 Subject: [PATCH 07/22] fixtures accompanyingPeriod + fixture new firstnames set --- .../DataFixtures/ORM/LoadPeople.php | 83 ++++++++++++++----- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php index 1419aa47a..fa20d3457 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php @@ -21,6 +21,7 @@ namespace Chill\PersonBundle\DataFixtures\ORM; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; @@ -195,6 +196,9 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con case 'maritalStatus': $value = $this->getReference($value); break; + case 'accompanyingPeriods': + $this->addAccompanyingPeriods($p, $value, $manager); + break; } //try to add the data using the setSomething function, @@ -230,15 +234,15 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con private function getRandomAddress() { return (new Address()) - ->setStreetAddress1($this->faker->streetAddress) - ->setStreetAddress2( - rand(0,9) > 5 ? $this->faker->streetAddress : '' - ) - ->setPostcode($this->getReference( - LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)] - )) - ->setValidFrom($this->faker->dateTimeBetween('-5 years')) - ; + ->setStreetAddress1($this->faker->streetAddress) + ->setStreetAddress2( + rand(0,9) > 5 ? $this->faker->streetAddress : '' + ) + ->setPostcode($this->getReference( + LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)] + )) + ->setValidFrom($this->faker->dateTimeBetween('-5 years')) + ; } private function getCountry($countryCode) @@ -251,25 +255,25 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con ->findOneByCountryCode($countryCode); } - private $maritalStatusRef = ['ms_single', 'ms_married', 'ms_widow', 'ms_separat', + private $maritalStatusRef = ['ms_single', 'ms_married', 'ms_widow', 'ms_separat', 'ms_divorce', 'ms_legalco', 'ms_unknown']; - private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert", - "Compère", "Jean-de-Dieu", - "Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric", - "Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou", - "Vursuv" ); - private $firstNamesFemale = array("Svedana", "Sevlatina","Irène", "Marcelle", - "Corentine", "Alfonsine","Caroline","Solange","Gostine", "Fatoumata", - "Groseille", "Chana", "Oxana", "Ivana"); + private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert", "Justin", "Brian", + "Compère", "Jean-de-Dieu", "Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric", + "Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou", "Vursuv", "Youssef" ); + + private $firstNamesFemale = array("Svedana", "Sevlatina", "Irène", "Marcelle", + "Corentine", "Alfonsine", "Caroline", "Solange", "Gostine", "Fatoumata", "Nicole", + "Groseille", "Chana", "Oxana", "Ivana", "Julie", "Tina", "Adèle" ); + + private $lastNames = array("Diallo", "Bah", "Gaillot", "Martin"); - private $lastNames = array("Diallo", "Bah", "Gaillot"); private $lastNamesTrigrams = array("fas", "tré", "hu", 'blart', 'van', 'der', 'lin', 'den', - 'ta', 'mi', 'gna', 'bol', 'sac', 'ré', 'jo', 'du', 'pont', 'cas', 'tor', 'rob', 'al', - 'ma', 'gone', 'car',"fu", "ka", "lot", "no", "va", "du", "bu", "su", + 'ta', 'mi', 'net', 'gna', 'bol', 'sac', 'ré', 'jo', 'du', 'pont', 'cas', 'tor', 'rob', 'al', + 'ma', 'gone', 'car',"fu", "ka", "lot", "no", "va", "du", "bu", "su", "jau", "tte", 'sir', "lo", 'to', "cho", "car", 'mo','zu', 'qi', 'mu'); - private $genders = array(Person::MALE_GENDER, Person::FEMALE_GENDER); + private $genders = array(Person::MALE_GENDER, Person::FEMALE_GENDER); private $years = array(); @@ -287,7 +291,22 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con 'CountryOfBirth' => 'FR', 'Nationality' => 'RU', 'center' => 'centerA', - 'maritalStatus' => 'ms_divorce' + 'maritalStatus' => 'ms_divorce', + 'accompanyingPeriods' => [ + [ + 'from' => '2015-02-01', + 'to' => '2015-10-30', + 'remark' => 'oops', + ],[ + 'from' => '2017-06-01', + 'to' => '2018-03-30', + 'remark' => 'argg', + ],[ + 'from' => '2019-01-01', + 'to' => '2019-12-31', + 'remark' => 'blob', + ] + ] ), array( //to have a person with same firstname as Gérard Depardieu @@ -343,4 +362,22 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con 'maritalStatus' => 'ms_legalco' ), ); + + + private function addAccompanyingPeriods(Person $person, array $periods, ObjectManager $manager) + { + foreach ($periods as $period) { + + echo "adding new past Accompanying Period..\n"; + + /** @var AccompanyingPeriod $accompanyingPeriod */ + $accompanyingPeriod = new AccompanyingPeriod(new \DateTime($period['from'])); + $accompanyingPeriod + ->setClosingDate(new \DateTime($period['to'])) + ->setRemark($period['remark']) + ; + + $person->addAccompanyingPeriod($accompanyingPeriod); + } + } } From ba31927dc3e8da0098d9dda745ee1d43d80861d5 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 29 Mar 2021 11:04:01 +0200 Subject: [PATCH 08/22] move CloseMotive Repository in AccompanyingPeriod package --- .../AccompanyingPeriod/ClosingMotive.php | 18 ++++++++++-------- .../Form/Type/ClosingMotivePickerType.php | 2 +- .../ClosingMotiveRepository.php | 15 ++++++++++----- .../config/services/form.yaml | 6 +++--- .../config/services/repository.yaml | 6 +++--- 5 files changed, 27 insertions(+), 20 deletions(-) rename src/Bundle/ChillPersonBundle/Repository/{ => AccompanyingPeriod}/ClosingMotiveRepository.php (82%) diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php index 05149e23f..795f2b29c 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php @@ -1,19 +1,21 @@ - * + * Chill is a software for social workers + * + * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS, + * , + * * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as + * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * + * License, or (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -28,7 +30,7 @@ use Doctrine\Common\Collections\ArrayCollection; * ClosingMotive give an explanation why we closed the Accompanying period * * @ORM\Entity( - * repositoryClass="Chill\PersonBundle\Repository\ClosingMotiveRepository") + * repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository") * @ORM\Table(name="chill_person_closingmotive") */ class ClosingMotive diff --git a/src/Bundle/ChillPersonBundle/Form/Type/ClosingMotivePickerType.php b/src/Bundle/ChillPersonBundle/Form/Type/ClosingMotivePickerType.php index aa7e47583..d2f85c924 100644 --- a/src/Bundle/ChillPersonBundle/Form/Type/ClosingMotivePickerType.php +++ b/src/Bundle/ChillPersonBundle/Form/Type/ClosingMotivePickerType.php @@ -11,7 +11,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive; use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension; use Symfony\Component\OptionsResolver\Options; -use Chill\PersonBundle\Repository\ClosingMotiveRepository; +use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository; /** * Class ClosingMotivePickerType diff --git a/src/Bundle/ChillPersonBundle/Repository/ClosingMotiveRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php similarity index 82% rename from src/Bundle/ChillPersonBundle/Repository/ClosingMotiveRepository.php rename to src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php index c3519796d..10c308b68 100644 --- a/src/Bundle/ChillPersonBundle/Repository/ClosingMotiveRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php @@ -1,11 +1,15 @@ + * Chill is a software for social workers + * + * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS, + * , * * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,7 +19,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -namespace Chill\PersonBundle\Repository; + +namespace Chill\PersonBundle\Repository\AccompanyingPeriod; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; diff --git a/src/Bundle/ChillPersonBundle/config/services/form.yaml b/src/Bundle/ChillPersonBundle/config/services/form.yaml index 659421c8a..99f5fa62b 100644 --- a/src/Bundle/ChillPersonBundle/config/services/form.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/form.yaml @@ -19,10 +19,10 @@ services: arguments: $translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper' $chillEntityRenderExtension: '@Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension' - $closingMotiveRepository: '@Chill\PersonBundle\Repository\ClosingMotiveRepository' + $closingMotiveRepository: '@Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository' tags: - { name: form.type, alias: closing_motive } - + Chill\PersonBundle\Form\AccompanyingPeriodType: arguments: $config: "%chill_person.accompanying_period_fields%" @@ -39,7 +39,7 @@ services: - '@Symfony\Component\Translation\TranslatorInterface' tags: - { name: form.type } - + Chill\PersonBundle\Form\Type\PersonAltNameType: arguments: $configHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper' diff --git a/src/Bundle/ChillPersonBundle/config/services/repository.yaml b/src/Bundle/ChillPersonBundle/config/services/repository.yaml index ee945def7..50209b010 100644 --- a/src/Bundle/ChillPersonBundle/config/services/repository.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/repository.yaml @@ -6,9 +6,9 @@ services: arguments: - 'Chill\PersonBundle\Entity\Person' Chill\PersonBundle\Repository\PersonRepository: '@chill.person.repository.person' - - Chill\PersonBundle\Repository\ClosingMotiveRepository: - class: Chill\PersonBundle\Repository\ClosingMotiveRepository + + Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository: + class: Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository factory: ['@doctrine.orm.entity_manager', getRepository] arguments: - 'Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive' From acff64c16f933be22cd9e6c57a55cb2624c68b6f Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 29 Mar 2021 11:24:57 +0200 Subject: [PATCH 09/22] Add Origin Entity in Accompanying Period package --- .../Entity/AccompanyingPeriod.php | 22 +++++- .../Entity/AccompanyingPeriod/Origin.php | 79 +++++++++++++++++++ .../AccompanyingPeriod/OriginRepository.php | 69 ++++++++++++++++ .../migrations/Version20210329090904.php | 45 +++++++++++ 4 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210329090904.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index de7efb124..9761aa48d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -22,6 +22,7 @@ namespace Chill\PersonBundle\Entity; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -93,6 +94,15 @@ class AccompanyingPeriod */ private $user; + /** + * @var Origin + * + * @ORM\ManyToOne( + * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Origin") + * @ORM\JoinColumn(nullable=true) + */ + private $origin; + /** * AccompanyingPeriod constructor. @@ -355,5 +365,15 @@ class AccompanyingPeriod return $this; } - + + public function getOrigin(): Origin + { + return $this->origin; + } + + public function setOrigin($origin): AccompanyingPeriod + { + $this->origin = $origin; + return $this; + } } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php new file mode 100644 index 000000000..4016cd833 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Origin.php @@ -0,0 +1,79 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Entity\AccompanyingPeriod; + +use Chill\PersonBundle\Entity\AccompanyingPeriod\OriginRepository; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity(repositoryClass=OriginRepository::class) + * @ORM\Table(name="chill_person_accompanying_period_origin") + */ +class Origin +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @ORM\Column(type="string", length=255) + */ + private $label; + + /** + * @ORM\Column(type="date_immutable", nullable=true) + */ + private $noActiveAfter; + + public function getId(): ?int + { + return $this->id; + } + + public function getLabel(): ?string + { + return $this->label; + } + + public function setLabel(string $label): self + { + $this->label = $label; + + return $this; + } + + public function getNoActiveAfter(): ?\DateTimeImmutable + { + return $this->noActiveAfter; + } + + public function setNoActiveAfter(?\DateTimeImmutable $noActiveAfter): self + { + $this->noActiveAfter = $noActiveAfter; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php new file mode 100644 index 000000000..c2283b859 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php @@ -0,0 +1,69 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\PersonBundle\Repository\AccompanyingPeriod; + +use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; + +/** + * @method Origin|null find($id, $lockMode = null, $lockVersion = null) + * @method Origin|null findOneBy(array $criteria, array $orderBy = null) + * @method Origin[] findAll() + * @method Origin[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class OriginRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Origin::class); + } + + // /** + // * @return Origin[] Returns an array of Origin objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('o') + ->andWhere('o.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('o.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Origin + { + return $this->createQueryBuilder('o') + ->andWhere('o.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210329090904.php b/src/Bundle/ChillPersonBundle/migrations/Version20210329090904.php new file mode 100644 index 000000000..1ccab6a50 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210329090904.php @@ -0,0 +1,45 @@ +addSql('CREATE SEQUENCE chill_person_accompanying_period_origin_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_accompanying_period_origin (id INT NOT NULL, label VARCHAR(255) NOT NULL, noActiveAfter DATE DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_origin.noActiveAfter IS \'(DC2Type:date_immutable)\''); + + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD origin_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A86856A273CC FOREIGN KEY (origin_id) REFERENCES chill_person_accompanying_period_origin (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_E260A86856A273CC ON chill_person_accompanying_period (origin_id)'); + + } + + public function down(Schema $schema) : void + { + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A86856A273CC'); + + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_origin_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_person_accompanying_period_origin'); + + $this->addSql('DROP INDEX IDX_E260A86856A273CC'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP origin_id'); + + } +} From c45390dd89f9205bccb4a9bb69e71b0a8dc0f047 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 29 Mar 2021 14:34:02 +0200 Subject: [PATCH 10/22] add Accompanying Period Comment and Resource entities --- .../Entity/AccompanyingPeriod/Comment.php | 152 ++++++++++++++++++ .../Entity/AccompanyingPeriod/Resource.php | 129 +++++++++++++++ .../AccompanyingPeriod/CommentRepository.php | 70 ++++++++ .../AccompanyingPeriod/ResourceRepository.php | 70 ++++++++ .../migrations/Version20210329113152.php | 60 +++++++ 5 files changed, 481 insertions(+) create mode 100644 src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php create mode 100644 src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210329113152.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php new file mode 100644 index 000000000..15b52a9dd --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php @@ -0,0 +1,152 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Entity\AccompanyingPeriod; + +use Chill\PersonBundle\Repository\AccompanyingPeriod\CommentRepository; +use Chill\MainBundle\Entity\User; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity(repositoryClass=CommentRepository::class) + * @ORM\Table(name="chill_person_accompanying_period_comment") + */ +class Comment +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) + * @ORM\JoinColumn(nullable=false) + */ + private $accompanyingPeriod; + + /** + * @ORM\ManyToOne(targetEntity=User::class) + * @ORM\JoinColumn(nullable=false) + */ + private $creator; + + /** + * @ORM\Column(type="datetime") + */ + private $createdAt; + + /** + * @ORM\Column(type="datetime") + */ + private $updatedAt; + + /** + * @ORM\ManyToOne(targetEntity=User::class) + * @ORM\JoinColumn(nullable=false) + */ + private $updatedBy; + + /** + * @ORM\Column(type="text") + */ + private $content; + + public function getId(): ?int + { + return $this->id; + } + + public function getAccompanyingPeriod(): ?AccompanyingPeriod + { + return $this->accompanyingPeriod; + } + + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self + { + $this->accompanyingPeriod = $accompanyingPeriod; + + return $this; + } + + public function getCreator(): ?User + { + return $this->creator; + } + + public function setCreator(?User $creator): self + { + $this->creator = $creator; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTimeInterface $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function getUpdatedAt(): ?\DateTimeInterface + { + return $this->updatedAt; + } + + public function setUpdatedAt(\DateTimeInterface $updatedAt): self + { + $this->updatedAt = $updatedAt; + + return $this; + } + + public function getUpdatedBy(): ?User + { + return $this->updatedBy; + } + + public function setUpdatedBy(?User $updatedBy): self + { + $this->updatedBy = $updatedBy; + + return $this; + } + + public function getContent(): ?string + { + return $this->content; + } + + public function setContent(string $content): self + { + $this->content = $content; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php new file mode 100644 index 000000000..90236f014 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php @@ -0,0 +1,129 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Entity\AccompanyingPeriod; + +use Chill\PersonBundle\Repository\AccompanyingPeriod\ResourceRepository; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment; +use Chill\PersonBundle\Entity\Person; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity(repositoryClass=ResourceRepository::class) + * @ORM\Table(name="chill_person_accompanying_period_resource") + */ +class Resource +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) + * @ORM\JoinColumn(nullable=false) + */ + private $accompanyingPeriod; + + /** + * @ORM\ManyToOne(targetEntity=ThirdParty::class) + * @ORM\JoinColumn(nullable=true) + */ + private $thirdParty; + + /** + * @ORM\ManyToOne(targetEntity=Person::class) + * @ORM\JoinColumn(nullable=true) + */ + private $person; + + /** + * @ORM\ManyToOne(targetEntity=Comment::class) + * @ORM\JoinColumn(nullable=true) + */ + private $comment; + + public function getId(): ?int + { + return $this->id; + } + + public function getAccompanyingPeriod(): ?AccompanyingPeriod + { + return $this->accompanyingPeriod; + } + + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self + { + $this->accompanyingPeriod = $accompanyingPeriod; + + return $this; + } + + public function getThirdParty(): ?ThirdParty + { + return $this->thirdParty; + } + + public function setThirdParty(?ThirdParty $thirdParty): self + { + $this->thirdParty = $thirdParty; + + return $this; + } + + public function getPerson(): ?Person + { + return $this->person; + } + + public function setPerson(?Person $person): self + { + $this->person = $person; + + return $this; + } + + public function getComment(): ?Comment + { + return $this->comment; + } + + public function setComment(?Comment $comment): self + { + $this->comment = $comment; + + return $this; + } + + /** + * @return Person|ThirdParty + */ + public function getResource() + { + return $this->person ?? $this->thirdParty; + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php new file mode 100644 index 000000000..8abda6903 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php @@ -0,0 +1,70 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Repository\AccompanyingPeriod; + +use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; + +/** + * @method Comment|null find($id, $lockMode = null, $lockVersion = null) + * @method Comment|null findOneBy(array $criteria, array $orderBy = null) + * @method Comment[] findAll() + * @method Comment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class CommentRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Comment::class); + } + + // /** + // * @return Comment[] Returns an array of Comment objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Comment + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php new file mode 100644 index 000000000..0507d9b6d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php @@ -0,0 +1,70 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Repository\AccompanyingPeriod; + +use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; + +/** + * @method Resource|null find($id, $lockMode = null, $lockVersion = null) + * @method Resource|null findOneBy(array $criteria, array $orderBy = null) + * @method Resource[] findAll() + * @method Resource[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ResourceRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Resource::class); + } + + // /** + // * @return Resource[] Returns an array of Resource objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('r') + ->andWhere('r.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('r.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Resource + { + return $this->createQueryBuilder('r') + ->andWhere('r.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210329113152.php b/src/Bundle/ChillPersonBundle/migrations/Version20210329113152.php new file mode 100644 index 000000000..2cba2dd7e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210329113152.php @@ -0,0 +1,60 @@ +addSql('CREATE SEQUENCE chill_person_accompanying_period_comment_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_accompanying_period_comment (id INT NOT NULL, creator_id INT NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, content TEXT NOT NULL, accompanyingPeriod_id INT NOT NULL, updatedBy_id INT NOT NULL, PRIMARY KEY(id))'); + + $this->addSql('CREATE INDEX IDX_CD960EF3D7FA8EF0 ON chill_person_accompanying_period_comment (accompanyingPeriod_id)'); + $this->addSql('CREATE INDEX IDX_CD960EF361220EA6 ON chill_person_accompanying_period_comment (creator_id)'); + $this->addSql('CREATE INDEX IDX_CD960EF365FF1AEC ON chill_person_accompanying_period_comment (updatedBy_id)'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_comment ADD CONSTRAINT FK_CD960EF3D7FA8EF0 FOREIGN KEY (accompanyingPeriod_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_comment ADD CONSTRAINT FK_CD960EF361220EA6 FOREIGN KEY (creator_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_comment ADD CONSTRAINT FK_CD960EF365FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + + $this->addSql('CREATE SEQUENCE chill_person_accompanying_period_resource_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_accompanying_period_resource (id INT NOT NULL, person_id INT DEFAULT NULL, comment_id INT DEFAULT NULL, accompanyingPeriod_id INT NOT NULL, thirdParty_id INT DEFAULT NULL, PRIMARY KEY(id))'); + + $this->addSql('CREATE INDEX IDX_DC78989FD7FA8EF0 ON chill_person_accompanying_period_resource (accompanyingPeriod_id)'); + $this->addSql('CREATE INDEX IDX_DC78989F3EA5CAB0 ON chill_person_accompanying_period_resource (thirdParty_id)'); + $this->addSql('CREATE INDEX IDX_DC78989F217BBB47 ON chill_person_accompanying_period_resource (person_id)'); + $this->addSql('CREATE INDEX IDX_DC78989FF8697D13 ON chill_person_accompanying_period_resource (comment_id)'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_resource ADD CONSTRAINT FK_DC78989FD7FA8EF0 FOREIGN KEY (accompanyingPeriod_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_resource ADD CONSTRAINT FK_DC78989F3EA5CAB0 FOREIGN KEY (thirdParty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_resource ADD CONSTRAINT FK_DC78989F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_resource ADD CONSTRAINT FK_DC78989FF8697D13 FOREIGN KEY (comment_id) REFERENCES chill_person_accompanying_period_comment (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + } + + public function down(Schema $schema) : void + { + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_resource_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_person_accompanying_period_resource'); + + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_comment_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_person_accompanying_period_comment'); + + } +} From 85c4560f2226dfae7f5e8740efa270f492b92016 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 29 Mar 2021 17:03:12 +0200 Subject: [PATCH 11/22] Complete accompanying period entity --- .../Entity/AccompanyingPeriod.php | 249 ++++++++++++++---- .../migrations/Version20210329144338.php | 74 ++++++ 2 files changed, 275 insertions(+), 48 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 9761aa48d..700abda88 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -22,7 +22,10 @@ namespace Chill\PersonBundle\Entity; +use Chill\MainBundle\Entity\Scope; +use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive; use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; +use Chill\ThirdPartyBundle\Entity\ThirdParty; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -37,6 +40,11 @@ use Chill\MainBundle\Entity\User; */ class AccompanyingPeriod { + const INTENSITY = [ + 'occasional' => 'ponctuel', + 'regular' => 'régulier' + ]; + /** * @var integer * @@ -69,7 +77,6 @@ class AccompanyingPeriod /** * @var Collection - * * @ORM\ManyToMany( * targetEntity="Chill\PersonBundle\Entity\Person", * mappedBy="accompanyingPeriods") @@ -86,23 +93,79 @@ class AccompanyingPeriod private $closingMotive = null; /** - * The user making the accompanying - * @var User - * - * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") + * @ORM\ManyToOne(targetEntity=User::class) * @ORM\JoinColumn(nullable=true) */ private $user; /** - * @var Origin - * - * @ORM\ManyToOne( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Origin") + * @ORM\ManyToOne(targetEntity=User::class) + * @ORM\JoinColumn(nullable=true) + */ + private $createdBy; + + /** + * @var string + * @ORM\Column(type="string", length=32, nullable=true) + */ + private $step = 'DRAFT'; + + /** + * @ORM\ManyToOne(targetEntity=Origin::class) * @ORM\JoinColumn(nullable=true) */ private $origin; + /** + * @var string + * @ORM\Column(type="string", nullable=true) + */ + private $intensity; + + /** + * @var Collection + * @ORM\ManyToMany( + * targetEntity=Scope::class, + * cascade={} + * ) + * @ORM\JoinTable( + * name="accompanying_periods_scopes", + * joinColumns={@ORM\JoinColumn(name="accompanying_period_id", referencedColumnName="id")}, + * inverseJoinColumns={@ORM\JoinColumn(name="scope_id", referencedColumnName="id")} + * ) + */ + private $scopes; + + /** + * @ORM\ManyToOne(targetEntity=Person::class) + * @ORM\JoinColumn(nullable=true) + */ + private $requestorPerson; + + /** + * @ORM\ManyToOne(targetEntity=ThirdParty::class) + * @ORM\JoinColumn(nullable=true) + */ + private $requestorThirdParty; + + /** + * @var bool + * @ORM\Column(type="boolean") + */ + private $requestorAnonymous = false; + + /** + * @var bool + * @ORM\Column(type="boolean") + */ + private $emergency = false; + + /** + * @var bool + * @ORM\Column(type="boolean") + */ + private $confidential = false; + /** * AccompanyingPeriod constructor. @@ -113,6 +176,7 @@ class AccompanyingPeriod public function __construct(\DateTime $dateOpening) { $this->setOpeningDate($dateOpening); $this->persons = new ArrayCollection(); + $this->scopes = new ArrayCollection(); } /** @@ -217,71 +281,45 @@ class AccompanyingPeriod return $this->remark; } - /** - * Set persons - */ - public function setPersons($persons): AccompanyingPeriod - { - $this->persons = $persons; - - return $this; - } - - /** - * Get Persons - */ public function getPersons(): Collection { return $this->persons; } - /** - * Return true if a given Person is associated - */ public function containsPerson(Person $person): bool { foreach ($this->persons as $p) { if ($p === $person) { return true; } } + return false; } /** - * Add person. - * * For consistency, you should use Person::addAccompanyingPeriod instead. * @see Person::addAccompanyingPeriod */ - public function addPerson(Person $person = null): AccompanyingPeriod + public function addPerson(Person $person = null): self { $this->persons[] = $person; return $this; } - /** - * Remove person. - */ public function removePerson(Person $person): void { $this->persons->removeElement($person); } - /** - * @return AccompanyingPeriod\ClosingMotive - */ - public function getClosingMotive() + public function getClosingMotive(): ?ClosingMotive { return $this->closingMotive; } - /** - * @param AccompanyingPeriod\ClosingMotive|null $closingMotive - * @return $this - */ - public function setClosingMotive(AccompanyingPeriod\ClosingMotive $closingMotive = null) + public function setClosingMotive(ClosingMotive $closingMotive = null): self { $this->closingMotive = $closingMotive; + return $this; } @@ -347,18 +385,11 @@ class AccompanyingPeriod } } - /** - * @return User|null - */ function getUser(): ?User { return $this->user; } - /** - * @param User $user - * @return AccompanyingPeriod - */ function setUser(User $user): self { $this->user = $user; @@ -371,9 +402,131 @@ class AccompanyingPeriod return $this->origin; } - public function setOrigin($origin): AccompanyingPeriod + public function setOrigin(Origin $origin): self { $this->origin = $origin; + return $this; } + + public function getRequestorPerson(): ?Person + { + return $this->requestorPerson; + } + + public function setRequestorPerson(Person $requestorPerson): self + { + $this->requestorPerson = ($this->requestorThirdParty === null) ? $requestorPerson : null; + + return $this; + } + + public function getRequestorThirdParty(): ?ThirdParty + { + return $this->requestorThirdParty; + } + + public function setRequestorThirdParty(ThirdParty $requestorThirdParty): self + { + $this->requestorThirdParty = ($this->requestorPerson === null) ? $requestorThirdParty : null; + + return $this; + } + + /** + * @return Person|ThirdParty + */ + public function getRequestor() + { + return $this->requestorPerson ?? $this->requestorThirdParty; + } + + public function isRequestorAnonymous(): bool + { + return $this->requestorAnonymous; + } + + public function setRequestorAnonymous(bool $requestorAnonymous): self + { + $this->requestorAnonymous = $requestorAnonymous; + + return $this; + } + + public function isEmergency(): bool + { + return $this->emergency; + } + + public function setEmergency(bool $emergency): self + { + $this->emergency = $emergency; + + return $this; + } + + public function isConfidential(): bool + { + return $this->confidential; + } + + public function setConfidential(bool $confidential): self + { + $this->confidential = $confidential; + + return $this; + } + + public function getCreatedBy(): ?User + { + return $this->createdBy; + } + + public function setCreatedBy(User $createdBy): self + { + $this->createdBy = $createdBy; + + return $this; + } + + public function getStep(): string + { + return $this->step; + } + + public function setStep(string $step): self + { + $this->step = $step; + + return $this; + } + + public function getIntensity(): string + { + return $this->intensity; + } + + public function setIntensity(string $intensity): self + { + $this->intensity = $intensity; + + return $this; + } + + public function getScopes(): Collection + { + return $this->scopes; + } + + public function addScope(Scope $scope): self + { + $this->scopes[] = $scope; + + return $this; + } + + public function removeScope(Scope $scope): void + { + $this->scopes->removeElement($scope); + } } diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php new file mode 100644 index 000000000..a0cdf39cd --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php @@ -0,0 +1,74 @@ +addSql('CREATE TABLE accompanying_periods_scopes (accompanying_period_id INT NOT NULL, scope_id INT NOT NULL, PRIMARY KEY(accompanying_period_id, scope_id))'); + + $this->addSql('CREATE INDEX IDX_87C4EAB032A7A428 ON accompanying_periods_scopes (accompanying_period_id)'); + $this->addSql('CREATE INDEX IDX_87C4EAB0682B5931 ON accompanying_periods_scopes (scope_id)'); + + $this->addSql('ALTER TABLE accompanying_periods_scopes ADD CONSTRAINT FK_87C4EAB032A7A428 FOREIGN KEY (accompanying_period_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE accompanying_periods_scopes ADD CONSTRAINT FK_87C4EAB0682B5931 FOREIGN KEY (scope_id) REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD step VARCHAR(32) DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD intensity VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD createdBy_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorPerson_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorThirdParty_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorAnonymous BOOLEAN NOT NULL DEFAULT FALSE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD emergency BOOLEAN NOT NULL DEFAULT FALSE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD confidential BOOLEAN NOT NULL DEFAULT FALSE'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A8683174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A86834269C3F FOREIGN KEY (requestorPerson_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A868CFE4D554 FOREIGN KEY (requestorThirdParty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + $this->addSql('CREATE INDEX IDX_E260A8683174800F ON chill_person_accompanying_period (createdBy_id)'); + $this->addSql('CREATE INDEX IDX_E260A86834269C3F ON chill_person_accompanying_period (requestorPerson_id)'); + $this->addSql('CREATE INDEX IDX_E260A868CFE4D554 ON chill_person_accompanying_period (requestorThirdParty_id)'); + + } + + public function down(Schema $schema) : void + { + + $this->addSql('DROP TABLE accompanying_periods_scopes'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A8683174800F'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A86834269C3F'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A868CFE4D554'); + + $this->addSql('DROP INDEX IDX_E260A8683174800F'); + $this->addSql('DROP INDEX IDX_E260A86834269C3F'); + $this->addSql('DROP INDEX IDX_E260A868CFE4D554'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP step'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP intensity'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP createdBy_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP requestorPerson_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP requestorThirdParty_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP requestorAnonymous'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP emergency'); + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP confidential'); + + } +} From 24d8b5559177e663ff1f6bc3be27ed45bbf4b084 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 30 Mar 2021 09:34:40 +0200 Subject: [PATCH 12/22] minor corrections --- src/Bundle/ChillPersonBundle/Entity/Person.php | 4 +++- .../Resources/views/AccompanyingPeriod/list.html.twig | 3 +++ .../ChillPersonBundle/migrations/Version20210329144338.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index e0bc73990..b3a3f5628 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -284,10 +284,12 @@ class Person implements HasCenterInterface * * @uses AccompanyingPeriod::addPerson */ - public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void + public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): self { $accompanyingPeriod->addPerson($this); $this->accompanyingPeriods->add($accompanyingPeriod); + + return $this; } /** diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig index 54b03162b..1dfc72198 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/list.html.twig @@ -5,6 +5,9 @@ {% block title %}{{ 'Person accompanying period - %name%'|trans({ '%name%' : person.__toString}) }}{% endblock title %} {% block personcontent %} + +

    {{ 'Accompanying period list'|trans }}

    + diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php index a0cdf39cd..f8ae84adc 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php @@ -16,7 +16,7 @@ final class Version20210329144338 extends AbstractMigration { public function getDescription() : string { - return 'Complete accompanying period table'; + return 'Complete AccompanyingPeriod table'; } public function up(Schema $schema) : void From 1d6a8987e9be07bf476d24df6f0414d4f15bcc9d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 30 Mar 2021 18:16:37 +0200 Subject: [PATCH 13/22] Allow to enable multiple simultaneous accompanyingPeriods --- .../Controller/AccompanyingPeriodController.php | 14 +++++++++----- .../DependencyInjection/ChillPersonExtension.php | 15 +++++++++------ .../DependencyInjection/Configuration.php | 13 +++++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index c3851cfcf..6b6e4dda9 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -293,11 +293,15 @@ class AccompanyingPeriodController extends AbstractController $errors = $this->validator->validate($person, null, ['Default']); - $errors_accompanying_period = $this->validator->validate($person, null, - ['accompanying_period_consistent']); - - foreach($errors_accompanying_period as $error ) { - $errors->add($error); + // Can be disabled with config + if (false === $this->container->getParameter('chill_person.allow_multiple_simultaneous_accompanying_periods')) { + + $errors_accompanying_period = $this->validator->validate($person, null, + ['accompanying_period_consistent']); + + foreach($errors_accompanying_period as $error ) { + $errors->add($error); + } } return $errors; diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index c1ea40486..f8e8173de 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -56,6 +56,9 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $this->handlePersonFieldsParameters($container, $config['person_fields']); $this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']); + + $container->setParameter('chill_person.allow_multiple_simultaneous_accompanying_periods', + $config['allow_multiple_simultaneous_accompanying_periods']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader->load('services.yaml'); @@ -140,7 +143,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac } $container->prependExtensionConfig('chill_custom_fields', - array('customizables_entities' => + array('customizables_entities' => array( array('class' => 'Chill\PersonBundle\Entity\Person', 'name' => 'PersonEntity') ) @@ -152,7 +155,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac * @param ContainerBuilder $container * @throws MissingBundleException */ - public function prepend(ContainerBuilder $container) + public function prepend(ContainerBuilder $container) { $this->prependRoleHierarchy($container); $this->prependHomepageWidget($container); @@ -189,7 +192,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac /** * Add a widget "add a person" on the homepage, automatically - * + * * @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container */ protected function prependHomepageWidget(containerBuilder $container) @@ -208,7 +211,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac /** * Add role hierarchy. - * + * * @param ContainerBuilder $container */ protected function prependRoleHierarchy(ContainerBuilder $container) @@ -217,7 +220,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac 'role_hierarchy' => array( 'CHILL_PERSON_UPDATE' => array('CHILL_PERSON_SEE'), 'CHILL_PERSON_CREATE' => array('CHILL_PERSON_SEE'), - PersonVoter::LISTS => [ ChillExportVoter::EXPORT ], + PersonVoter::LISTS => [ ChillExportVoter::EXPORT ], PersonVoter::STATS => [ ChillExportVoter::EXPORT ] ) )); @@ -225,7 +228,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac /** * Add DQL function linked with person - * + * * @param ContainerBuilder $container */ protected function prependDoctrineDQL(ContainerBuilder $container) diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index 9784e8523..3ebe3ceb1 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -104,8 +104,21 @@ class Configuration implements ConfigurationInterface ->canBeDisabled() ->children() ->append($this->addFieldNode('user')) + ->append($this->addFieldNode('createdBy')) + ->append($this->addFieldNode('step')) + ->append($this->addFieldNode('origin')) + ->append($this->addFieldNode('intensity')) + ->append($this->addFieldNode('scopes')) + ->append($this->addFieldNode('requestor')) + ->append($this->addFieldNode('anonymous')) + ->append($this->addFieldNode('emergency')) + ->append($this->addFieldNode('confidential')) ->end() //children for 'accompanying_person_fields', parent = array 'person_fields' ->end() // paccompanying_person_fields, parent = children of root + ->booleanNode('allow_multiple_simultaneous_accompanying_periods') + ->info('Can we have more than one simultaneous accompanying period in the same time. Default false.') + ->defaultValue(false) + ->end() ->end() // children of 'root', parent = root ; From a3395895cb203d5c20003a633022763886bdf66a Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 30 Mar 2021 19:44:48 +0200 Subject: [PATCH 14/22] Rename table closinmotive --- .../AccompanyingPeriod/ClosingMotive.php | 2 +- .../ClosingMotiveRepository.php | 4 +-- .../migrations/Version20210329144338.php | 6 ++-- .../migrations/Version20210330164922.php | 35 +++++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210330164922.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php index 795f2b29c..1bb48da00 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/ClosingMotive.php @@ -31,7 +31,7 @@ use Doctrine\Common\Collections\ArrayCollection; * * @ORM\Entity( * repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository") - * @ORM\Table(name="chill_person_closingmotive") + * @ORM\Table(name="chill_person_accompanying_period_closingmotive") */ class ClosingMotive { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php index 10c308b68..ef1130b62 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ClosingMotiveRepository.php @@ -44,13 +44,13 @@ class ClosingMotiveRepository extends EntityRepository $rsm->addRootEntityFromClassMetadata($this->getClassName(), 'cm'); $sql = "SELECT ".(string) $rsm." - FROM chill_person_closingmotive AS cm + FROM chill_person_accompanying_period_closingmotive AS cm WHERE active IS TRUE "; if ($onlyLeaf) { $sql .= "AND cm.id NOT IN ( - SELECT DISTINCT parent_id FROM chill_person_closingmotive WHERE parent_id IS NOT NULL + SELECT DISTINCT parent_id FROM chill_person_accompanying_period_closingmotive WHERE parent_id IS NOT NULL )"; } diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php index f8ae84adc..dc75997ab 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210329144338.php @@ -34,9 +34,9 @@ final class Version20210329144338 extends AbstractMigration $this->addSql('ALTER TABLE chill_person_accompanying_period ADD createdBy_id INT DEFAULT NULL'); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorPerson_id INT DEFAULT NULL'); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorThirdParty_id INT DEFAULT NULL'); - $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorAnonymous BOOLEAN NOT NULL DEFAULT FALSE'); - $this->addSql('ALTER TABLE chill_person_accompanying_period ADD emergency BOOLEAN NOT NULL DEFAULT FALSE'); - $this->addSql('ALTER TABLE chill_person_accompanying_period ADD confidential BOOLEAN NOT NULL DEFAULT FALSE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD requestorAnonymous BOOLEAN NOT NULL DEFAULT \'false\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD emergency BOOLEAN NOT NULL DEFAULT \'false\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD confidential BOOLEAN NOT NULL DEFAULT \'false\''); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A8683174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A86834269C3F FOREIGN KEY (requestorPerson_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210330164922.php b/src/Bundle/ChillPersonBundle/migrations/Version20210330164922.php new file mode 100644 index 000000000..681132565 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210330164922.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE chill_person_closingmotive RENAME TO chill_person_accompanying_period_closingmotive'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_closingmotive RENAME CONSTRAINT fk_92351ece727aca70 TO FK_72D110E8727ACA70'); + $this->addSql('ALTER TABLE chill_person_accompanying_period RENAME CONSTRAINT fk_64a4a621504cb38d TO FK_E260A868504CB38D'); + } + + public function down(Schema $schema) : void + { + $this->addSql('ALTER TABLE chill_person_accompanying_period_closingmotive RENAME TO chill_person_closingmotive'); + $this->addSql('ALTER TABLE chill_person_closingmotive RENAME CONSTRAINT FK_72D110E8727ACA70 TO fk_92351ece727aca70'); + $this->addSql('ALTER TABLE chill_person_accompanying_period RENAME CONSTRAINT FK_E260A868504CB38D TO fk_64a4a621504cb38d'); + } +} From bd7b4b3fdbddd5b7ea7f23a3f88dfabf9b56f969 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 31 Mar 2021 10:37:31 +0200 Subject: [PATCH 15/22] fix repository for AccompanyingPeriod --- .../Entity/AccompanyingPeriod.php | 4 +- .../AccompanyingPeriodRepository.php | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 700abda88..d82857bdb 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -33,9 +33,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; use Chill\MainBundle\Entity\User; /** - * AccompanyingPeriod + * AccompanyingPeriod Class * - * @ORM\Entity() + * @ORM\Entity(repositoryClass=AccompanyingPeriodRepository::class) * @ORM\Table(name="chill_person_accompanying_period") */ class AccompanyingPeriod diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php new file mode 100644 index 000000000..009793bdb --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php @@ -0,0 +1,70 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Repository; + +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; + +/** + * @method AccompanyingPeriod|null find($id, $lockMode = null, $lockVersion = null) + * @method AccompanyingPeriod|null findOneBy(array $criteria, array $orderBy = null) + * @method AccompanyingPeriod[] findAll() + * @method AccompanyingPeriod[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class AccompanyingPeriodRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, AccompanyingPeriod::class); + } + + // /** + // * @return AccompanyingPeriod[] Returns an array of AccompanyingPeriod objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('a') + ->andWhere('a.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('a.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?AccompanyingPeriod + { + return $this->createQueryBuilder('a') + ->andWhere('a.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} From a98056d31b25217a65b3f72c189033aa8c66753c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 31 Mar 2021 11:21:51 +0200 Subject: [PATCH 16/22] Transform join table between Person and AccompanyingPeriod in Doctrine entity --- .../Entity/AccompanyingPeriod.php | 6 +- .../AccompanyingPeriodParticipation.php | 65 +++++++++++++++++ .../ChillPersonBundle/Entity/Person.php | 13 ++-- ...ompanyingPeriodParticipationRepository.php | 70 +++++++++++++++++++ .../migrations/Version20210331084527.php | 59 ++++++++++++++++ 5 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php create mode 100644 src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index d82857bdb..29355b5b8 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -77,9 +77,9 @@ class AccompanyingPeriod /** * @var Collection - * @ORM\ManyToMany( - * targetEntity="Chill\PersonBundle\Entity\Person", - * mappedBy="accompanyingPeriods") + * + * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, + * mappedBy="accompanyingPeriod") */ private $persons; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php new file mode 100644 index 000000000..4a2fe3b44 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php @@ -0,0 +1,65 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Entity; + +use Chill\PersonBundle\Repository\AccompanyingPeriodParticipationRepository; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\Person; +use Doctrine\ORM\Mapping as ORM; + +/** + * AccompanyingPeriodParticipation Class + * + * @package Chill\PersonBundle\Entity + * @ORM\Entity(repositoryClass=AccompanyingPeriodParticipationRepository::class) + * @ORM\Table(name="chill_person_accompanying_period_participation") + */ +class AccompanyingPeriodParticipation +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @ORM\ManyToOne(targetEntity=Person::class, + * inversedBy="accompanyingPeriods") + * @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false) + */ + private $person; + + /** + * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, + * inversedBy="persons") + * @ORM\JoinColumn(name="accompanyingperiod_id", referencedColumnName="id", nullable=false) + */ + private $accompanyingPeriod; + + + public function getId(): ?int + { + return $this->id; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index b3a3f5628..bd89fbcea 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -42,7 +42,6 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; * name="person_names", * columns={"firstName", "lastName"} * )}) - * sf4 check index name * @ORM\HasLifecycleCallbacks() */ class Person implements HasCenterInterface @@ -204,17 +203,13 @@ class Person implements HasCenterInterface /** * The person's accompanying periods (when the person was accompanied by the center) - * @var ArrayCollection + * @var Collection * - * @ORM\ManyToMany( - * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", - * inversedBy="persons", + * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, + * mappedBy="person", * cascade={"persist", "remove", "merge", "detach"}) - * @ORM\JoinTable( - * name="persons_accompanying_periods" - * ) */ - private $accompanyingPeriods; //TO-CHANGE in accompanyingHistory + private $accompanyingPeriods; /** * A remark over the person diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php new file mode 100644 index 000000000..8d767b6ab --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php @@ -0,0 +1,70 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Repository; + +use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; + +/** + * @method AccompanyingPeriodParticipation|null find($id, $lockMode = null, $lockVersion = null) + * @method AccompanyingPeriodParticipation|null findOneBy(array $criteria, array $orderBy = null) + * @method AccompanyingPeriodParticipation[] findAll() + * @method AccompanyingPeriodParticipation[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class AccompanyingPeriodParticipationRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, AccompanyingPeriodParticipation::class); + } + + // /** + // * @return AccompanyingPeriodParticipation[] Returns an array of AccompanyingPeriodParticipation objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('a') + ->andWhere('a.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('a.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?AccompanyingPeriodParticipation + { + return $this->createQueryBuilder('a') + ->andWhere('a.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php b/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php new file mode 100644 index 000000000..c42da9874 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php @@ -0,0 +1,59 @@ +addSql('ALTER TABLE persons_accompanying_periods DROP CONSTRAINT persons_accompanying_periods_pkey'); + $this->addSql('ALTER TABLE persons_accompanying_periods RENAME TO chill_person_accompanying_period_participation'); + + // 2 + // NOT NECCESSARY $this->addSql('CREATE SEQUENCE chill_person_accompanying_period_participation_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD COLUMN id SERIAL NOT NULL PRIMARY KEY'); + // TO CHECK !! automatically complete missing values allowing not null clause + // but add strange "id serial (10) default nextval('chill_person_accompanying_period_participation_id_seq':: regclass )" in column definition + + // 3 + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT fk_49a3871f217bbb47'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT fk_49a3871f550b0c53'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT FK_A59DF89F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT FK_A59DF89F550B0C53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER INDEX idx_49a3871f217bbb47 RENAME TO IDX_A59DF89F217BBB47'); + $this->addSql('ALTER INDEX idx_49a3871f550b0c53 RENAME TO IDX_A59DF89F550B0C53'); + } + + public function down(Schema $schema) : void + { + // 3 + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT FK_A59DF89F217BBB47'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT FK_A59DF89F550B0C53'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT fk_49a3871f217bbb47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT fk_49a3871f550b0c53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER INDEX idx_a59df89f550b0c53 RENAME TO idx_49a3871f550b0c53'); + $this->addSql('ALTER INDEX idx_a59df89f217bbb47 RENAME TO idx_49a3871f217bbb47'); + + // 2 + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_participation_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP id'); + + // 1 + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation RENAME TO persons_accompanying_periods'); + $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT persons_accompanying_periods_pkey PRIMARY KEY (person_id, accompanyingperiod_id)'); + } +} From 01f24ecf1f237fd046c58a2a3adf3769aa85846a Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 31 Mar 2021 20:57:15 +0200 Subject: [PATCH 17/22] Adapt entity AccompanyingPeriodParticipation attributes and methods (dont break UI) --- .../AccompanyingPeriodController.php | 15 ++-- .../Entity/AccompanyingPeriod.php | 76 +++++++++++++------ .../AccompanyingPeriodParticipation.php | 67 +++++++++++++++- .../ChillPersonBundle/Entity/Person.php | 75 ++++++++++++++---- .../config/services/repository.yaml | 6 ++ .../ChillPersonBundle/config/validation.yaml | 6 +- .../migrations/Version20210331084527.php | 16 +++- 7 files changed, 203 insertions(+), 58 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php index 6b6e4dda9..2b51e9191 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodController.php @@ -88,12 +88,12 @@ class AccompanyingPeriodController extends AbstractController $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, 'You are not allowed to update this person'); - $accompanyingPeriod = new AccompanyingPeriod(new \DateTime()); - $accompanyingPeriod->setClosingDate(new \DateTime()); - - $person->addAccompanyingPeriod( - $accompanyingPeriod); - + $accompanyingPeriod = new AccompanyingPeriod(new \DateTimeImmutable('now')); + $accompanyingPeriod->setClosingDate(new \DateTimeImmutable('now')); + + $accompanyingPeriod->addPerson($person); + //or $person->addAccompanyingPeriod($accompanyingPeriod); + $form = $this->createForm( AccompanyingPeriodType::class, $accompanyingPeriod, [ @@ -153,8 +153,9 @@ class AccompanyingPeriodController extends AbstractController } /** @var Person $person */ - $person = $em->getRepository(Person::class)->find($person_id); + $person = $this->_getPerson($person_id); + // CHECK if (! $accompanyingPeriod->containsPerson($person)) { throw new Exception("Accompanying period " . $period_id . " does not contain person " . $person_id); } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 29355b5b8..915500392 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -35,7 +35,7 @@ use Chill\MainBundle\Entity\User; /** * AccompanyingPeriod Class * - * @ORM\Entity(repositoryClass=AccompanyingPeriodRepository::class) + * @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository") * @ORM\Table(name="chill_person_accompanying_period") */ class AccompanyingPeriod @@ -79,9 +79,10 @@ class AccompanyingPeriod * @var Collection * * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class, - * mappedBy="accompanyingPeriod") + * mappedBy="accompanyingPeriod", + * cascade={"persist", "remove", "merge", "detach"}) */ - private $persons; + private $participations; /** * @var AccompanyingPeriod\ClosingMotive @@ -175,7 +176,7 @@ class AccompanyingPeriod */ public function __construct(\DateTime $dateOpening) { $this->setOpeningDate($dateOpening); - $this->persons = new ArrayCollection(); + $this->participations = new ArrayCollection(); $this->scopes = new ArrayCollection(); } @@ -280,37 +281,63 @@ class AccompanyingPeriod { return $this->remark; } - - public function getPersons(): Collection - { - return $this->persons; - } - public function containsPerson(Person $person): bool + /** + * Get Participations Collection + */ + public function getParticipations(): Collection { - foreach ($this->persons as $p) { - if ($p === $person) { return true; } - } - - return false; + return $this->participations; } /** - * For consistency, you should use Person::addAccompanyingPeriod instead. - * @see Person::addAccompanyingPeriod + * This private function scan Participations Collection, + * searching for a given Person + */ + private function participationsContainsPerson(Person $person): ?AccompanyingPeriodParticipation + { + foreach ($this->participations as $participation) { + /** @var AccompanyingPeriodParticipation $participation */ + if ($person === $participation->getPerson()) { + return $participation; + }} + + return null; + } + + /** + * This public function is the same but return only true or false + */ + public function containsPerson(Person $person): bool + { + return ($this->participationsContainsPerson($person) === null) ? false : true; + } + + /** + * Add Person */ public function addPerson(Person $person = null): self { - $this->persons[] = $person; + $participation = new AccompanyingPeriodParticipation($this, $person); + $this->participations[] = $participation; return $this; } + /** + * Remove Person + */ public function removePerson(Person $person): void { - $this->persons->removeElement($person); + $participation = $this->participationsContainsPerson($person); + + if (! null === $participation) { + $participation->setEndDate(new \DateTimeImmutable('now')); + $this->participations->removeElement($participation); + } } + public function getClosingMotive(): ?ClosingMotive { return $this->closingMotive; @@ -335,11 +362,12 @@ class AccompanyingPeriod return false; } - foreach ($this->getPersons() as $p) { - if ($p === $person) { - $periods = $p->getAccompanyingPeriodsOrdered(); - return end($periods) === $this; - } + $participation = $this->participationsContainsPerson($person); + if (!null === $participation) + { + $person = $participation->getPerson(); + $periods = $person->getAccompanyingPeriodsOrdered(); + return end($periods) === $this; } return false; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php index 4a2fe3b44..9a807b179 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php @@ -44,22 +44,81 @@ class AccompanyingPeriodParticipation private $id; /** - * @ORM\ManyToOne(targetEntity=Person::class, - * inversedBy="accompanyingPeriods") + * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations") * @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false) */ private $person; /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, - * inversedBy="persons") + * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="participations") * @ORM\JoinColumn(name="accompanyingperiod_id", referencedColumnName="id", nullable=false) */ private $accompanyingPeriod; + /** + * @ORM\Column(type="date", nullable=false) + */ + private $startDate; + + /** + * @ORM\Column(type="date", nullable=true) + */ + private $endDate = null; + + public function __construct(AccompanyingPeriod $accompanyingPeriod, Person $person) + { + $this->startDate = new \DateTimeImmutable('now'); + $this->accompanyingPeriod = $accompanyingPeriod; + $this->person = $person; + } public function getId(): ?int { return $this->id; } + + public function getPerson(): ?Person + { + return $this->person; + } + + public function setPerson(?Person $person): self + { + $this->person = $person; + + return $this; + } + + public function getAccompanyingPeriod(): ?AccompanyingPeriod + { + return $this->accompanyingPeriod; + } + + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self + { + $this->accompanyingPeriod = $accompanyingPeriod; + + return $this; + } + + public function getStartDate(): ?\DateTimeInterface + { + return $this->startDate; + } + + /* + * public function setStartDate(\DateTimeInterface $startDate): self { $this->startDate = $startDate; return $this; } + */ + + public function getEndDate(): ?\DateTimeInterface + { + return $this->endDate; + } + + public function setEndDate(?\DateTimeInterface $endDate): self + { + $this->endDate = $endDate; + + return $this; + } } diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index bd89fbcea..e3a01a055 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -209,7 +209,7 @@ class Person implements HasCenterInterface * mappedBy="person", * cascade={"persist", "remove", "merge", "detach"}) */ - private $accompanyingPeriods; + private $accompanyingPeriodParticipations; /** * A remark over the person @@ -262,7 +262,7 @@ class Person implements HasCenterInterface */ public function __construct(\DateTime $opening = null) { - $this->accompanyingPeriods = new ArrayCollection(); + $this->accompanyingPeriodParticipations = new ArrayCollection(); $this->spokenLanguages = new ArrayCollection(); $this->addresses = new ArrayCollection(); $this->altNames = new ArrayCollection(); @@ -273,16 +273,39 @@ class Person implements HasCenterInterface $this->open(new AccompanyingPeriod($opening)); } - + /** - * Add AccompanyingPeriod + * This private function scan accompanyingPeriodParticipations Collection, + * searching for a given AccompanyingPeriod + */ + private function participationsContainAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): ?AccompanyingPeriodParticipation + { + foreach ($this->accompanyingPeriodParticipations as $participation) { + /** @var AccompanyingPeriodParticipation $participation */ + if ($accompanyingPeriod === $participation->getAccompanyingPeriod()) { + return $participation; + }} + + return null; + } + + /** + * This public function is the same but return only true or false + */ + public function containsAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool + { + return ($this->participationsContainAccompanyingPeriod($accompanyingPeriod)) ? false : true; + } + + /** + * Add AccompanyingPeriodParticipation * * @uses AccompanyingPeriod::addPerson */ public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): self { - $accompanyingPeriod->addPerson($this); - $this->accompanyingPeriods->add($accompanyingPeriod); + $participation = new AccompanyingPeriodParticipation($accompanyingPeriod, $this); + $this->accompanyingPeriodParticipations->add($participation); return $this; } @@ -292,7 +315,12 @@ class Person implements HasCenterInterface */ public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void { - $this->accompanyingPeriods->remove($accompanyingPeriod); + $participation = $this->participationsContainAccompanyingPeriod($accompanyingPeriod); + + if (! null === $participation) { + $participation->setEndDate(\DateTimeImmutable::class); + $this->accompanyingPeriodParticipations->removeElement($participation); + } } /** @@ -335,9 +363,10 @@ class Person implements HasCenterInterface return null; } - foreach ($this->accompanyingPeriods as $period) { - if ($period->isOpen()) { - return $period; + foreach ($this->accompanyingPeriodParticipations as $participation) { + /** @var AccompanyingPeriodParticipation $participation */ + if ($participation->getAccompanyingPeriod()->isOpen()) { + return $participation->getAccompanyingPeriod(); } } } @@ -353,19 +382,33 @@ class Person implements HasCenterInterface } /** - * Get AccompanyingPeriods Collection + * Get AccompanyingPeriods array */ - public function getAccompanyingPeriods() : Collection + public function getAccompanyingPeriods(): array { - return $this->accompanyingPeriods; + $accompanyingPeriods = []; + foreach ($this->accompanyingPeriodParticipations as $participation) + { + /** @var AccompanyingPeriodParticipation $participation */ + $accompanyingPeriods[] = $participation->getAccompanyingPeriod(); + } + return $accompanyingPeriods; + } + + /** + * Get AccompanyingPeriodParticipations Collection + */ + public function getAccompanyingPeriodParticipations(): Collection + { + return $this->accompanyingPeriodParticipations; } /** * Get the accompanying periods of a give person with the chronological order. */ - public function getAccompanyingPeriodsOrdered() : array + public function getAccompanyingPeriodsOrdered(): array { - $periods = $this->getAccompanyingPeriods()->toArray(); + $periods = $this->getAccompanyingPeriods(); //order by date : usort($periods, function($a, $b) { @@ -504,7 +547,7 @@ class Person implements HasCenterInterface * @param PersonAltName $altName * @return $this */ - public function removeAltName(PersonAltName $altName) + public function removeAltName(PersonAltName $altName) { if ($this->altNames->contains($altName)) { $altName->setPerson(null); diff --git a/src/Bundle/ChillPersonBundle/config/services/repository.yaml b/src/Bundle/ChillPersonBundle/config/services/repository.yaml index 50209b010..8cfaa8471 100644 --- a/src/Bundle/ChillPersonBundle/config/services/repository.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/repository.yaml @@ -12,3 +12,9 @@ services: factory: ['@doctrine.orm.entity_manager', getRepository] arguments: - 'Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive' + + Chill\PersonBundle\Repository\AccompanyingPeriodRepository: + class: Chill\PersonBundle\Repository\AccompanyingPeriodRepository + tags: [ doctrine.repository_service ] + arguments: + - '@Doctrine\Persistence\ManagerRegistry' diff --git a/src/Bundle/ChillPersonBundle/config/validation.yaml b/src/Bundle/ChillPersonBundle/config/validation.yaml index 814db0ee4..ba6d6b84d 100644 --- a/src/Bundle/ChillPersonBundle/config/validation.yaml +++ b/src/Bundle/ChillPersonBundle/config/validation.yaml @@ -27,9 +27,9 @@ Chill\PersonBundle\Entity\Person: gender: - NotNull: groups: [general, creation] - accompanyingPeriods: - - Valid: - traverse: true + #accompanyingPeriods: + # - Valid: + # traverse: true email: - Email: groups: [general, creation] diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php b/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php index c42da9874..9c379c4b0 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210331084527.php @@ -24,12 +24,16 @@ final class Version20210331084527 extends AbstractMigration $this->addSql('ALTER TABLE persons_accompanying_periods RENAME TO chill_person_accompanying_period_participation'); // 2 - // NOT NECCESSARY $this->addSql('CREATE SEQUENCE chill_person_accompanying_period_participation_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + // SERIAL automatically create sequence with NEXTVAL() $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD COLUMN id SERIAL NOT NULL PRIMARY KEY'); - // TO CHECK !! automatically complete missing values allowing not null clause - // but add strange "id serial (10) default nextval('chill_person_accompanying_period_participation_id_seq':: regclass )" in column definition + // drop NEXTVAL() in column definition + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ALTER id DROP DEFAULT'); // 3 + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD startDate DATE NOT NULL DEFAULT \'1970-01-01\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD endDate DATE DEFAULT NULL'); + + // 4 $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT fk_49a3871f217bbb47'); $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT fk_49a3871f550b0c53'); $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT FK_A59DF89F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); @@ -40,7 +44,7 @@ final class Version20210331084527 extends AbstractMigration public function down(Schema $schema) : void { - // 3 + // 4 $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT FK_A59DF89F217BBB47'); $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP CONSTRAINT FK_A59DF89F550B0C53'); $this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD CONSTRAINT fk_49a3871f217bbb47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); @@ -48,6 +52,10 @@ final class Version20210331084527 extends AbstractMigration $this->addSql('ALTER INDEX idx_a59df89f550b0c53 RENAME TO idx_49a3871f550b0c53'); $this->addSql('ALTER INDEX idx_a59df89f217bbb47 RENAME TO idx_49a3871f217bbb47'); + // 3 + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP startDate'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP endDate'); + // 2 $this->addSql('DROP SEQUENCE chill_person_accompanying_period_participation_id_seq CASCADE'); $this->addSql('ALTER TABLE chill_person_accompanying_period_participation DROP id'); From 25634ba12bc79f6058aac041ac5184f704a558c2 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 1 Apr 2021 11:06:36 +0200 Subject: [PATCH 18/22] Make some relations bidirectionnal --- .../Entity/AccompanyingPeriod.php | 75 +++++++++++++++---- .../Entity/AccompanyingPeriod/Comment.php | 4 +- .../Entity/AccompanyingPeriod/Resource.php | 5 +- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 915500392..2e8b02f0d 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -24,7 +24,9 @@ namespace Chill\PersonBundle\Entity; use Chill\MainBundle\Entity\Scope; use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment; use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Chill\ThirdPartyBundle\Entity\ThirdParty; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -74,7 +76,16 @@ class AccompanyingPeriod * @ORM\Column(type="text") */ private $remark = ''; - + + /** + * @var Collection + * + * @ORM\OneToMany(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Comment", + * mappedBy="accompanyingPeriod" + * ) + */ + private $comments; + /** * @var Collection * @@ -167,6 +178,15 @@ class AccompanyingPeriod */ private $confidential = false; + /** + * @var Collection + * + * @ORM\OneToMany( + * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Resource", + * mappedBy="accompanyingPeriod" + * ) + */ + private $resources; /** * AccompanyingPeriod constructor. @@ -254,14 +274,8 @@ class AccompanyingPeriod return false; } - - /** - * Set remark - * - * @param string $remark - * @return AccompanyingPeriod - */ - public function setRemark($remark) + + public function setRemark(string $remark): self { if ($remark === null) { $remark = ''; @@ -271,17 +285,29 @@ class AccompanyingPeriod return $this; } - - /** - * Get remark - * - * @return string - */ - public function getRemark() + + public function getRemark(): string { return $this->remark; } + public function getComments(): Collection + { + return $this->comments; + } + + public function addComment(Comment $comment): self + { + $this->comments[] = $comment; + + return $this; + } + + public function removeComment(Comment $comment): void + { + $this->comments->removeElement($comment); + } + /** * Get Participations Collection */ @@ -557,4 +583,21 @@ class AccompanyingPeriod { $this->scopes->removeElement($scope); } + + public function getResources(): Collection + { + return $this->resources; + } + + public function addResource(Resource $resource): self + { + $this->resources[] = $resource; + + return $this; + } + + public function removeResource(Resource $resource): void + { + $this->resources->removeElement($resource); + } } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php index 15b52a9dd..e8ecf3248 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php @@ -41,7 +41,9 @@ class Comment private $id; /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) + * @ORM\ManyToOne( + * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", + * inversedBy="comments") * @ORM\JoinColumn(nullable=false) */ private $accompanyingPeriod; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php index 90236f014..ec13fcad6 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php @@ -43,7 +43,10 @@ class Resource private $id; /** - * @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class) + * @ORM\ManyToOne( + * targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", + * inversedBy="resources" + * ) * @ORM\JoinColumn(nullable=false) */ private $accompanyingPeriod; From de240b099fecc28950c4e89f20d9cb0b86365693 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 2 Apr 2021 17:50:45 +0200 Subject: [PATCH 19/22] remove commented code in new repositories --- .../AccompanyingPeriod/CommentRepository.php | 30 +------------------ .../AccompanyingPeriod/OriginRepository.php | 29 +----------------- .../AccompanyingPeriod/ResourceRepository.php | 28 ----------------- ...ompanyingPeriodParticipationRepository.php | 28 ----------------- .../AccompanyingPeriodRepository.php | 28 ----------------- 5 files changed, 2 insertions(+), 141 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php index 8abda6903..b41e77591 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/CommentRepository.php @@ -38,33 +38,5 @@ class CommentRepository extends ServiceEntityRepository { parent::__construct($registry, Comment::class); } - - // /** - // * @return Comment[] Returns an array of Comment objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('c') - ->andWhere('c.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('c.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?Comment - { - return $this->createQueryBuilder('c') - ->andWhere('c.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ + } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php index c2283b859..6a5b28901 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/OriginRepository.php @@ -19,6 +19,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + namespace Chill\PersonBundle\Repository\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin; @@ -38,32 +39,4 @@ class OriginRepository extends ServiceEntityRepository parent::__construct($registry, Origin::class); } - // /** - // * @return Origin[] Returns an array of Origin objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('o') - ->andWhere('o.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('o.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?Origin - { - return $this->createQueryBuilder('o') - ->andWhere('o.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php index 0507d9b6d..46eaaaaa0 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/ResourceRepository.php @@ -39,32 +39,4 @@ class ResourceRepository extends ServiceEntityRepository parent::__construct($registry, Resource::class); } - // /** - // * @return Resource[] Returns an array of Resource objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('r') - ->andWhere('r.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('r.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?Resource - { - return $this->createQueryBuilder('r') - ->andWhere('r.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php index 8d767b6ab..fbe957ecf 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodParticipationRepository.php @@ -39,32 +39,4 @@ class AccompanyingPeriodParticipationRepository extends ServiceEntityRepository parent::__construct($registry, AccompanyingPeriodParticipation::class); } - // /** - // * @return AccompanyingPeriodParticipation[] Returns an array of AccompanyingPeriodParticipation objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('a') - ->andWhere('a.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('a.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?AccompanyingPeriodParticipation - { - return $this->createQueryBuilder('a') - ->andWhere('a.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php index 009793bdb..4bc9f92db 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodRepository.php @@ -39,32 +39,4 @@ class AccompanyingPeriodRepository extends ServiceEntityRepository parent::__construct($registry, AccompanyingPeriod::class); } - // /** - // * @return AccompanyingPeriod[] Returns an array of AccompanyingPeriod objects - // */ - /* - public function findByExampleField($value) - { - return $this->createQueryBuilder('a') - ->andWhere('a.exampleField = :val') - ->setParameter('val', $value) - ->orderBy('a.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; - } - */ - - /* - public function findOneBySomeField($value): ?AccompanyingPeriod - { - return $this->createQueryBuilder('a') - ->andWhere('a.exampleField = :val') - ->setParameter('val', $value) - ->getQuery() - ->getOneOrNullResult() - ; - } - */ } From 5bee607afb7dc02f451eea813dddc9d7ac21ba45 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 2 Apr 2021 19:21:44 +0200 Subject: [PATCH 20/22] fix migration review: improve up and down query --- .../migrations/Version20210326113045.php | 72 ++++--------------- 1 file changed, 15 insertions(+), 57 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php index 5113ccce2..68ad31667 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php @@ -23,26 +23,8 @@ final class Version20210326113045 extends AbstractMigration } /** - * === UP ===> - * - * Preup and postup functions backup datas and transform them - * before injecting them in the new many-to-many join table. * In these direction, there is no loss. */ - public function preUp(Schema $schema) : void - { - // extract datas - $query = "SELECT person_id, id as accompagnying_period_id FROM chill_person_accompanying_period WHERE person_id IS NOT NULL"; - $data = $this->connection->prepare($query); - $data->execute(); - foreach ($data as $row) - { - $personId = $row['person_id']; - $accompagnyingPeriodId = $row['accompagnying_period_id']; - $this->datas[] = "($personId, $accompagnyingPeriodId)"; - } - } - public function up(Schema $schema) : void { // create join table @@ -51,6 +33,10 @@ final class Version20210326113045 extends AbstractMigration $this->addSql('CREATE INDEX IDX_49A3871F550B0C53 ON persons_accompanying_periods (accompanyingperiod_id)'); $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT FK_49A3871F217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT FK_49A3871F550B0C53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + + // insert datas in new join table + $this->addSql('INSERT INTO persons_accompanying_periods (person_id, accompanyingperiod_id)' + . 'SELECT person_id, id as accompagnying_period_id FROM chill_person_accompanying_period WHERE person_id IS NOT NULL'); // drop column $this->addSql('DROP INDEX idx_64a4a621217bbb47'); @@ -58,55 +44,27 @@ final class Version20210326113045 extends AbstractMigration $this->addSql('ALTER TABLE chill_person_accompanying_period DROP person_id'); } - public function postUp(Schema $schema) : void - { - // insert datas in new join table - $SQL = "INSERT INTO persons_accompanying_periods (person_id, accompanyingperiod_id) VALUES " . implode(', ', $this->datas); - $this->connection->executeQuery($SQL); - } - - /** - * <=== DOWN === - * - * In predown and postdown we backup datas from jointable, and transform them - * before injecting them back in the many-to-one column 'person_id'. - * * The distinct clause makes that for each group of duplicates, it keeps only the first row in the returned result set. * Then we have only few lost datas. Lost datas: when many persons for one AccompanyingPeriod (keep only first person) */ - - public function preDown(Schema $schema) : void - { - // extract datas - $query = "SELECT DISTINCT ON (accompanyingperiod_id) accompanyingperiod_id AS id, person_id FROM persons_accompanying_periods ORDER BY id, person_id ASC"; - $data = $this->connection->prepare($query); - $data->execute(); - foreach ($data as $row) - { - $id = $row['id']; - $personId = $row['person_id']; - $this->datas[$id] = "$personId"; - } - } - public function down(Schema $schema) : void { - // drop join table - $this->addSql('DROP TABLE persons_accompanying_periods'); - // add column $this->addSql('ALTER TABLE chill_person_accompanying_period ADD person_id INT DEFAULT NULL'); $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT fk_64a4a621217bbb47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('CREATE INDEX idx_64a4a621217bbb47 ON chill_person_accompanying_period (person_id)'); - } - - public function postDown(Schema $schema) : void - { + // insert datas in existing table - foreach ($this->datas as $id => $personId) { - $SQL = "UPDATE chill_person_accompanying_period SET person_id='$personId' WHERE id='$id'"; - $this->connection->executeQuery($SQL); // CHECK if we have to execute query out of foreach loop. how ? - } + $this->addSql('UPDATE chill_person_accompanying_period AS ap ' + . 'SET person_id = jt.person_id ' + . 'FROM ( ' + . 'SELECT DISTINCT ON (accompanyingperiod_id) accompanyingperiod_id AS id, person_id FROM persons_accompanying_periods ' + . 'ORDER BY id, person_id ASC ' + . ') AS jt ' + . 'WHERE ap.id = jt.id'); + + // drop join table + $this->addSql('DROP TABLE persons_accompanying_periods'); } } From aa05223a4e0867244499866110a52610b90c0f83 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 2 Apr 2021 19:22:57 +0200 Subject: [PATCH 21/22] fix translation --- src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php | 5 +---- src/Bundle/ChillPersonBundle/translations/messages.fr.yml | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 2e8b02f0d..a7311f838 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -42,10 +42,7 @@ use Chill\MainBundle\Entity\User; */ class AccompanyingPeriod { - const INTENSITY = [ - 'occasional' => 'ponctuel', - 'regular' => 'régulier' - ]; + const INTENSITY = ['occasional', 'regular']; /** * @var integer diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index f5d1bb0f5..146aed9e0 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -281,7 +281,10 @@ person_admin: marital status explanation: > Configurer la liste des états civils. +# specific to accompanying period accompanying_period: dates: Période dates_from_%opening_date%: Ouvert depuis le %opening_date% dates_from_%opening_date%_to_%closing_date%: Ouvert du %opening_date% au %closing_date% +occasional: ponctuel +regular: régulier From cc40e7a99a10d5b17f76a1ffaff40a5da1c59b09 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 13 Apr 2021 15:31:04 +0200 Subject: [PATCH 22/22] fix sql migration syntax --- .../ChillPersonBundle/migrations/Version20210326113045.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php index 68ad31667..8ae60b739 100644 --- a/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210326113045.php @@ -35,7 +35,7 @@ final class Version20210326113045 extends AbstractMigration $this->addSql('ALTER TABLE persons_accompanying_periods ADD CONSTRAINT FK_49A3871F550B0C53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); // insert datas in new join table - $this->addSql('INSERT INTO persons_accompanying_periods (person_id, accompanyingperiod_id)' + $this->addSql('INSERT INTO persons_accompanying_periods (person_id, accompanyingperiod_id) ' . 'SELECT person_id, id as accompagnying_period_id FROM chill_person_accompanying_period WHERE person_id IS NOT NULL'); // drop column