diff --git a/Controller/HistoryController.php b/Controller/HistoryController.php new file mode 100644 index 000000000..d89eefc45 --- /dev/null +++ b/Controller/HistoryController.php @@ -0,0 +1,266 @@ +_getPerson($id); + + if ($person === null) { + return $this->createNotFoundException('Person not found'); + } + + return $this->render('CLChillPersonBundle:History:list.html.twig', + array('histories' => $person->getHistoriesOrdered(), + 'person' => $person)); + + } + + public function updateAction($historyId){ + + } + + public function closeAction($id) { + $person = $this->_getPerson($id); + + if ($person === null) { + return $this->createNotFoundException('Person not found'); + } + + if ($person->isOpen() === false) { + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.close.is_not_open', + array('%name%' => $person->__toString()))); + + return $this->redirect( + $this->generateUrl('chill_person_history_list', array( + 'id' => $person->getId() + ))); + } + + $current = $person->getCurrentHistory(); + + $container = array( + 'dateClosing' => new \DateTime(), + 'motive' => null, + 'texto' => $current->getMemo()); + + + + $form = $this->createFormBuilder($container) + ->add('dateClosing', 'date', array( + 'data' => new \DateTime() + )) + ->add('motive', 'choice', array( + 'choices' => $this->_getMotive(), + 'empty_value' => 'views.Person.close.select_a_motive' + )) + ->add('texto', 'textarea', array( + 'required' => false + )) + ->getForm(); + + $request = $this->getRequest(); + + if ($request->getMethod() === 'POST') { + $form->handleRequest($request); + + if ($form->isValid()){ + + + + $person->close($form['dateClosing']->getData(), + $form['motive']->getData(), + $form['texto']->getData()); + + + $errors = $this->_validatePerson($person); + + + + if (count($errors) === 0) { + $this->get('session')->getFlashBag() + ->add('success', $this->get('translator') + ->trans('controller.Person.history.close.done', + array('%name%' => $person->__toString()))); + + $this->getDoctrine()->getManager()->flush(); + + return $this->redirect( + $this->generateUrl('chill_person_history_list', array( + 'id' => $person->getId() + )) + ); + } else { + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.close.error')); + + foreach ($errors as $error) { + $this->get('session')->getFlashBag() + ->add('info', $error->getMessage()); + } + + + + + } + + } else { //if form is not valid + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.close.error_in_form')); + } + } + + + + + + return $this->render('CLChillPersonBundle:History:close.html.twig', + array( + 'form' => $form->createView(), + 'person' => $person, + 'history' => $current + )); + } + + /** + * + * @param CL\Chill\PersonBundle\Entity\Person $person + * @return \Symfony\Component\Validator\ConstraintViolationListInterface + */ + private function _validatePerson(Person $person) { + $errors = $this->get('validator')->validate($person, + array('Default')); + $errors_history = $this->get('validator')->validate($person, + array('history_consistent')); + + foreach($errors_history as $error ) { + $errors->add($error); + } + + return $errors; + } + + + public function openAction($id) { + $person = $this->_getPerson($id); + + if ($person === null) { + return $this->createNotFoundException('Person not found'); + } + + if ($person->isOpen() === true) { + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.open.is_not_closed', + array('%name%' => $person->__toString()))); + + return $this->redirect( + $this->generateUrl('chill_person_history_list', array( + 'id' => $person->getId() + ))); + } + + $current = $person->getCurrentHistory(); + + $container = array( + 'dateOpening' => new \DateTime(), + 'texto' => null); + + + + $form = $this->createFormBuilder($container) + ->add('dateOpening', 'date', array( + 'data' => new \DateTime() + )) + ->add('texto', 'textarea', array( + 'required' => false + )) + ->getForm(); + + $request = $this->getRequest(); + + if ($request->getMethod() === 'POST') { + $form->handleRequest($request); + + if ($form->isValid()) { + + $person->open($form['dateOpening']->getData(), + $form['texto']->getData()); + + + $errors = $this->_validatePerson($person); + + if (count($errors) <= 0) { + $this->get('session')->getFlashBag() + ->add('success', $this->get('translator') + ->trans('controller.Person.history.open.done', + array('%name%' => $person->__toString()))); + + $this->getDoctrine()->getManager()->flush(); + + return $this->redirect( + $this->generateUrl('chill_person_history_list', array( + 'id' => $person->getId() + )) + ); + } else { + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.open.error')); + + foreach ($errors as $error) { + $this->get('session')->getFlashBag() + ->add('info', $error->getMessage()); + } + } + + } else { // if errors in forms + $this->get('session')->getFlashBag() + ->add('danger', $this->get('translator') + ->trans('controller.Person.history.open.error_in_form')); + } + + } + + + + + + return $this->render('CLChillPersonBundle:History:open.html.twig', + array( + 'form' => $form->createView(), + 'person' => $person, + 'history' => $current + )); + } + + private function _getMotive() { + $motivesArray = $this->get('service_container') + ->getParameter('person.history.close.motives'); + + $a = array(); + + foreach ($motivesArray as $key => $params ) { + $a[$key] = $params['label']; + } + + return $a; + + } + + private function _getPerson($id) { + return $this->getDoctrine()->getManager() + ->getRepository('CLChillPersonBundle:Person') + ->find($id); + } + +} diff --git a/Entity/Person.php b/Entity/Person.php index f3e6d54f5..fcebf208d 100644 --- a/Entity/Person.php +++ b/Entity/Person.php @@ -3,6 +3,7 @@ namespace CL\Chill\PersonBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Validator\ExecutionContextInterface; /** * Person @@ -87,14 +88,168 @@ ou une valeur vide lorsque la donnée nest pas connue*/ private $email = ''; /** - * @var \Doctrine\Common\Collections\Collection + * @var \CL\Chill\MainBundle\Entity\Country */ private $countryOfBirth; /** - * @var \Doctrine\Common\Collections\Collection + * @var \CL\Chill\MainBundle\Entity\Country */ - private $nationality; + private $nationality; + + /** + * + * @var \Doctrine\Common\Collections\ArrayCollection + */ + private $history; + + /** + * + * @var boolean + */ + private $proxyHistoryOpenState = false; + + + public function __construct(\DateTime $opening = null) { + $this->history = new \Doctrine\Common\Collections\ArrayCollection(); + + if ($opening === null) { + $opening = new \DateTime(); + } + + $this->open($opening); + } + + /** + * + * @param \CL\Chill\PersonBundle\Entity\PersonHistoryFile $history + * @uses PersonHistoryFile::setPerson + */ + public function addHistoryFile(PersonHistoryFile $history) { + $history->setPerson($this); + $this->history->add($history); + } + + /** + * set the Person file as open at the given date. + * + * For updating a opening's date, you should update PersonHistoryFile instance + * directly. + * + * For closing a file, @see this::close + * + * To check if the Person and his history is consistent, use validation. + * + * @param \DateTime $date + */ + public function open(\DateTime $date, $memo = '') { + $history = new PersonHistoryFile($date); + $history->setMemo($memo); + $this->proxyHistoryOpenState = true; + $this->addHistoryFile($history); + } + + /** + * + * Set the Person file as closed at the given date. + * + * For update a closing date, you should update PersonHistoryFile instance + * directly. + * + * To check if the Person and his history are consistent, use validation. + * + * @param \DateTime $date + * @param string $motive + * @param string $memo + * @throws \Exception if two lines of history are open. + */ + public function close(\DateTime $date, $motive, $memo = '') { + $histories = $this->history; + + $found = false; + + foreach ($histories as $history) { + if ($history->isOpen()) { + + if ($found === true) { + throw new \Exception('two open line in history were found. This should not happen.'); + } + + $history->setDateClosing($date); + $history->setMotive($motive); + $history->setMemo($memo); + $this->proxyHistoryOpenState = false; + $found = true; + } + } + } + + /** + * + * @return null|PersonHistoryFile + */ + public function getCurrentHistory() { + if ($this->proxyHistoryOpenState === false) { + return null; + } + + foreach ($this->history as $history) { + if ($history->isOpen()) { + return $history; + } + } + } + + /** + * + * @return \Doctrine\Common\Collections\ArrayCollection + */ + public function getHistories() { + return $this->history; + } + + /** + * + * @return PersonHistoryFile[] + */ + public function getHistoriesOrdered() { + $histories = $this->getHistories()->toArray(); + + //order by date : + usort($histories, function($a, $b) { + + $dateA = $a->getDateOpening(); + $dateB = $b->getDateOpening(); + + if ($dateA == $dateB) { + $dateEA = $a->getDateClosing(); + $dateEB = $b->getDateClosing(); + + if ($dateEA == $dateEB) { + return 0; + } + + if ($dateEA < $dateEB) { + return -1; + } else { + return +1; + } + } + + if ($dateA < $dateB) { + return -1 ; + } else { + return 1; + } + }); + + + return $histories; + } + + public function isOpen() { + return $this->proxyHistoryOpenState; + } /** * Get id @@ -433,4 +588,110 @@ ou une valeur vide lorsque la donnée nest pas connue*/ public function __toString() { return $this->getLabel(); } + + + + // VALIDATION + + + public function isHistoryValid(ExecutionContextInterface $context) { + $r = $this->checkHistoryIsNotCovering(); + + + if ($r !== true) { + + if ($r['result'] === self::ERROR_OPENING_NOT_CLOSED_IS_BEFORE_NEW_LINE) { + $context->addViolationAt('history', + 'validation.Person.constraint.history.open_history_without_closing', + array() ); + return; + } + + $context->addViolationAt('history', + 'validation.Person.constraint.history.opening_is_before_closing', + array( + '%dateOpening%' => $r['dateOpening']->format('d-m-Y'), + '%dateClosing%' => $r['dateClosing']->format('d-m-Y'), + '%date%' => $r['date']->format('d-m-Y') + ) + ); + + + + } + } + + + + const ERROR_OPENING_IS_INSIDE_CLOSING = 1; + const ERROR_OPENING_NOT_CLOSED_IS_BEFORE_NEW_LINE = 2; + const ERROR_OPENING_NOT_CLOSE_IS_INSIDE_CLOSED_HISTORY_LINE = 3; + + public function checkHistoryIsNotCovering() { + + $histories = $this->getHistoriesOrdered(); + + + //check order : + $oldOpening = array(); + $oldClosing = array(); + $i = 0; + + foreach ($histories as $key => $history) { + //history is open : we must check the arent any history after + if ($history->isOpen()) { + foreach ($histories as $subKey => $against) { + //if we are checking the same, continue + if ($key === $subKey) { + continue; + } + + if ($history->getDateOpening() > $against->getDateOpening() + && $history->getDateOpening() < $against->getDateOpening()) { + // the history date opening is inside another opening line + return array( + 'result' => self::ERROR_OPENING_NOT_CLOSE_IS_INSIDE_CLOSED_HISTORY_LINE, + 'dateOpening' => $against->getDateOpening(), + 'dateClosing' => $against->getDateClosing(), + 'date' => $history->getDateOpening() + ); + } + + //if we have an aopening later... + if ($history->getDateOpening() < $against->getDateClosing()) { + return array( 'result' => self::ERROR_OPENING_NOT_CLOSED_IS_BEFORE_NEW_LINE, + 'dateOpening' => $against->getDateOpening(), + 'dateClosing' => $against->getDateClosing(), + 'date' => $history->getDateOpening() + ); + } + + + } + + } else { + //we must check there is not covering lines + + foreach ($histories as $subKey => $against) { + //check if dateOpening is inside an `against` line + if ($history->getDateOpening() > $against->getDateOpening() + && $history->getDateOpening() < $against->getDateClosing()) { + return array( + 'result' => self::ERROR_OPENING_IS_INSIDE_CLOSING, + 'dateOpening' => $against->getDateOpening(), + 'dateClosing' => $against->getDateClosing(), + 'date' => $history->getDateOpening() + ); + } + } + } + } + + return true; + + } + + + + } \ No newline at end of file diff --git a/Entity/PersonHistoryFile.php b/Entity/PersonHistoryFile.php new file mode 100644 index 000000000..ee3b25c60 --- /dev/null +++ b/Entity/PersonHistoryFile.php @@ -0,0 +1,231 @@ +setDateOpening($dateOpening); + } + + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * Set date_opening + * + * @param \DateTime $dateOpening + * @return PersonHistoryFile + */ + public function setDateOpening($dateOpening) + { + $this->date_opening = $dateOpening; + + return $this; + } + + /** + * Get date_opening + * + * @return \DateTime + */ + public function getDateOpening() + { + return $this->date_opening; + } + + /** + * Set date_closing + * + * For closing a Person file, you should use Person::setClosed instead. + * + * @param \DateTime $dateClosing + * @return PersonHistoryFile + * + */ + public function setDateClosing($dateClosing) + { + $this->date_closing = $dateClosing; + + return $this; + } + + /** + * Get date_closing + * + * @return \DateTime + */ + public function getDateClosing() + { + return $this->date_closing; + } + + /** + * + * @return boolean + */ + public function isOpen() { + if ($this->getDateClosing() === null) { + return true; + } else { + return false; + } + } + + /** + * Set motive + * + * @param string $motive + * @return PersonHistoryFile + */ + public function setMotive($motive) + { + $this->motive = $motive; + + return $this; + } + + /** + * Get motive + * + * @return string + */ + public function getMotive() + { + return $this->motive; + } + + /** + * Set memo + * + * @param string $memo + * @return PersonHistoryFile + */ + public function setMemo($memo) + { + if ($memo === null) { + $memo = ''; + } + + $this->memo = $memo; + + return $this; + } + + /** + * Get memo + * + * @return string + */ + public function getMemo() + { + return $this->memo; + } + + /** + * Set person. + * + * For consistency, you should use Person::addHistoryFile instead. + * + * @param \CL\Chill\PersonBundle\Entity\Person $person + * @return PersonHistoryFile + * @see Person::addHistoryFile + */ + public function setPerson(\CL\Chill\PersonBundle\Entity\Person $person = null) + { + $this->person = $person; + + return $this; + } + + /** + * Get person + * + * @return \CL\Chill\PersonBundle\Entity\Person + */ + public function getPerson() + { + return $this->person; + } + + + /// VALIDATION function + + + public function isDateConsistent(ExecutionContextInterface $context) { + if ($this->isOpen()) { + return; + } + + if ($this->isClosingAfterOpening() === false) { + $context->addViolationAt('dateClosing', + 'validation.PersonHistoryFile.constraint.dateOfClosing_before_dateOfOpening', + array(), null); + } + } + + /** + * + * @return boolean + */ + public function isClosingAfterOpening() { + + $diff = $this->getDateOpening()->diff($this->getDateClosing()); + + if ($diff->invert === 0) { + return true; + } else { + return false; + } + + } +} diff --git a/Form/PersonType.php b/Form/PersonType.php index a03d9c25c..f50c94b42 100644 --- a/Form/PersonType.php +++ b/Form/PersonType.php @@ -20,7 +20,9 @@ class PersonType extends AbstractType $builder ->add('name') ->add('surname') - ->add('dateOfBirth', 'date', array('required' => false)) + ->add('dateOfBirth', 'birthday', array( + 'required' => false + )) ->add('placeOfBirth', 'text', array('required' => false)) ->add('genre', new GenderType(), array( 'required' => false diff --git a/Resources/assets/css/sass/person.scss b/Resources/assets/css/sass/person.scss index fbec51b25..c753b4a5c 100644 --- a/Resources/assets/css/sass/person.scss +++ b/Resources/assets/css/sass/person.scss @@ -49,6 +49,20 @@ div#person_wrapper { margin-left: 0.2em; } + .has_error { + label { + color: red; + } + + ul.errors li { + color: red; + } + + input { + + } + } + div.form_control { .controls { float: right; diff --git a/Resources/config/doctrine/Person.orm.yml b/Resources/config/doctrine/Person.orm.yml index 7adb628bc..b19fa57e5 100644 --- a/Resources/config/doctrine/Person.orm.yml +++ b/Resources/config/doctrine/Person.orm.yml @@ -44,6 +44,9 @@ CL\Chill\PersonBundle\Entity\Person: type: text email: type: text + proxyHistoryOpenState: + type: boolean + name: proxy_open manyToOne: countryOfBirth: targetEntity: CL\Chill\MainBundle\Entity\Country @@ -53,4 +56,9 @@ CL\Chill\PersonBundle\Entity\Person: targetEntity: CL\Chill\MainBundle\Entity\Country inversedBy: nationals nullable: true + oneToMany: + history: + targetEntity: PersonHistoryFile + mappedBy: person + cascade: [persist, remove, merge, detach] lifecycleCallbacks: { } diff --git a/Resources/config/doctrine/PersonHistoryFile.orm.yml b/Resources/config/doctrine/PersonHistoryFile.orm.yml new file mode 100644 index 000000000..f3ea0e6e8 --- /dev/null +++ b/Resources/config/doctrine/PersonHistoryFile.orm.yml @@ -0,0 +1,25 @@ +CL\Chill\PersonBundle\Entity\PersonHistoryFile: + type: entity + table: person_history_file + id: + id: + type: integer + id: true + generator: { strategy: AUTO } + fields: + date_opening: + type: date + date_closing: + type: date + default: null + nullable: true + motive: + type: string + length: 200 + memo: + type: text + manyToOne: + person: + targetEntity: Person + inversedBy: history + cascade: [refresh] diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml index 3b74594d9..922bbfc40 100644 --- a/Resources/config/routing.yml +++ b/Resources/config/routing.yml @@ -19,16 +19,28 @@ chill_person_general_update: chill_person_search: pattern: /search - defaults: { _controller: CLChillPersonBundle:Person:search } - -chill_person_view_history: - pattern: /view/{id}/history - defaults: {_controller: CLChillPersonBundle:Person:history } + defaults: { _controller: CLChillPersonBundle:Person:search } + +chill_person_history_list: + pattern: /{id}/history + defaults: { _controller: CLChillPersonBundle:History:list } options: menu: person order: 100 label: menu.person.history - + +chill_person_history_update: + pattern: /{id}/history/{historyId}/update + defaults: { _controller: CLChillPersonBundle:History:update } + +chill_person_history_close: + pattern: /{id}/history/close + defaults: { _controller: CLChillPersonBundle:History:close } + +chill_person_history_open: + pattern: /{id}/history/open + defaults: { _controller: CLChillPersonBundle:History:open } + #sample chill_appointment_list: pattern: /view/{id}/appointment/list @@ -84,4 +96,4 @@ chill_docs: options: menu: person order: 800 - label: "Documents" \ No newline at end of file + label: "Documents" diff --git a/Resources/config/validation.yml b/Resources/config/validation.yml new file mode 100644 index 000000000..b0eeb87c2 --- /dev/null +++ b/Resources/config/validation.yml @@ -0,0 +1,57 @@ +CL\Chill\PersonBundle\Entity\Person: + properties: + belgian_national_number: + - NotBlank: + groups: [general] + - CL\BelgianNationalNumberBundle\Validator\Constraint\BelgianNationalNumber: + groups: [general] + name: + - NotBlank: + groups: [general] + - Length: + min: 2 + max: 255 + minMessage: validation.Person.constraint.name_min + maxMessage: validation.Person.constraint.name_max + groups: [general] + + surname: + - NotBlank: + groups: [general] + - Length: + min: 2 + max: 255 + minMessage: validation.Person.constraint.name_min + maxMessage: validation.Person.constraint.name_max + groups: [general] + dateOfBirth: + - Date: + groups: [general] + nbOfChild: + - Range: + min: 0 + max: 20 + minMessage: validation.Person.constraint.nbOfChild_min + maxMessage: validation.Person.constraint.nbOfChild_max + invalidMessage: validation.Person.constraint.nbOfChild_invalid + groups: [general] + history: + - Valid: + traverse: true + constraints: + - Callback: + methods: [isHistoryValid] + groups: [history_consistent] + + + +CL\Chill\PersonBundle\Entity\PersonHistoryFile: + properties: + date_opening: + - Date: ~ + - NotNull: ~ + date_closing: + - Date: ~ + constraints: + - Callback: + methods: [isDateConsistent] \ No newline at end of file diff --git a/Resources/public/css/person.css b/Resources/public/css/person.css index 23793ac50..afb341683 100644 --- a/Resources/public/css/person.css +++ b/Resources/public/css/person.css @@ -7,4 +7,6 @@ div#person_wrapper div#person_details dd { margin: 0 0 0 199px; padding: 0 0 0.5 div#person_wrapper div#person_details label { color: green; } div#person_wrapper div#person_details label:not(.radio) { min-width: 190px; font-weight: bold; } div#person_wrapper div#person_details label.radio { margin-left: 0.2em; } +div#person_wrapper div#person_details .has_error label { color: red; } +div#person_wrapper div#person_details .has_error ul.errors li { color: red; } div#person_wrapper div#person_details div.form_control .controls { float: right; } diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 2ed63761a..1e1b2cc04 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -14,6 +14,11 @@ person: MAN: Homme WOM: Femme undefined: Non renseigné + history: + close: + motives: + not_come: Plus venu + finished: Accompagnement terminé search: @@ -25,9 +30,22 @@ validation: form: person: success: Bravo ! Les données ont été mises à jour. - error: '{1} Le champs %field% est incorrect. Veuillez le mettre à jour | ]1, Inf] Plusieurs champs sont incorrects. Veuillez les vérifier.' - -views: + error: '{1} Le champs %field% est incorrect. Veuillez le corriger. | ]1, Inf] Plusieurs champs sont incorrects. Veuillez les vérifier.' +controller: + Person: + history: + close: + done: Bravo ! Le dossier de %name% a été clotûré. + error: Une erreur est survenue. Le dossier n'a pu être clos. + error_in_form: Le formulaire n'est pas valide. + is_not_open: Le dossier de %name% n'est pas ouvert. Il ne peut donc être fermé. + open: + done: Bravo ! Le dossier de %name% est maintenant ouvert. + error: Une erreur est survenue. Le dossier n'a pu être ouvert. + error_in_form: Le formulaire n'est pas valide. + is_not_closed: Le dossier de %name% n'est pas fermé. Il ne peut donc être ouvert. + +views: layout: born: '{0} Né le %date% | {1} Née le %date%' without_nationality: Nationalité inconnue @@ -62,6 +80,28 @@ views: submit: Envoi list: without_nationality: Nationalité inconnue + #History + hlist: + title: Historique du dossier - %name% + dateOpening_title: Date d'ouverture + dateClosing_title: Date de fermeture + still_open: Toujours en cours + edit: Modifier + close: Clôre le dossier + open: Ouvrir le dossier + close: + last_opening_since: Dernière ouverture le %last_opening%. + action: Clotûrer + select_a_motive: Choisissez un motif + date_of_closing: Date de clotûre + motive_of_closing: Motif de clôture + texto: Mémo + open: + action: Ouvrir + date_of_opening: Date d'ouverture + texto: Mémo + + diff --git a/Resources/translations/validators.fr.yml b/Resources/translations/validators.fr.yml new file mode 100644 index 000000000..5461e3d34 --- /dev/null +++ b/Resources/translations/validators.fr.yml @@ -0,0 +1,14 @@ +validation: + Person: + constraint: + name_min: Ce nom est trop court. Il devrait contenir {{ limit }} caractères. + name_max: Ce nom est trop long. Il devrait contenir {{ limit }} caractères. + nbOfChild_min: Ce nombre est négatif. Il ne peut y avoir moins de 0 enfants. + nbOfChild_max: Ce nombre est trop élevé. Il ne peut être supérieur à {{ limit }}. + nbOfChild_invalid: La valeur introduite n'est pas un nombre. + history: + opening_is_before_closing: L'historique des ouvertures et fermetures de dossier n'est pas cohérent. La date %dateOpening% ouvre un dossier avant une précédente fermeture au %dateClosing%. Vérifiez la liste des ouvertures et fermetures. + open_history_without_closing: Vous tentez d'ouvrir un dossier à une date passée alors qu'il est réouvert plus tard. Veuillez insérer une nouvelle ligne d'ouverture avant de la clotûrer avant la suivante. + PersonHistoryFile: + constraint: + dateOfClosing_before_dateOfOpening: La date de fermeture du dossier ne peut pas être avant la date d'ouverture. diff --git a/Resources/views/Default/index.html.twig b/Resources/views/Default/index.html.twig deleted file mode 100644 index 4ce626e9b..000000000 --- a/Resources/views/Default/index.html.twig +++ /dev/null @@ -1 +0,0 @@ -Hello {{ name }}! diff --git a/Resources/views/History/close.html.twig b/Resources/views/History/close.html.twig new file mode 100644 index 000000000..c1c9c92df --- /dev/null +++ b/Resources/views/History/close.html.twig @@ -0,0 +1,31 @@ +{% extends "CLChillPersonBundle::layout.html.twig" %} + +{% set activeRouteKey = null %} + +{% block title %}{% endblock title %} + +{% form_theme form 'CLChillMainBundle:Form:fields.html.twig' %} + +{% block personcontent %} + +{{ form_start(form) }} + +{{ 'views.Person.close.last_opening_since'|trans( + { '%last_opening%' : history.dateOpening|date(date_format) }) }} + +{{ form_row(form.dateClosing, {'label' : 'views.Person.close.date_of_closing'} ) }} + +{{ form_row(form.motive, {'label' : 'views.Person.close.motive_of_closing'} ) }} + +{{ form_row(form.texto, {'label' : 'views.Person.close.texto' } ) }} + +{{ form_rest(form) }} + +
{{ 'views.Person.hlist.dateOpening_title'|trans }} | +{{ 'views.Person.hlist.dateClosing_title'|trans }} | ++ |
---|---|---|
{{ history.dateOpening|date(date_format) }} | +{% spaceless %} + {% if history.isOpen %} + {{ 'views.Person.hlist.still_open'|trans }} + + {% else %} + {{ history.dateClosing|date(date_format) }} + {% endif %} + + {% endspaceless %} | ++ + | +
{% transchoice person.genreNumeric diff --git a/Tests/Controller/DefaultControllerTest.php b/Tests/Controller/DefaultControllerTest.php index 7b4facafb..cb222c803 100644 --- a/Tests/Controller/DefaultControllerTest.php +++ b/Tests/Controller/DefaultControllerTest.php @@ -8,10 +8,6 @@ class DefaultControllerTest extends WebTestCase { public function testIndex() { - $client = static::createClient(); - - $crawler = $client->request('GET', '/hello/Fabien'); - - $this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0); + } } diff --git a/Tests/Controller/HistoryControllerTest.php b/Tests/Controller/HistoryControllerTest.php new file mode 100644 index 000000000..dfd52c363 --- /dev/null +++ b/Tests/Controller/HistoryControllerTest.php @@ -0,0 +1,182 @@ +setDateClosing($datetime2); + + + $r = $history->isClosingAfterOpening(); + + $this->assertTrue($r); + } + + public function testClosingIsBeforeOpeningConsistency() { + $datetime1 = new \DateTime('tomorrow'); + + + $history = new PersonHistoryFile($datetime1); + + + $datetime2 = new \DateTime('now'); + + $history->setDateClosing($datetime2); + + $this->assertFalse($history->isClosingAfterOpening()); + } + + public function testClosingEqualOpening() { + $datetime = new \DateTime('now'); + + $history = new PersonHistoryFile($datetime); + $history->setDateClosing($datetime); + + $this->assertTrue($history->isClosingAfterOpening()); + } + + public function testIsOpen() { + $history = new PersonHistoryFile(new \DateTime()); + + $this->assertTrue($history->isOpen()); + } + + public function testIsClosed() { + $history = new PersonHistoryFile(new \DateTime()); + + $history->setDateClosing(new \DateTime('tomorrow')); + + $this->assertFalse($history->isOpen()); + } + + public function testHistoryOrderWithUnorderedHistory() { + $d = new \DateTime(); $d->setDate(2013, 2, 1); + $p = new Person($d); + + $e = new \DateTime(); $e->setDate(2013,3,1); + $p->close($e, null); + + $f = new \DateTime(); $f->setDate(2013, 1, 1); + $p->open($f); + + $g = new \DateTime(); $g->setDate(2013, 4, 1); + $p->close($g, null); + + $r = $p->getHistoriesOrdered(); + + $date = $r[0]->getDateOpening()->format('Y-m-d'); + + + $this->assertEquals($date, '2013-01-01'); + } + + + public function testHistoryOrderSameDateOpening() { + $d = new \DateTime(); $d->setDate(2013, 2, 1); + $p = new Person($d); + + $e = new \DateTime(); $e->setDate(2013, 3, 1); + $p->close($e, null); + + $f = new \DateTime(); $f->setDate(2013, 2, 1); + $p->open($f); + + $g = new \DateTime(); $g->setDate(2013, 4, 1); + $p->close($g, null); + + $r = $p->getHistoriesOrdered(); + + $date = $r[0]->getDateClosing()->format('Y-m-d'); + + + $this->assertEquals($date, '2013-03-01'); + } + + public function testDateCoveringWithCoveringHistory() { + $d = new \DateTime(); $d->setDate(2013, 2, 1); + $p = new Person($d); + + $e = new \DateTime(); $e->setDate(2013,3,1); + $p->close($e, null); + + $f = new \DateTime(); $f->setDate(2013, 1, 1); + $p->open($f); + + $g = new \DateTime(); $g->setDate(2013, 4, 1); + $p->close($g, null); + + $r = $p->checkHistoryIsNotCovering(); + + $this->assertEquals($r['result'], Person::ERROR_OPENING_IS_INSIDE_CLOSING); + } + + + + public function testNotOpenAFileReOpenedLater() { + $d = new \DateTime(); $d->setDate(2013, 2, 1); + $p = new Person($d); + + $e = new \DateTime(); $e->setDate(2013, 3, 1); + $p->close($e, null); + + $f = new \DateTime(); $f->setDate(2013, 1, 1); + $p->open($f); + + + + $r = $p->checkHistoryIsNotCovering(); + + var_dump($r); + + $this->assertEquals($r['result'], Person::ERROR_OPENING_NOT_CLOSED_IS_BEFORE_NEW_LINE); + } + + + + + + + public function testOrder() { + $d = new \DateTime(); $d->setDate(2013, 2, 1); + $g = new \DateTime(); $g->setDate(2013, 4, 1); + $f = new \DateTime(); $f->setDate(2013, 1, 1); + $e = new \DateTime(); $e->setDate(2013,3,1); + + $a = array($d, $g, $f, $e); + + + usort($a, function($a, $b) { + if ($a === $b) { + return 0; + } + + if ($a < $b) { + return -1; + } else { + return 1; + } + }); + + + $date = $a[0]->format('Y-m-d'); + + $this->assertEquals($date, '2013-01-01'); + + } + + + +}