Merge branch '_8_entity_parcours' into 'master'

WIP issue8 : entity parcours

See merge request Chill-Projet/chill-bundles!8
This commit is contained in:
Mathieu Jaumotte 2021-04-13 20:48:36 +00:00
commit 8a83e8ed22
31 changed files with 1814 additions and 346 deletions

View File

@ -3,7 +3,7 @@
/* /*
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -23,6 +23,7 @@
namespace Chill\PersonBundle\Controller; namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Privacy\PrivacyEvent; use Chill\PersonBundle\Privacy\PrivacyEvent;
use Doctrine\DBAL\Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Form\AccompanyingPeriodType; use Chill\PersonBundle\Form\AccompanyingPeriodType;
@ -32,6 +33,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface;
/** /**
@ -63,48 +65,38 @@ class AccompanyingPeriodController extends AbstractController
$this->validator = $validator; $this->validator = $validator;
} }
/** public function listAction(int $person_id): Response
* @param $person_id {
* @return Response
*/
public function listAction($person_id){
$person = $this->_getPerson($person_id); $person = $this->_getPerson($person_id);
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, [
'element_class' => AccompanyingPeriod::class, 'element_class' => AccompanyingPeriod::class,
'action' => 'list' 'action' => 'list'
)); ]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig', return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig', [
array('accompanying_periods' => $person->getAccompanyingPeriodsOrdered(), 'accompanying_periods' => $person->getAccompanyingPeriodsOrdered(),
'person' => $person)); 'person' => $person
]);
} }
/** public function createAction(int $person_id, Request $request): Response
* @param $person_id
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
*/
public function createAction($person_id, Request $request)
{ {
$person = $this->_getPerson($person_id); $person = $this->_getPerson($person_id);
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
'You are not allowed to update this person'); 'You are not allowed to update this person');
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime()); $accompanyingPeriod = new AccompanyingPeriod(new \DateTimeImmutable('now'));
$accompanyingPeriod->setClosingDate(new \DateTime()); $accompanyingPeriod->setClosingDate(new \DateTimeImmutable('now'));
$person->addAccompanyingPeriod( $accompanyingPeriod->addPerson($person);
$accompanyingPeriod); //or $person->addAccompanyingPeriod($accompanyingPeriod);
$form = $this->createForm( $form = $this->createForm(
AccompanyingPeriodType::class, AccompanyingPeriodType::class,
$accompanyingPeriod, $accompanyingPeriod, [
[
'period_action' => 'create', 'period_action' => 'create',
'center' => $person->getCenter() 'center' => $person->getCenter()
]); ]);
@ -114,7 +106,7 @@ class AccompanyingPeriodController extends AbstractController
$errors = $this->_validatePerson($person); $errors = $this->_validatePerson($person);
$flashBag = $this->get('session')->getFlashBag(); $flashBag = $this->get('session')->getFlashBag();
if ($form->isValid(array('Default', 'closed')) if ($form->isValid(['Default', 'closed'])
&& count($errors) === 0) { && count($errors) === 0) {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
@ -124,8 +116,11 @@ class AccompanyingPeriodController extends AbstractController
$this->get('translator')->trans( $this->get('translator')->trans(
'A period has been created.')); 'A period has been created.'));
return $this->redirect($this->generateUrl('chill_person_accompanying_period_list', return $this->redirect(
array('person_id' => $person->getId()))); $this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId()
]));
} else { } else {
$flashBag->add('error', $this->get('translator') $flashBag->add('error', $this->get('translator')
->trans('Error! Period not created!')); ->trans('Error! Period not created!'));
@ -136,57 +131,64 @@ class AccompanyingPeriodController extends AbstractController
} }
} }
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [
array( 'form' => $form->createView(),
'form' => $form->createView(), 'person' => $person,
'person' => $person, 'accompanying_period' => $accompanyingPeriod
'accompanying_period' => $accompanyingPeriod ]);
)
);
} }
/** /**
* @param $person_id * @throws Exception
* @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): Response
{
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$accompanyingPeriod = $em->getRepository('ChillPersonBundle:AccompanyingPeriod') /** @var AccompanyingPeriod $accompanyingPeriod */
->find($period_id); $accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($period_id);
if ($accompanyingPeriod === null) { if ($accompanyingPeriod === null) {
return $this->createNotFoundException("Period with id ".$period_id. throw $this->createNotFoundException("Period with id " . $period_id . " is not found");
" is not found");
} }
$person = $accompanyingPeriod->getPerson(); /** @var Person $person */
$person = $this->_getPerson($person_id);
// CHECK
if (! $accompanyingPeriod->containsPerson($person)) {
throw new Exception("Accompanying period " . $period_id . " does not contain person " . $person_id);
}
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
'You are not allowed to update this person'); 'You are not allowed to update this person');
$form = $this->createForm(AccompanyingPeriodType::class, $form = $this->createForm(AccompanyingPeriodType::class,
$accompanyingPeriod, array('period_action' => 'update', $accompanyingPeriod, [
'center' => $person->getCenter())); 'period_action' => 'update',
'center' => $person->getCenter()
]);
if ($request->getMethod() === 'POST') { if ($request->getMethod() === 'POST') {
$form->handleRequest($request); $form->handleRequest($request);
$errors = $this->_validatePerson($person); $errors = $this->_validatePerson($person);
$flashBag = $this->get('session')->getFlashBag(); $flashBag = $this->get('session')->getFlashBag();
if ($form->isValid(array('Default', 'closed')) if ($form->isValid(['Default', 'closed'])
&& count($errors) === 0) { && count($errors) === 0) {
$em->flush(); $em->flush();
$flashBag->add('success', $flashBag->add('success',
$this->get('translator')->trans( $this->get('translator')->trans('An accompanying period has been updated.'));
'An accompanying period has been updated.'));
return $this->redirect(
$this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId()
]));
return $this->redirect($this->generateUrl('chill_person_accompanying_period_list',
array('person_id' => $person->getId())));
} else { } else {
$flashBag->add('error', $this->get('translator') $flashBag->add('error', $this->get('translator')
->trans('Error when updating the period')); ->trans('Error when updating the period'));
@ -196,46 +198,42 @@ class AccompanyingPeriodController extends AbstractController
} }
} }
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [
array( 'form' => $form->createView(),
'form' => $form->createView(), 'person' => $person,
'person' => $person, 'accompanying_period' => $accompanyingPeriod
'accompanying_period' => $accompanyingPeriod ]);
) );
} }
/** /**
* @param $person_id
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
* @throws \Exception * @throws \Exception
*/ */
public function closeAction($person_id, Request $request) public function closeAction(int $person_id, Request $request): Response
{ {
$person = $this->_getPerson($person_id); $person = $this->_getPerson($person_id);
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, 'You are not allowed to update this person');
'You are not allowed to update this person');
if ($person->isOpen() === false) { if ($person->isOpen() === false) {
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', $this->get('translator') ->add('error', $this->get('translator')
->trans('Beware period is closed', ->trans('Beware period is closed', ['%name%' => $person->__toString()]
array('%name%' => $person->__toString()))); ));
return $this->redirect( return $this->redirect(
$this->generateUrl('chill_person_accompanying_period_list', array( $this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId() 'person_id' => $person->getId()
))); ]));
} }
$current = $person->getCurrentAccompanyingPeriod(); $current = $person->getCurrentAccompanyingPeriod();
$form = $this->createForm(AccompanyingPeriodType::class, $current, array( $form = $this->createForm(AccompanyingPeriodType::class, $current, [
'period_action' => 'close', 'period_action' => 'close',
'center' => $person->getCenter() 'center' => $person->getCenter()
)); ]);
if ($request->getMethod() === 'POST') { if ($request->getMethod() === 'POST') {
$form->handleRequest($request); $form->handleRequest($request);
@ -247,16 +245,18 @@ class AccompanyingPeriodController extends AbstractController
if (count($errors) === 0) { if (count($errors) === 0) {
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('success', $this->get('translator') ->add('success', $this->get('translator')
->trans('An accompanying period has been closed.', ->trans('An accompanying period has been closed.', [
array('%name%' => $person->__toString()))); '%name%' => $person->__toString()
]));
$this->getDoctrine()->getManager()->flush(); $this->getDoctrine()->getManager()->flush();
return $this->redirect( return $this->redirect(
$this->generateUrl('chill_person_accompanying_period_list', array( $this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId() 'person_id' => $person->getId()
)) ])
); );
} else { } else {
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', $this->get('translator') ->add('error', $this->get('translator')
@ -267,6 +267,7 @@ class AccompanyingPeriodController extends AbstractController
->add('info', $error->getMessage()); ->add('info', $error->getMessage());
} }
} }
} else { //if form is not valid } else { //if form is not valid
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', ->add('error',
@ -281,39 +282,34 @@ class AccompanyingPeriodController extends AbstractController
} }
} }
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [
array( 'form' => $form->createView(),
'form' => $form->createView(), 'person' => $person,
'person' => $person, 'accompanying_period' => $current
'accompanying_period' => $current ]);
));
} }
/** private function _validatePerson(Person $person): ConstraintViolationListInterface
* @param Person $person
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
*/
private function _validatePerson(Person $person)
{ {
$errors = $this->validator->validate($person, null, $errors = $this->validator->validate($person, null,
array('Default')); ['Default']);
$errors_accompanying_period = $this->validator->validate($person, null, // Can be disabled with config
array('accompanying_period_consistent')); if (false === $this->container->getParameter('chill_person.allow_multiple_simultaneous_accompanying_periods')) {
foreach($errors_accompanying_period as $error ) { $errors_accompanying_period = $this->validator->validate($person, null,
$errors->add($error); ['accompanying_period_consistent']);
foreach($errors_accompanying_period as $error ) {
$errors->add($error);
}
} }
return $errors; return $errors;
} }
/** public function openAction(int $person_id, Request $request): Response
* @param $person_id {
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
*/
public function openAction($person_id, Request $request) {
$person = $this->_getPerson($person_id); $person = $this->_getPerson($person_id);
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person, $this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
@ -324,19 +320,22 @@ class AccompanyingPeriodController extends AbstractController
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', $this->get('translator') ->add('error', $this->get('translator')
->trans('Error! Period %name% is not closed ; it can be open', ->trans('Error! Period %name% is not closed ; it can be open',
array('%name%' => $person->__toString()))); ['%name%' => $person->__toString()]
));
return $this->redirect( return $this->redirect(
$this->generateUrl('chill_person_accompanying_period_list', array( $this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId() 'person_id' => $person->getId()
))); ]));
} }
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime()); $accompanyingPeriod = new AccompanyingPeriod(new \DateTime());
$form = $this->createForm(AccompanyingPeriodType::class, $form = $this->createForm(AccompanyingPeriodType::class,
$accompanyingPeriod, array('period_action' => 'open', $accompanyingPeriod, [
'center' => $person->getCenter())); 'period_action' => 'open',
'center' => $person->getCenter()
]);
if ($request->getMethod() === 'POST') { if ($request->getMethod() === 'POST') {
$form->handleRequest($request); $form->handleRequest($request);
@ -348,16 +347,18 @@ class AccompanyingPeriodController extends AbstractController
if (count($errors) <= 0) { if (count($errors) <= 0) {
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('success', $this->get('translator') ->add('success', $this->get('translator')
->trans('An accompanying period has been opened.', ->trans('An accompanying period has been opened.',
array('%name%' => $person->__toString()))); ['%name%' => $person->__toString()]
));
$this->getDoctrine()->getManager()->flush(); $this->getDoctrine()->getManager()->flush();
return $this->redirect( return $this->redirect(
$this->generateUrl('chill_person_accompanying_period_list', array( $this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId() 'person_id' => $person->getId()
))); ]));
} else { } else {
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', $this->get('translator') ->add('error', $this->get('translator')
@ -368,27 +369,25 @@ class AccompanyingPeriodController extends AbstractController
->add('info', $error->getMessage()); ->add('info', $error->getMessage());
} }
} }
} else { // if errors in forms } else { // if errors in forms
$this->get('session')->getFlashBag() $this->get('session')->getFlashBag()
->add('error', $this->get('translator') ->add('error', $this->get('translator')
->trans('Period not opened : form is invalid')); ->trans('Period not opened : form is invalid')
);
} }
} }
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig', [
array('form' => $form->createView(), 'form' => $form->createView(),
'person' => $person, 'person' => $person,
'accompanying_period' => $accompanyingPeriod)); 'accompanying_period' => $accompanyingPeriod
]);
} }
/** public function reOpenAction(int $person_id, int $period_id, Request $request): Response
* @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)
{ {
/** @var Person $person */
$person = $this->_getPerson($person_id); $person = $this->_getPerson($person_id);
$criteria = Criteria::create(); $criteria = Criteria::create();
@ -405,7 +404,7 @@ class AccompanyingPeriodController extends AbstractController
$confirm = $request->query->getBoolean('confirm', false); $confirm = $request->query->getBoolean('confirm', false);
if ($confirm === true && $period->canBeReOpened()) { if ($confirm === true && $period->canBeReOpened($person)) {
$period->reOpen(); $period->reOpen();
$this->_validatePerson($person); $this->_validatePerson($person);
@ -415,13 +414,16 @@ class AccompanyingPeriodController extends AbstractController
$this->addFlash('success', $this->get('translator')->trans( $this->addFlash('success', $this->get('translator')->trans(
'The period has been re-opened')); 'The period has been re-opened'));
return $this->redirectToRoute('chill_person_accompanying_period_list', return $this->redirectToRoute('chill_person_accompanying_period_list', [
array('person_id' => $person->getId())); 'person_id' => $person->getId()
} elseif ($confirm === false && $period->canBeReOpened()) { ]);
return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', array(
} elseif ($confirm === false && $period->canBeReOpened($person)) {
return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', [
'period' => $period, 'period' => $period,
'person' => $person 'person' => $person
)); ]);
} else { } else {
return (new Response()) return (new Response())
->setStatusCode(Response::HTTP_BAD_REQUEST) ->setStatusCode(Response::HTTP_BAD_REQUEST)
@ -430,12 +432,10 @@ class AccompanyingPeriodController extends AbstractController
} }
/** /**
* * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* @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() $person = $this->getDoctrine()->getManager()
->getRepository('ChillPersonBundle:Person')->find($id); ->getRepository('ChillPersonBundle:Person')->find($id);

View File

@ -21,6 +21,7 @@
namespace Chill\PersonBundle\DataFixtures\ORM; namespace Chill\PersonBundle\DataFixtures\ORM;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
@ -195,6 +196,9 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
case 'maritalStatus': case 'maritalStatus':
$value = $this->getReference($value); $value = $this->getReference($value);
break; break;
case 'accompanyingPeriods':
$this->addAccompanyingPeriods($p, $value, $manager);
break;
} }
//try to add the data using the setSomething function, //try to add the data using the setSomething function,
@ -230,15 +234,15 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
private function getRandomAddress() private function getRandomAddress()
{ {
return (new Address()) return (new Address())
->setStreetAddress1($this->faker->streetAddress) ->setStreetAddress1($this->faker->streetAddress)
->setStreetAddress2( ->setStreetAddress2(
rand(0,9) > 5 ? $this->faker->streetAddress : '' rand(0,9) > 5 ? $this->faker->streetAddress : ''
) )
->setPostcode($this->getReference( ->setPostcode($this->getReference(
LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)] LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)]
)) ))
->setValidFrom($this->faker->dateTimeBetween('-5 years')) ->setValidFrom($this->faker->dateTimeBetween('-5 years'))
; ;
} }
private function getCountry($countryCode) private function getCountry($countryCode)
@ -254,19 +258,19 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
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']; 'ms_divorce', 'ms_legalco', 'ms_unknown'];
private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert", private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert", "Justin", "Brian",
"Compère", "Jean-de-Dieu", "Compère", "Jean-de-Dieu", "Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric",
"Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric", "Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou", "Vursuv", "Youssef" );
"Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou",
"Vursuv" ); private $firstNamesFemale = array("Svedana", "Sevlatina", "Irène", "Marcelle",
private $firstNamesFemale = array("Svedana", "Sevlatina","Irène", "Marcelle", "Corentine", "Alfonsine", "Caroline", "Solange", "Gostine", "Fatoumata", "Nicole",
"Corentine", "Alfonsine","Caroline","Solange","Gostine", "Fatoumata", "Groseille", "Chana", "Oxana", "Ivana", "Julie", "Tina", "Adèle" );
"Groseille", "Chana", "Oxana", "Ivana");
private $lastNames = array("Diallo", "Bah", "Gaillot", "Martin");
private $lastNames = array("Diallo", "Bah", "Gaillot");
private $lastNamesTrigrams = array("fas", "tré", "hu", 'blart', 'van', 'der', 'lin', 'den', private $lastNamesTrigrams = array("fas", "tré", "hu", 'blart', 'van', 'der', 'lin', 'den',
'ta', 'mi', 'gna', 'bol', 'sac', 'ré', 'jo', 'du', 'pont', 'cas', 'tor', 'rob', 'al', '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", 'ma', 'gone', 'car',"fu", "ka", "lot", "no", "va", "du", "bu", "su", "jau", "tte", 'sir',
"lo", 'to', "cho", "car", 'mo','zu', 'qi', 'mu'); "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);
@ -279,48 +283,101 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
private $peoples = array( private $peoples = array(
array( array(
'FirstName' => "Depardieu", 'LastName' => "Depardieu",
'LastName' => "Gérard", 'FirstName' => "Gérard",
'Birthdate' => "1948-12-27", 'Birthdate' => "1948-12-27",
'PlaceOfBirth' => "Châteauroux", 'PlaceOfBirth' => "Châteauroux",
'Gender' => Person::MALE_GENDER, 'Gender' => Person::MALE_GENDER,
'CountryOfBirth' => 'FR', 'CountryOfBirth' => 'FR',
'Nationality' => 'RU', 'Nationality' => 'RU',
'center' => 'centerA', '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( array(
//to have a person with same firstname as Gérard Depardieu //to have a person with same firstname as Gérard Depardieu
'FirstName' => "Depardieu", 'LastName' => "Depardieu",
'LastName' => "Jean", 'FirstName' => "Jean",
'Birthdate' => "1960-10-12", 'Birthdate' => "1960-10-12",
'CountryOfBirth' => 'FR', 'CountryOfBirth' => 'FR',
'Nationality' => 'FR', 'Nationality' => 'FR',
'center' => 'centerA', 'center' => 'centerA',
'maritalStatus' => 'ms_divorce' 'maritalStatus' => 'ms_divorce'
), ),
array( array(
//to have a person with same birthdate of Gérard Depardieu //to have a person with same birthdate of Gérard Depardieu
'FirstName' => 'Van Snick', 'LastName' => 'Van Snick',
'LastName' => 'Bart', 'FirstName' => 'Bart',
'Birthdate' => '1948-12-27', 'Birthdate' => '1948-12-27',
'center' => 'centerA', 'center' => 'centerA',
'maritalStatus' => 'ms_legalco' 'maritalStatus' => 'ms_legalco'
), ),
array( array(
//to have a woman with Depardieu as FirstName //to have a woman with Depardieu as FirstName
'FirstName' => 'Depardieu', 'LastName' => 'Depardieu',
'LastName' => 'Charline', 'FirstName' => 'Charline',
'Gender' => Person::FEMALE_GENDER, 'Gender' => Person::FEMALE_GENDER,
'center' => 'centerA', 'center' => 'centerA',
'maritalStatus' => 'ms_legalco' 'maritalStatus' => 'ms_legalco'
), ),
array( array(
//to have a special character in lastName //to have a special character in lastName
'FirstName' => 'Manço', 'LastName' => 'Manço',
'LastName' => 'Étienne', 'FirstName' => 'Étienne',
'center' => 'centerA', 'center' => 'centerA',
'maritalStatus' => 'ms_unknown' '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'
),
); );
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);
}
}
} }

View File

@ -50,24 +50,36 @@ class LoadPersonACL extends AbstractFixture implements OrderedFixtureInterface
case 'social': case 'social':
case 'direction': case 'direction':
printf("Adding CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE to %s permission group \n", $permissionsGroup->getName()); printf("Adding CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE to %s permission group \n", $permissionsGroup->getName());
$roleScopeUpdate = (new RoleScope()) $roleScopeUpdate = (new RoleScope())
->setRole('CHILL_PERSON_UPDATE') ->setRole('CHILL_PERSON_UPDATE')
->setScope(null); ->setScope(null);
$permissionsGroup->addRoleScope($roleScopeUpdate); $permissionsGroup->addRoleScope($roleScopeUpdate);
$roleScopeCreate = (new RoleScope()) $roleScopeCreate = (new RoleScope())
->setRole('CHILL_PERSON_CREATE') ->setRole('CHILL_PERSON_CREATE')
->setScope(null); ->setScope(null);
$permissionsGroup->addRoleScope($roleScopeCreate); $permissionsGroup->addRoleScope($roleScopeCreate);
$roleScopeDuplicate = (new RoleScope())
->setRole('CHILL_PERSON_DUPLICATE')
->setScope(null);
$permissionsGroup->addRoleScope($roleScopeDuplicate);
$roleScopeList = (new RoleScope()) $roleScopeList = (new RoleScope())
->setRole(PersonVoter::LISTS) ->setRole(PersonVoter::LISTS)
->setScope(null); ->setScope(null);
$permissionsGroup->addRoleScope($roleScopeList); $permissionsGroup->addRoleScope($roleScopeList);
$roleScopeStats = (new RoleScope()) $roleScopeStats = (new RoleScope())
->setRole(PersonVoter::STATS) ->setRole(PersonVoter::STATS)
->setScope(null); ->setScope(null);
$permissionsGroup->addRoleScope($roleScopeStats); $permissionsGroup->addRoleScope($roleScopeStats);
$manager->persist($roleScopeUpdate); $manager->persist($roleScopeUpdate);
$manager->persist($roleScopeCreate); $manager->persist($roleScopeCreate);
$manager->persist($roleScopeDuplicate);
break; break;
case 'administrative': case 'administrative':
printf("Adding CHILL_PERSON_SEE to %s permission group \n", $permissionsGroup->getName()); printf("Adding CHILL_PERSON_SEE to %s permission group \n", $permissionsGroup->getName());

View File

@ -57,6 +57,9 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
$this->handlePersonFieldsParameters($container, $config['person_fields']); $this->handlePersonFieldsParameters($container, $config['person_fields']);
$this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_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 = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader->load('services.yaml'); $loader->load('services.yaml');
$loader->load('services/widgets.yaml'); $loader->load('services/widgets.yaml');

View File

@ -104,8 +104,21 @@ class Configuration implements ConfigurationInterface
->canBeDisabled() ->canBeDisabled()
->children() ->children()
->append($this->addFieldNode('user')) ->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() //children for 'accompanying_person_fields', parent = array 'person_fields'
->end() // paccompanying_person_fields, parent = children of root ->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 ->end() // children of 'root', parent = root
; ;

View File

@ -3,7 +3,7 @@
/* /*
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -22,18 +22,28 @@
namespace Chill\PersonBundle\Entity; 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;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
/** /**
* AccompanyingPeriod * AccompanyingPeriod Class
* *
* @ORM\Entity() * @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository")
* @ORM\Table(name="chill_person_accompanying_period") * @ORM\Table(name="chill_person_accompanying_period")
*/ */
class AccompanyingPeriod class AccompanyingPeriod
{ {
const INTENSITY = ['occasional', 'regular'];
/** /**
* @var integer * @var integer
* *
@ -65,14 +75,22 @@ class AccompanyingPeriod
private $remark = ''; private $remark = '';
/** /**
* @var Person * @var Collection
* *
* @ORM\ManyToOne( * @ORM\OneToMany(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Comment",
* targetEntity="Chill\PersonBundle\Entity\Person", * mappedBy="accompanyingPeriod"
* inversedBy="accompanyingPeriods", * )
* cascade={"refresh"})
*/ */
private $person; private $comments;
/**
* @var Collection
*
* @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class,
* mappedBy="accompanyingPeriod",
* cascade={"persist", "remove", "merge", "detach"})
*/
private $participations;
/** /**
* @var AccompanyingPeriod\ClosingMotive * @var AccompanyingPeriod\ClosingMotive
@ -84,14 +102,88 @@ class AccompanyingPeriod
private $closingMotive = null; private $closingMotive = null;
/** /**
* The user making the accompanying * @ORM\ManyToOne(targetEntity=User::class)
* @var User
*
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
* @ORM\JoinColumn(nullable=true) * @ORM\JoinColumn(nullable=true)
*/ */
private $user; private $user;
/**
* @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;
/**
* @var Collection
*
* @ORM\OneToMany(
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Resource",
* mappedBy="accompanyingPeriod"
* )
*/
private $resources;
/** /**
* AccompanyingPeriod constructor. * AccompanyingPeriod constructor.
@ -101,6 +193,8 @@ class AccompanyingPeriod
*/ */
public function __construct(\DateTime $dateOpening) { public function __construct(\DateTime $dateOpening) {
$this->setOpeningDate($dateOpening); $this->setOpeningDate($dateOpening);
$this->participations = new ArrayCollection();
$this->scopes = new ArrayCollection();
} }
/** /**
@ -167,24 +261,18 @@ class AccompanyingPeriod
*/ */
public function isOpen(): bool public function isOpen(): bool
{ {
if ($this->getOpeningDate() > new \DateTime('now')) { if ($this->getOpeningDate() > new \DateTimeImmutable('now')) {
return false; return false;
} }
if ($this->getClosingDate() === null) { if ($this->getClosingDate() === null) {
return true; return true;
} else {
return false;
} }
return false;
} }
/** public function setRemark(string $remark): self
* Set remark
*
* @param string $remark
* @return AccompanyingPeriod
*/
public function setRemark($remark)
{ {
if ($remark === null) { if ($remark === null) {
$remark = ''; $remark = '';
@ -195,57 +283,93 @@ class AccompanyingPeriod
return $this; return $this;
} }
/** public function getRemark(): string
* Get remark
*
* @return string
*/
public function getRemark()
{ {
return $this->remark; return $this->remark;
} }
/** public function getComments(): Collection
* Set person.
*
* For consistency, you should use Person::addAccompanyingPeriod instead.
*
* @param Person $person
* @return AccompanyingPeriod
* @see Person::addAccompanyingPeriod
*/
public function setPerson(Person $person = null)
{ {
$this->person = $person; 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
*/
public function getParticipations(): Collection
{
return $this->participations;
}
/**
* 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
{
$participation = new AccompanyingPeriodParticipation($this, $person);
$this->participations[] = $participation;
return $this; return $this;
} }
/** /**
* Get person * Remove Person
*
* @return Person
*/ */
public function getPerson() public function removePerson(Person $person): void
{ {
return $this->person; $participation = $this->participationsContainsPerson($person);
if (! null === $participation) {
$participation->setEndDate(new \DateTimeImmutable('now'));
$this->participations->removeElement($participation);
}
} }
/**
* @return AccompanyingPeriod\ClosingMotive public function getClosingMotive(): ?ClosingMotive
*/
public function getClosingMotive()
{ {
return $this->closingMotive; return $this->closingMotive;
} }
/** public function setClosingMotive(ClosingMotive $closingMotive = null): self
* @param AccompanyingPeriod\ClosingMotive|null $closingMotive
* @return $this
*/
public function setClosingMotive(AccompanyingPeriod\ClosingMotive $closingMotive = null)
{ {
$this->closingMotive = $closingMotive; $this->closingMotive = $closingMotive;
return $this; return $this;
} }
@ -253,24 +377,28 @@ class AccompanyingPeriod
* If the period can be reopened. * If the period can be reopened.
* *
* This function test if the period is closed and if the period is the last * This function test if the period is closed and if the period is the last
* for the associated person * for the given person
*
* @return boolean
*/ */
public function canBeReOpened() public function canBeReOpened(Person $person): bool
{ {
if ($this->isOpen() === true) { if ($this->isOpen() === true) {
return false; return false;
} }
$periods = $this->getPerson()->getAccompanyingPeriodsOrdered(); $participation = $this->participationsContainsPerson($person);
if (!null === $participation)
{
$person = $participation->getPerson();
$periods = $person->getAccompanyingPeriodsOrdered();
return end($periods) === $this;
}
return end($periods) === $this; return false;
} }
/** /**
*/ */
public function reOpen() public function reOpen(): void
{ {
$this->setClosingDate(null); $this->setClosingDate(null);
$this->setClosingMotive(null); $this->setClosingMotive(null);
@ -308,18 +436,11 @@ class AccompanyingPeriod
} }
} }
/**
* @return User|null
*/
function getUser(): ?User function getUser(): ?User
{ {
return $this->user; return $this->user;
} }
/**
* @param User $user
* @return AccompanyingPeriod
*/
function setUser(User $user): self function setUser(User $user): self
{ {
$this->user = $user; $this->user = $user;
@ -327,4 +448,153 @@ class AccompanyingPeriod
return $this; return $this;
} }
public function getOrigin(): Origin
{
return $this->origin;
}
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);
}
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);
}
} }

View File

@ -1,13 +1,15 @@
<?php <?php
/* /*
* Chill is a software for social workers
* *
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop> * Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * 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 * 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -28,8 +30,8 @@ use Doctrine\Common\Collections\ArrayCollection;
* ClosingMotive give an explanation why we closed the Accompanying period * ClosingMotive give an explanation why we closed the Accompanying period
* *
* @ORM\Entity( * @ORM\Entity(
* repositoryClass="Chill\PersonBundle\Repository\ClosingMotiveRepository") * repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository")
* @ORM\Table(name="chill_person_closingmotive") * @ORM\Table(name="chill_person_accompanying_period_closingmotive")
*/ */
class ClosingMotive class ClosingMotive
{ {

View File

@ -0,0 +1,154 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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="Chill\PersonBundle\Entity\AccompanyingPeriod",
* inversedBy="comments")
* @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;
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -0,0 +1,132 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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="Chill\PersonBundle\Entity\AccompanyingPeriod",
* inversedBy="resources"
* )
* @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;
}
}

View File

@ -0,0 +1,124 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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="accompanyingPeriodParticipations")
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
*/
private $person;
/**
* @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;
}
}

View File

@ -42,7 +42,6 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
* name="person_names", * name="person_names",
* columns={"firstName", "lastName"} * columns={"firstName", "lastName"}
* )}) * )})
* sf4 check index name
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks()
*/ */
class Person implements HasCenterInterface class Person implements HasCenterInterface
@ -216,14 +215,13 @@ class Person implements HasCenterInterface
/** /**
* The person's accompanying periods (when the person was accompanied by the center) * The person's accompanying periods (when the person was accompanied by the center)
* @var ArrayCollection * @var Collection
* *
* @ORM\OneToMany( * @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class,
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod",
* mappedBy="person", * mappedBy="person",
* cascade={"persist", "remove", "merge", "detach"}) * cascade={"persist", "remove", "merge", "detach"})
*/ */
private $accompanyingPeriods; //TO-CHANGE in accompanyingHistory private $accompanyingPeriodParticipations;
/** /**
* A remark over the person * A remark over the person
@ -275,7 +273,7 @@ class Person implements HasCenterInterface
*/ */
public function __construct(\DateTime $opening = null) public function __construct(\DateTime $opening = null)
{ {
$this->accompanyingPeriods = new ArrayCollection(); $this->accompanyingPeriodParticipations = new ArrayCollection();
$this->spokenLanguages = new ArrayCollection(); $this->spokenLanguages = new ArrayCollection();
$this->addresses = new ArrayCollection(); $this->addresses = new ArrayCollection();
$this->altNames = new ArrayCollection(); $this->altNames = new ArrayCollection();
@ -289,21 +287,52 @@ class Person implements HasCenterInterface
} }
/** /**
* @param AccompanyingPeriod $accompanyingPeriod * This private function scan accompanyingPeriodParticipations Collection,
* @uses AccompanyingPeriod::setPerson * searching for a given AccompanyingPeriod
*/ */
public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) private function participationsContainAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): ?AccompanyingPeriodParticipation
{ {
$accompanyingPeriod->setPerson($this); foreach ($this->accompanyingPeriodParticipations as $participation) {
$this->accompanyingPeriods->add($accompanyingPeriod); /** @var AccompanyingPeriodParticipation $participation */
if ($accompanyingPeriod === $participation->getAccompanyingPeriod()) {
return $participation;
}}
return null;
} }
/** /**
* @param AccompanyingPeriod $accompanyingPeriod * This public function is the same but return only true or false
*/ */
public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) public function containsAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
{ {
$this->accompanyingPeriods->remove($accompanyingPeriod); return ($this->participationsContainAccompanyingPeriod($accompanyingPeriod)) ? false : true;
}
/**
* Add AccompanyingPeriodParticipation
*
* @uses AccompanyingPeriod::addPerson
*/
public function addAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): self
{
$participation = new AccompanyingPeriodParticipation($accompanyingPeriod, $this);
$this->accompanyingPeriodParticipations->add($participation);
return $this;
}
/**
* Remove AccompanyingPeriod
*/
public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void
{
$participation = $this->participationsContainAccompanyingPeriod($accompanyingPeriod);
if (! null === $participation) {
$participation->setEndDate(\DateTimeImmutable::class);
$this->accompanyingPeriodParticipations->removeElement($participation);
}
} }
/** /**
@ -315,10 +344,8 @@ class Person implements HasCenterInterface
* For closing a file, @see this::close * For closing a file, @see this::close
* *
* To check if the Person and its accompanying period is consistent, use validation. * 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->proxyAccompanyingPeriodOpenState = true;
$this->addAccompanyingPeriod($accompanyingPeriod); $this->addAccompanyingPeriod($accompanyingPeriod);
@ -332,28 +359,26 @@ class Person implements HasCenterInterface
* *
* To check if the Person and its accompanying period are consistent, use validation. * 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. * @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; $this->proxyAccompanyingPeriodOpenState = false;
} }
/** /**
* Return the opened accompanying period. * Return the opened accompanying period.
*
* @return AccompanyingPeriod
*/ */
public function getOpenedAccompanyingPeriod() public function getOpenedAccompanyingPeriod() : AccompanyingPeriod
{ {
if ($this->isOpen() === false) { if ($this->isOpen() === false) {
return null; return null;
} }
foreach ($this->accompanyingPeriods as $period) { foreach ($this->accompanyingPeriodParticipations as $participation) {
if ($period->isOpen()) { /** @var AccompanyingPeriodParticipation $participation */
return $period; if ($participation->getAccompanyingPeriod()->isOpen()) {
return $participation->getAccompanyingPeriod();
} }
} }
} }
@ -361,31 +386,41 @@ class Person implements HasCenterInterface
/** /**
* Returns the opened accompanying period. * Returns the opened accompanying period.
* *
* @return AccompanyingPeriod
* @deprecated since 1.1 use `getOpenedAccompanyingPeriod instead * @deprecated since 1.1 use `getOpenedAccompanyingPeriod instead
*/ */
public function getCurrentAccompanyingPeriod() public function getCurrentAccompanyingPeriod() : AccompanyingPeriod
{ {
return $this->getOpenedAccompanyingPeriod(); return $this->getOpenedAccompanyingPeriod();
} }
/** /**
* @return ArrayCollection * Get AccompanyingPeriods array
*/ */
public function getAccompanyingPeriods() public function getAccompanyingPeriods(): array
{ {
return $this->accompanyingPeriods; $accompanyingPeriods = [];
foreach ($this->accompanyingPeriodParticipations as $participation)
{
/** @var AccompanyingPeriodParticipation $participation */
$accompanyingPeriods[] = $participation->getAccompanyingPeriod();
}
return $accompanyingPeriods;
} }
/** /**
* Get the accompanying periods of a give person with the * Get AccompanyingPeriodParticipations Collection
* chronological order.
*
* @return AccompanyingPeriod[]
*/ */
public function getAccompanyingPeriodsOrdered() public function getAccompanyingPeriodParticipations(): Collection
{ {
$periods = $this->getAccompanyingPeriods()->toArray(); return $this->accompanyingPeriodParticipations;
}
/**
* Get the accompanying periods of a give person with the chronological order.
*/
public function getAccompanyingPeriodsOrdered(): array
{
$periods = $this->getAccompanyingPeriods();
//order by date : //order by date :
usort($periods, function($a, $b) { usort($periods, function($a, $b) {
@ -418,11 +453,9 @@ class Person implements HasCenterInterface
} }
/** /**
* check if the person is opened * Check if the person is opened
*
* @return boolean
*/ */
public function isOpen() public function isOpen() : bool
{ {
foreach ($this->getAccompanyingPeriods() as $period) { foreach ($this->getAccompanyingPeriods() as $period) {
if ($period->isOpen()) { if ($period->isOpen()) {
@ -1109,4 +1142,15 @@ class Person implements HasCenterInterface
return true; return true;
} }
public function getFullnameCanonical() : string
{
return $this->fullnameCanonical;
}
public function setFullnameCanonical($fullnameCanonical) : Person
{
$this->fullnameCanonical = $fullnameCanonical;
return $this;
}
} }

View File

@ -11,7 +11,7 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive; use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension; use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\Options;
use Chill\PersonBundle\Repository\ClosingMotiveRepository; use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository;
/** /**
* Class ClosingMotivePickerType * Class ClosingMotivePickerType

View File

@ -1,11 +1,15 @@
<?php <?php
/* /*
* Copyright (C) 2020 Champs-Libres <info@champs-libres.coop> * Chill is a software for social workers
*
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as
* the Free Software Foundation, either version 3 of the License, or * published by the Free Software Foundation, either version 3 of the
* (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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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 * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\PersonBundle\Repository;
namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
@ -39,13 +44,13 @@ class ClosingMotiveRepository extends EntityRepository
$rsm->addRootEntityFromClassMetadata($this->getClassName(), 'cm'); $rsm->addRootEntityFromClassMetadata($this->getClassName(), 'cm');
$sql = "SELECT ".(string) $rsm." $sql = "SELECT ".(string) $rsm."
FROM chill_person_closingmotive AS cm FROM chill_person_accompanying_period_closingmotive AS cm
WHERE WHERE
active IS TRUE "; active IS TRUE ";
if ($onlyLeaf) { if ($onlyLeaf) {
$sql .= "AND cm.id NOT IN ( $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
)"; )";
} }

View File

@ -0,0 +1,42 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -5,6 +5,9 @@
{% block title %}{{ 'Person accompanying period - %name%'|trans({ '%name%' : person.__toString}) }}{% endblock title %} {% block title %}{{ 'Person accompanying period - %name%'|trans({ '%name%' : person.__toString}) }}{% endblock title %}
{% block personcontent %} {% block personcontent %}
<h1>{{ 'Accompanying period list'|trans }}</h1>
<table class="rounded"> <table class="rounded">
<thead> <thead>
<tr> <tr>
@ -68,7 +71,7 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if accompanying_period.canBeReOpened == true %} {% if accompanying_period.canBeReOpened(person) == true %}
<li> <li>
<a href="{{ path('chill_person_accompanying_period_re_open', {'person_id' : person.id, 'period_id' : accompanying_period.id } ) }}" class="sc-button bt-create change-icon has-hidden"> <a href="{{ path('chill_person_accompanying_period_re_open', {'person_id' : person.id, 'period_id' : accompanying_period.id } ) }}" class="sc-button bt-create change-icon has-hidden">
<i class="fa fa-unlock" aria-hidden="true"></i><span class="show-on-hover">{{'Re-open accompanying period'|trans }}</span> <i class="fa fa-unlock" aria-hidden="true"></i><span class="show-on-hover">{{'Re-open accompanying period'|trans }}</span>

View File

@ -19,7 +19,7 @@ services:
arguments: arguments:
$translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper' $translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper'
$chillEntityRenderExtension: '@Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension' $chillEntityRenderExtension: '@Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension'
$closingMotiveRepository: '@Chill\PersonBundle\Repository\ClosingMotiveRepository' $closingMotiveRepository: '@Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository'
tags: tags:
- { name: form.type, alias: closing_motive } - { name: form.type, alias: closing_motive }

View File

@ -7,8 +7,14 @@ services:
- 'Chill\PersonBundle\Entity\Person' - 'Chill\PersonBundle\Entity\Person'
Chill\PersonBundle\Repository\PersonRepository: '@chill.person.repository.person' Chill\PersonBundle\Repository\PersonRepository: '@chill.person.repository.person'
Chill\PersonBundle\Repository\ClosingMotiveRepository: Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository:
class: Chill\PersonBundle\Repository\ClosingMotiveRepository class: Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository
factory: ['@doctrine.orm.entity_manager', getRepository] factory: ['@doctrine.orm.entity_manager', getRepository]
arguments: arguments:
- 'Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive' - 'Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive'
Chill\PersonBundle\Repository\AccompanyingPeriodRepository:
class: Chill\PersonBundle\Repository\AccompanyingPeriodRepository
tags: [ doctrine.repository_service ]
arguments:
- '@Doctrine\Persistence\ManagerRegistry'

View File

@ -27,9 +27,9 @@ Chill\PersonBundle\Entity\Person:
gender: gender:
- NotNull: - NotNull:
groups: [general, creation] groups: [general, creation]
accompanyingPeriods: #accompanyingPeriods:
- Valid: # - Valid:
traverse: true # traverse: true
email: email:
- Email: - Email:
groups: [general, creation] groups: [general, creation]

View File

@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Change model relation between Person and AccompagnyingPeriod
* Migrate datas into new join table
*
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
final class Version20210326113045 extends AbstractMigration
{
private $datas = [];
public function getDescription() : string
{
return 'Change model relation between Person and AccompagnyingPeriod, without losing datas when going up';
}
/**
* In these direction, there is no loss.
*/
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');
// 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');
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT fk_64a4a621217bbb47');
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP 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 down(Schema $schema) : void
{
// 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)');
// insert datas in existing table
$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');
}
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add AccompanyingPeriod Origin table
*
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
final class Version20210329090904 extends AbstractMigration
{
public function getDescription() : string
{
return 'Add AccompanyingPeriod Origin table';
}
public function up(Schema $schema) : void
{
$this->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');
}
}

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add AccompanyingPeriod Comment and Resource tables
*
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
final class Version20210329113152 extends AbstractMigration
{
public function getDescription() : string
{
return 'Add AccompanyingPeriod Comment and Resource tables';
}
public function up(Schema $schema) : void
{
$this->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');
}
}

View File

@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Complete accompanying period table
*
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
final class Version20210329144338 extends AbstractMigration
{
public function getDescription() : string
{
return 'Complete AccompanyingPeriod table';
}
public function up(Schema $schema) : void
{
$this->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');
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Rename table closinmotive
*
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
final class Version20210330164922 extends AbstractMigration
{
public function getDescription() : string
{
return 'Rename table closinmotive';
}
public function up(Schema $schema) : void
{
$this->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');
}
}

View File

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Transform join table between Person and AccompanyingPeriod in Doctrine entity
*/
final class Version20210331084527 extends AbstractMigration
{
public function getDescription() : string
{
return 'Transform join table between Person and AccompanyingPeriod in Doctrine entity';
}
public function up(Schema $schema) : void
{
// 1
$this->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
// SERIAL automatically create sequence with NEXTVAL()
$this->addSql('ALTER TABLE chill_person_accompanying_period_participation ADD COLUMN id SERIAL NOT NULL PRIMARY KEY');
// 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');
$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
{
// 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');
$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');
// 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');
// 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)');
}
}

View File

@ -285,7 +285,10 @@ person_admin:
marital status explanation: > marital status explanation: >
Configurer la liste des états civils. Configurer la liste des états civils.
# specific to accompanying period
accompanying_period: accompanying_period:
dates: Période dates: Période
dates_from_%opening_date%: Ouvert depuis le %opening_date% dates_from_%opening_date%: Ouvert depuis le %opening_date%
dates_from_%opening_date%_to_%closing_date%: Ouvert du %opening_date% au %closing_date% dates_from_%opening_date%_to_%closing_date%: Ouvert du %opening_date% au %closing_date%
occasional: ponctuel
regular: régulier

View File

@ -10,7 +10,7 @@
'Opening date can not be null': 'La date d''ouverure ne peut être nulle' '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 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' '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% 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: +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' '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'