mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'master' into social_action_exports
This commit is contained in:
commit
8fdb2747ac
@ -16,6 +16,8 @@ and this project adheres to
|
||||
* [person-thirdparty]: fix quick-add of names that consist of multiple parts (eg. De Vlieger) within onthefly modal person/thirdparty
|
||||
* [search]: Order of birthdate fields changed in advanced search to avoid confusion.
|
||||
* [workflow]: Constraint added to workflow (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/675)
|
||||
* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620)
|
||||
* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611)
|
||||
|
||||
## Test releases
|
||||
|
||||
|
@ -24,6 +24,7 @@ parameters:
|
||||
- "/spec/"
|
||||
- "/var/"
|
||||
- "/vendor/"
|
||||
- "/tests/app"
|
||||
|
||||
# Psalm
|
||||
tasks.psalm.blocking: true
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,16 +25,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in &&, mixed given on the right side\\.$#"
|
||||
count: 3
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillActivityBundle/Form/ActivityType.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 3
|
||||
|
@ -21,6 +21,7 @@ use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Repository\LocationRepository;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
@ -56,6 +57,8 @@ final class ActivityController extends AbstractController
|
||||
|
||||
private ActivityTypeRepository $activityTypeRepository;
|
||||
|
||||
private CenterResolverManagerInterface $centerResolver;
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
@ -82,7 +85,8 @@ final class ActivityController extends AbstractController
|
||||
EntityManagerInterface $entityManager,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer
|
||||
SerializerInterface $serializer,
|
||||
CenterResolverManagerInterface $centerResolver
|
||||
) {
|
||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
@ -96,6 +100,7 @@ final class ActivityController extends AbstractController
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->logger = $logger;
|
||||
$this->serializer = $serializer;
|
||||
$this->centerResolver = $centerResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +203,7 @@ final class ActivityController extends AbstractController
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
|
||||
|
||||
$form = $this->createForm(ActivityType::class, $entity, [
|
||||
'center' => $entity->getCenter(),
|
||||
'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null,
|
||||
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
|
||||
'activityType' => $entity->getActivityType(),
|
||||
'accompanyingPeriod' => $accompanyingPeriod,
|
||||
@ -416,7 +421,7 @@ final class ActivityController extends AbstractController
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::CREATE, $entity);
|
||||
|
||||
$form = $this->createForm(ActivityType::class, $entity, [
|
||||
'center' => $entity->getCenter(),
|
||||
'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null,
|
||||
'role' => new Role('CHILL_ACTIVITY_CREATE'),
|
||||
'activityType' => $entity->getActivityType(),
|
||||
'accompanyingPeriod' => $accompanyingPeriod,
|
||||
|
@ -61,8 +61,6 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
|
||||
ActivityVoter::DELETE => [ActivityVoter::SEE_DETAILS],
|
||||
ActivityVoter::SEE_DETAILS => [ActivityVoter::SEE],
|
||||
ActivityVoter::FULL => [
|
||||
ActivityVoter::CREATE_PERSON,
|
||||
ActivityVoter::CREATE_ACCOMPANYING_COURSE,
|
||||
ActivityVoter::DELETE,
|
||||
ActivityVoter::UPDATE,
|
||||
],
|
||||
|
@ -16,8 +16,8 @@ use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable;
|
||||
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Chill\MainBundle\Entity\HasCentersInterface;
|
||||
use Chill\MainBundle\Entity\HasScopesInterface;
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
@ -55,7 +55,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* getUserFunction="getUser",
|
||||
* path="scope")
|
||||
*/
|
||||
class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, HasCenterInterface, HasScopeInterface
|
||||
class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, HasCentersInterface, HasScopesInterface
|
||||
{
|
||||
public const SENTRECEIVED_RECEIVED = 'received';
|
||||
|
||||
@ -306,13 +306,17 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
* get the center
|
||||
* center is extracted from person.
|
||||
*/
|
||||
public function getCenter(): ?Center
|
||||
public function getCenters(): iterable
|
||||
{
|
||||
if ($this->person instanceof Person) {
|
||||
return $this->person->getCenter();
|
||||
return [$this->person->getCenter()];
|
||||
}
|
||||
|
||||
return null;
|
||||
if ($this->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
return $this->getAccompanyingPeriod()->getCenters() ?? [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getComment(): CommentEmbeddable
|
||||
@ -422,6 +426,19 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function getScopes(): iterable
|
||||
{
|
||||
if (null !== $this->getAccompanyingPeriod()) {
|
||||
return $this->getAccompanyingPeriod()->getScopes();
|
||||
}
|
||||
|
||||
if (null !== $this->getPerson()) {
|
||||
return [$this->scope];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getSentReceived(): string
|
||||
{
|
||||
return $this->sentReceived;
|
||||
|
@ -14,17 +14,20 @@ namespace Chill\ActivityBundle\Form;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Entity\ActivityPresence;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\DocStoreBundle\Form\StoredObjectType;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\Type\ChillCollectionType;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\CommentType;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\MainBundle\Form\Type\PrivateCommentType;
|
||||
use Chill\MainBundle\Form\Type\ScopePickerType;
|
||||
use Chill\MainBundle\Form\Type\UserPickerType;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
@ -50,6 +53,7 @@ use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use function in_array;
|
||||
|
||||
class ActivityType extends AbstractType
|
||||
@ -109,19 +113,18 @@ class ActivityType extends AbstractType
|
||||
$activityType = $options['activityType'];
|
||||
|
||||
// TODO revoir la gestion des center au niveau du form des activité.
|
||||
if ($options['center']) {
|
||||
if ($options['center'] instanceof Center && null !== $options['data']->getPerson()) {
|
||||
$builder->add('scope', ScopePickerType::class, [
|
||||
'center' => $options['center'],
|
||||
'role' => $options['role'],
|
||||
// TODO make required again once scope and rights are fixed
|
||||
'required' => false,
|
||||
'role' => ActivityVoter::CREATE === (string) $options['role'] ? ActivityVoter::CREATE_PERSON : (string) $options['role'],
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingPeriod */
|
||||
$accompanyingPeriod = null;
|
||||
|
||||
if ($options['accompanyingPeriod']) {
|
||||
if ($options['accompanyingPeriod'] instanceof AccompanyingPeriod) {
|
||||
$accompanyingPeriod = $options['accompanyingPeriod'];
|
||||
}
|
||||
|
||||
@ -218,12 +221,10 @@ class ActivityType extends AbstractType
|
||||
]);
|
||||
}
|
||||
|
||||
if ($activityType->isVisible('user') && $options['center']) {
|
||||
$builder->add('user', UserPickerType::class, [
|
||||
if ($activityType->isVisible('user') && $options['center'] instanceof Center) {
|
||||
$builder->add('user', PickUserDynamicType::class, [
|
||||
'label' => $activityType->getLabel('user'),
|
||||
'required' => $activityType->isRequired('user'),
|
||||
'center' => $options['center'],
|
||||
'role' => $options['role'],
|
||||
]);
|
||||
}
|
||||
|
||||
@ -442,8 +443,8 @@ class ActivityType extends AbstractType
|
||||
|
||||
$resolver
|
||||
->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod'])
|
||||
->setAllowedTypes('center', ['null', 'Chill\MainBundle\Entity\Center'])
|
||||
->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role')
|
||||
->setAllowedTypes('center', ['null', Center::class])
|
||||
->setAllowedTypes('role', [Role::class, 'string'])
|
||||
->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']);
|
||||
}
|
||||
|
@ -120,3 +120,11 @@
|
||||
|
||||
{{ form_end(edit_form) }}
|
||||
{# {{ form(delete_form) }} #}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_script_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
@ -46,7 +46,7 @@
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %}
|
||||
|
||||
{% if is_granted('CHILL_ACTIVITY_CREATE_PERSON', person) %}
|
||||
{% if is_granted('CHILL_ACTIVITY_CREATE', person) %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
|
||||
|
@ -119,3 +119,11 @@
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_script_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
@ -133,7 +133,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
|
||||
// change attribute CREATE
|
||||
if (self::CREATE === $attribute) {
|
||||
$attribute = self::CREATE_PERSON;
|
||||
return $this->voterHelper->voteOnAttribute(self::CREATE_PERSON, $subject->getPerson(), $token);
|
||||
}
|
||||
} elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) {
|
||||
@ -144,7 +144,8 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
if (AccompanyingPeriod::STEP_CLOSED === $subject->getAccompanyingPeriod()->getStep()) {
|
||||
return false;
|
||||
}
|
||||
$attribute = self::CREATE_ACCOMPANYING_COURSE;
|
||||
|
||||
return $this->voterHelper->voteOnAttribute(self::CREATE_ACCOMPANYING_COURSE, $subject->getAccompanyingPeriod(), $token);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException('Could not determine context of activity.');
|
||||
@ -158,12 +159,12 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
|
||||
// transform the attribute
|
||||
if (self::CREATE === $attribute) {
|
||||
$attribute = self::CREATE_ACCOMPANYING_COURSE;
|
||||
return $this->voterHelper->voteOnAttribute(self::CREATE_ACCOMPANYING_COURSE, $subject, $token);
|
||||
}
|
||||
} elseif ($subject instanceof Person) {
|
||||
// transform the attribute
|
||||
if (self::CREATE === $attribute) {
|
||||
$attribute = self::CREATE_PERSON;
|
||||
return $this->voterHelper->voteOnAttribute(self::CREATE_PERSON, $subject, $token);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,8 +130,10 @@ class ActivityContext implements
|
||||
return $this->personRender->renderString($p, []);
|
||||
},
|
||||
'multiple' => false,
|
||||
'required' => false,
|
||||
'expanded' => true,
|
||||
'label' => $options[$key . 'Label'],
|
||||
'placeholder' => $this->translator->trans('Any person selected'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\DocStoreBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Entity\HasScopesInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
@ -18,7 +19,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
* @ORM\Entity
|
||||
* @ORM\Table("chill_doc.accompanyingcourse_document")
|
||||
*/
|
||||
class AccompanyingCourseDocument extends Document
|
||||
class AccompanyingCourseDocument extends Document implements HasScopesInterface
|
||||
{
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class)
|
||||
@ -31,6 +32,15 @@ class AccompanyingCourseDocument extends Document
|
||||
return $this->course;
|
||||
}
|
||||
|
||||
public function getScopes(): iterable
|
||||
{
|
||||
if (null !== $this->course) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->course->getScopes();
|
||||
}
|
||||
|
||||
public function setCourse(?AccompanyingPeriod $course): self
|
||||
{
|
||||
$this->course = $course;
|
||||
|
@ -16,8 +16,6 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
@ -26,7 +24,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
/**
|
||||
* @ORM\MappedSuperclass
|
||||
*/
|
||||
class Document implements HasScopeInterface, TrackCreationInterface, TrackUpdateInterface
|
||||
class Document implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
use TrackCreationTrait;
|
||||
|
||||
@ -70,13 +68,6 @@ class Document implements HasScopeInterface, TrackCreationInterface, TrackUpdate
|
||||
*/
|
||||
private $object;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\Scope The document's center
|
||||
*/
|
||||
private $scope;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate")
|
||||
*/
|
||||
@ -122,16 +113,6 @@ class Document implements HasScopeInterface, TrackCreationInterface, TrackUpdate
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scope.
|
||||
*
|
||||
* @return \Chill\MainBundle\Entity\Scope
|
||||
*/
|
||||
public function getScope(): ?Scope
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function getTemplate(): ?DocGeneratorTemplate
|
||||
{
|
||||
return $this->template;
|
||||
@ -175,13 +156,6 @@ class Document implements HasScopeInterface, TrackCreationInterface, TrackUpdate
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setScope($scope): self
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTemplate(?DocGeneratorTemplate $template): self
|
||||
{
|
||||
$this->template = $template;
|
||||
|
@ -13,6 +13,7 @@ namespace Chill\DocStoreBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
@ -27,6 +28,13 @@ class PersonDocument extends Document implements HasCenterInterface, HasScopeInt
|
||||
*/
|
||||
private Person $person;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\Scope The document's center
|
||||
*/
|
||||
private $scope;
|
||||
|
||||
public function getCenter()
|
||||
{
|
||||
return $this->getPerson()->getCenter();
|
||||
@ -37,10 +45,22 @@ class PersonDocument extends Document implements HasCenterInterface, HasScopeInt
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function getScope(): ?Scope
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function setPerson($person): self
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setScope($scope): self
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -88,10 +88,5 @@ class AccompanyingCourseDocumentType extends AbstractType
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Document::class,
|
||||
]);
|
||||
|
||||
// $resolver->setRequired(['role', 'center'])
|
||||
// ->setAllowedTypes('role', [ \Symfony\Component\Security\Core\Role\Role::class ])
|
||||
// ->setAllowedTypes('center', [ \Chill\MainBundle\Entity\Center::class ])
|
||||
// ;
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class PersonDocumentACLAwareRepository implements PersonDocumentACLAwareReposito
|
||||
$this->addACL($qb, $person);
|
||||
|
||||
foreach ($orderBy as $field => $order) {
|
||||
$qb->addOrderBy($field, $order);
|
||||
$qb->addOrderBy('d.' . $field, $order);
|
||||
}
|
||||
|
||||
$qb->setFirstResult($offset)->setMaxResults($limit);
|
||||
|
@ -106,6 +106,10 @@ class AccompanyingCourseDocumentVoter extends AbstractChillVoter implements Prov
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self::CREATE === $attribute && null !== $subject->getCourse()) {
|
||||
return $this->voterHelper->voteOnAttribute($attribute, $subject->getCourse(), $token);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
|
||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace Chill\EventBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* Class AdminController
|
||||
@ -20,18 +21,12 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* Event admin.
|
||||
*
|
||||
* @Route("/{_locale}/admin/event", name="chill_event_admin_index")
|
||||
*/
|
||||
public function indexAction()
|
||||
public function indexAdminAction()
|
||||
{
|
||||
return $this->render('ChillEventBundle:Admin:layout.html.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function redirectToAdminIndexAction()
|
||||
{
|
||||
return $this->redirectToRoute('chill_main_admin_central');
|
||||
return $this->render('ChillEventBundle:Admin:index.html.twig');
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ class EventController extends AbstractController
|
||||
/**
|
||||
* @var Center $centers
|
||||
*/
|
||||
$centers = $this->authorizationHelper->getReachableCenters($this->getUser(), $role);
|
||||
$centers = $this->authorizationHelper->getReachableCenters($this->getUser(), (string) $role);
|
||||
|
||||
if (count($centers) === 1) {
|
||||
return $this->redirectToRoute('chill_event__event_new', [
|
||||
|
@ -151,7 +151,7 @@ class PickEventType extends AbstractType
|
||||
} else {
|
||||
$centers = $this->authorizationHelper->getReachableCenters(
|
||||
$this->user,
|
||||
$options['role']
|
||||
(string) $options['role']
|
||||
);
|
||||
}
|
||||
|
||||
|
61
src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php
Normal file
61
src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\EventBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
class AdminMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
protected $authorizationChecker;
|
||||
|
||||
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
|
||||
{
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$menu->addChild('Events', [
|
||||
'route' => 'chill_event_admin_index',
|
||||
])
|
||||
->setAttribute('class', 'list-group-item-header')
|
||||
->setExtras([
|
||||
'order' => 6500,
|
||||
]);
|
||||
|
||||
$menu->addChild('Event type', [
|
||||
'route' => 'chill_eventtype_admin',
|
||||
])->setExtras(['order' => 6510]);
|
||||
|
||||
$menu->addChild('Event status', [
|
||||
'route' => 'chill_event_admin_status',
|
||||
])->setExtras(['order' => 6520]);
|
||||
|
||||
$menu->addChild('Role', [
|
||||
'route' => 'chill_event_admin_role',
|
||||
])->setExtras(['order' => 6530]);
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['admin_section', 'admin_event'];
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_event', {
|
||||
'layout': '@ChillMain/Admin/menu_admin_section.html.twig',
|
||||
}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}<!-- block content empty -->
|
||||
<h1>{{ 'Events configuration' |trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@ -1,31 +0,0 @@
|
||||
{#
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
<info@champs-libres.coop> / <http://www.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/>.
|
||||
#}
|
||||
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_events', {
|
||||
'layout': '@ChillEvent/Admin/menu.html.twig',
|
||||
}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}<!-- block content empty -->
|
||||
<h1>{{ 'Events configuration' |trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@ -1,21 +1,3 @@
|
||||
{#
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
<info@champs-libres.coop> / <http://www.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/>.
|
||||
#}
|
||||
|
||||
{% extends "@ChillMain/Menu/verticalMenu.html.twig" %}
|
||||
{% block v_menu_title %}{{ 'Events configuration menu'|trans }}{% endblock %}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
<h1>{{ 'Role edit'|trans }}</h1>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "ChillEventBundle:Admin:layout.html.twig" %}
|
||||
{% extends "ChillEventBundle:Admin:index.html.twig" %}
|
||||
|
||||
{% block admin_content -%}
|
||||
|
||||
|
@ -9,24 +9,24 @@ chill_event_participation:
|
||||
|
||||
## ADMIN
|
||||
|
||||
chill_event_admin:
|
||||
chill_event_admin_index:
|
||||
path: /{_locale}/admin/event
|
||||
controller: Chill\EventBundle\Controller\AdminController::indexAction
|
||||
options:
|
||||
menus:
|
||||
admin_section:
|
||||
order: 2100
|
||||
label: "Events"
|
||||
icons: ['calendar']
|
||||
controller: Chill\EventBundle\Controller\AdminController::indexAdminAction
|
||||
# options:
|
||||
# menus:
|
||||
# admin_section:
|
||||
# order: 2100
|
||||
# label: "Events"
|
||||
# icons: ['calendar']
|
||||
|
||||
chill_event_admin_redirect_to_admin_index:
|
||||
path: /{_locale}/admin/event_redirect_to_main
|
||||
controller: Chill\EventBundle\Controller\AdminController::redirectToAdminIndexAction
|
||||
options:
|
||||
menus:
|
||||
admin_events:
|
||||
order: 0
|
||||
label: Main admin menu
|
||||
# chill_event_admin_redirect_to_admin_index:
|
||||
# path: /{_locale}/admin/event_redirect_to_main
|
||||
# controller: Chill\EventBundle\Controller\AdminController::redirectToAdminIndexAction
|
||||
# options:
|
||||
# menus:
|
||||
# admin_events:
|
||||
# order: 0
|
||||
# label: Main admin menu
|
||||
|
||||
chill_event_admin_status:
|
||||
resource: "@ChillEventBundle/config/routes/status.yaml"
|
||||
@ -39,4 +39,4 @@ chill_event_admin_role:
|
||||
chill_event_admin_event_type:
|
||||
resource: "@ChillEventBundle/config/routes/eventtype.yaml"
|
||||
prefix: /{_locale}/admin/event/event_type
|
||||
|
||||
|
||||
|
@ -1,2 +1,11 @@
|
||||
services:
|
||||
Chill\EventBundle\Controller\:
|
||||
autowire: true
|
||||
resource: '../Controller'
|
||||
tags: ['controller.service_arguments']
|
||||
|
||||
Chill\EventBundle\Menu\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Menu/'
|
||||
tags: ['chill.menu_builder']
|
@ -126,7 +126,7 @@ class Version20160318111334 extends AbstractMigration
|
||||
$this->addSql('ALTER TABLE chill_event_participation '
|
||||
. 'ADD CONSTRAINT FK_4E7768AC217BBB47 '
|
||||
. 'FOREIGN KEY (person_id) '
|
||||
. 'REFERENCES Person (id) '
|
||||
. 'REFERENCES chill_person_person(id) '
|
||||
. 'NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_event_participation '
|
||||
. 'ADD CONSTRAINT FK_4E7768ACD60322AC '
|
||||
|
@ -92,5 +92,8 @@ final class PostalCodeAPIController extends ApiController
|
||||
$qb->where('e.country = :country')
|
||||
->setParameter('country', $request->query->get('country'));
|
||||
}
|
||||
|
||||
$qb->andWhere('e.origin = :zero')
|
||||
->setParameter('zero', 0);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ declare(strict_types=1);
|
||||
namespace Chill\MainBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class UserApiController extends ApiController
|
||||
@ -58,4 +60,14 @@ class UserApiController extends ApiController
|
||||
['groups' => ['read']]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryBuilder $query
|
||||
*/
|
||||
protected function customizeQuery(string $action, Request $request, $query): void
|
||||
{
|
||||
if ('_index' === $action) {
|
||||
$query->andWhere($query->expr()->eq('e.enabled', "'TRUE'"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class UserJobApiController extends ApiController
|
||||
{
|
||||
protected function customizeQuery(string $action, Request $request, $query): void
|
||||
{
|
||||
if ('_index' === $action) {
|
||||
$query->andWhere($query->expr()->eq('e.active', "'TRUE'"));
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ use Chill\MainBundle\Controller\LanguageController;
|
||||
use Chill\MainBundle\Controller\LocationController;
|
||||
use Chill\MainBundle\Controller\LocationTypeController;
|
||||
use Chill\MainBundle\Controller\UserController;
|
||||
use Chill\MainBundle\Controller\UserJobApiController;
|
||||
use Chill\MainBundle\Controller\UserJobController;
|
||||
use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
|
||||
use Chill\MainBundle\Doctrine\DQL\GetJsonFieldByKey;
|
||||
@ -501,6 +502,7 @@ class ChillMainExtension extends Extension implements
|
||||
'name' => 'user_job',
|
||||
'base_path' => '/api/1.0/main/user-job',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'controller' => UserJobApiController::class,
|
||||
'actions' => [
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
|
@ -75,8 +75,6 @@ class PickCenterType extends AbstractType
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
|
||||
|
||||
$export = $this->exportManager->getExport($options['export_alias']);
|
||||
$centers = $this->authorizationHelper->getReachableCenters(
|
||||
$this->user,
|
||||
|
@ -119,8 +119,8 @@ final class PostalCodeRepository implements ObjectRepository
|
||||
|
||||
$pertinenceClause = ['STRICT_WORD_SIMILARITY(canonical, UNACCENT(?))'];
|
||||
$pertinenceArgs = [$pattern];
|
||||
$orWhere = ['canonical %>> UNACCENT(?)'];
|
||||
$orWhereArgs = [$pattern];
|
||||
$andWhere = ['canonical %>> UNACCENT(?)'];
|
||||
$andWhereArgs = [$pattern];
|
||||
|
||||
foreach (explode(' ', $pattern) as $part) {
|
||||
$part = trim($part);
|
||||
@ -129,8 +129,8 @@ final class PostalCodeRepository implements ObjectRepository
|
||||
continue;
|
||||
}
|
||||
|
||||
$orWhere[] = "canonical LIKE '%' || UNACCENT(LOWER(?)) || '%'";
|
||||
$orWhereArgs[] = $part;
|
||||
$andWhere[] = "canonical LIKE '%' || UNACCENT(LOWER(?)) || '%'";
|
||||
$andWhereArgs[] = $part;
|
||||
$pertinenceClause[] =
|
||||
"(EXISTS (SELECT 1 FROM unnest(string_to_array(canonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int";
|
||||
$pertinenceClause[] =
|
||||
@ -139,7 +139,7 @@ final class PostalCodeRepository implements ObjectRepository
|
||||
}
|
||||
$query
|
||||
->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs)
|
||||
->andWhereClause(implode(' OR ', $orWhere), $orWhereArgs);
|
||||
->andWhereClause(implode(' AND ', $andWhere), $andWhereArgs);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ final class Version20210505153727 extends AbstractMigration
|
||||
');
|
||||
$this->addSql('
|
||||
WITH hydrated_addresses AS (
|
||||
SELECT *, rank() OVER (PARTITION BY pa_a.person_id ORDER BY validfrom)
|
||||
SELECT *, rank() OVER (PARTITION BY pa_a.person_id ORDER BY validfrom, id)
|
||||
FROM chill_main_address AS aa JOIN chill_person_persons_to_addresses AS pa_a ON aa.id = pa_a.address_id
|
||||
)
|
||||
UPDATE chill_main_address AS b
|
||||
SET validto = (
|
||||
SELECT validfrom - INTERVAL \'1 DAY\'
|
||||
SELECT validfrom
|
||||
FROM hydrated_addresses
|
||||
WHERE hydrated_addresses.id = (
|
||||
SELECT a1.id
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20220711150006 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_workflow_entity_step
|
||||
DROP CONSTRAINT chill_custom_only_one_step_opened');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add a constraint to ensure that only one step is available at a time';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_workflow_entity_step
|
||||
ADD CONSTRAINT chill_custom_only_one_step_opened
|
||||
EXCLUDE (
|
||||
entityworkflow_id WITH =
|
||||
) WHERE (transitionafter IS NULL)
|
||||
DEFERRABLE INITIALLY DEFERRED');
|
||||
}
|
||||
}
|
@ -177,7 +177,7 @@ class AccompanyingCourseController extends Controller
|
||||
*/
|
||||
public function editAction(AccompanyingPeriod $accompanyingCourse): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $accompanyingCourse);
|
||||
|
||||
return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [
|
||||
'accompanyingCourse' => $accompanyingCourse,
|
||||
@ -215,7 +215,7 @@ class AccompanyingCourseController extends Controller
|
||||
// get persons without household
|
||||
$withoutHousehold = [];
|
||||
|
||||
foreach ($accompanyingCourse->getParticipations() as $p) {
|
||||
foreach ($accompanyingCourse->getCurrentParticipations() as $p) {
|
||||
if (false === $p->getPerson()->isSharingHousehold()) {
|
||||
$withoutHousehold[] = $p->getPerson();
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class HouseholdCompositionTypeController extends CRUDController
|
||||
{
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
$query->addOrderBy('e.id', 'ASC');
|
||||
|
||||
return parent::orderQuery($action, $query, $request, $paginator);
|
||||
}
|
||||
}
|
@ -228,6 +228,27 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\Household\HouseholdCompositionType::class,
|
||||
'name' => 'person_household_composition_type',
|
||||
'base_path' => '/admin/person/household/composition-type',
|
||||
'form_class' => \Chill\PersonBundle\Form\HouseholdCompositionTypeType::class,
|
||||
'controller' => \Chill\PersonBundle\Controller\HouseholdCompositionTypeController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/HouseholdCompositionType/index.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/HouseholdCompositionType/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/HouseholdCompositionType/edit.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\Relationships\Relation::class,
|
||||
'name' => 'person_relation',
|
||||
|
@ -36,49 +36,49 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface
|
||||
* inversedBy="comments")
|
||||
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
|
||||
*/
|
||||
private $accompanyingPeriod;
|
||||
private ?AccompanyingPeriod $accompanyingPeriod;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
* @Groups({"read", "write"})
|
||||
* @Groups({"read", "write", "docgen:read"})
|
||||
* @Assert\NotBlank
|
||||
* @Assert\NotNull
|
||||
*/
|
||||
private $content;
|
||||
private ?string $content;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Groups({"read"})
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private $createdAt;
|
||||
private ?DateTimeInterface $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Groups({"read"})
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private $creator;
|
||||
private ?User $creator;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Groups({"read"})
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private $id;
|
||||
private ?int $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $updatedAt;
|
||||
private ?DateTimeInterface $updatedAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $updatedBy;
|
||||
private ?User $updatedBy;
|
||||
|
||||
public function getAccompanyingPeriod(): ?AccompanyingPeriod
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ class Resource
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
* @Groups({"read"})
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private ?string $comment = '';
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Entity\Household;
|
||||
use ArrayIterator;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Validator\Constraints\Household\MaxHolder;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
@ -354,7 +355,12 @@ class Household
|
||||
return $this->members;
|
||||
}
|
||||
|
||||
public function getMembersDuringMembership(HouseholdMember $membership)
|
||||
/**
|
||||
* get all the members during a given membership.
|
||||
*
|
||||
* @return Collection|HouseholdMember[]
|
||||
*/
|
||||
public function getMembersDuringMembership(HouseholdMember $membership): Collection
|
||||
{
|
||||
return $this->getMembersOnRange(
|
||||
$membership->getStartDate(),
|
||||
@ -441,6 +447,28 @@ class Household
|
||||
return $this->getNonCurrentMembers($now)->matching($criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all the unique persons during a given membership.
|
||||
*
|
||||
* same as @see(self::getMembersDuringMembership}, except that the collection is filtered to
|
||||
* return unique members.
|
||||
*
|
||||
* @return Collection|Person[]
|
||||
*/
|
||||
public function getPersonsDuringMembership(HouseholdMember $member): Collection
|
||||
{
|
||||
// make list unique
|
||||
$membersByHash = [];
|
||||
|
||||
foreach ($this->getMembersDuringMembership($member) as $m) {
|
||||
if (null !== $m && null !== $m->getPerson()) {
|
||||
$membersByHash[spl_object_hash($m->getPerson())] = $m->getPerson();
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayCollection(array_values($membersByHash));
|
||||
}
|
||||
|
||||
public function getPreviousAddressOf(Address $address): ?Address
|
||||
{
|
||||
$iterator = new ArrayIterator($this->getAddressesOrdered());
|
||||
|
@ -1184,7 +1184,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `getCurrentPersonAddress` instead
|
||||
* @deprecated Use @see{Person::getCurrentPersonAddress} or @see{Person::getCurrentHouseholdAddress} instead
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
@ -1192,7 +1192,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
*/
|
||||
public function getLastAddress(?DateTime $from = null)
|
||||
{
|
||||
return $this->getCurrentPersonAddress();
|
||||
return $this->getCurrentHouseholdAddress(
|
||||
null !== $from ? DateTimeImmutable::createFromMutable($from) : null
|
||||
);
|
||||
}
|
||||
|
||||
public function getLastName(): string
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class HouseholdCompositionTypeType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('label', TranslatableStringFormType::class)
|
||||
->add('active', CheckboxType::class, [
|
||||
'label' => 'Actif?',
|
||||
'required' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setDefault('class', HouseholdCompositionType::class);
|
||||
}
|
||||
}
|
@ -46,9 +46,13 @@ class AdminHouseholdMenuBuilder implements LocalMenuBuilderInterface
|
||||
'route' => 'chill_crud_person_household_position_index',
|
||||
])->setExtras(['order' => 2110]);
|
||||
|
||||
$menu->addChild('Composition', [
|
||||
'route' => 'chill_crud_person_household_composition_type_index',
|
||||
])->setExtras(['order' => 2120]);
|
||||
|
||||
$menu->addChild('person_admin.relation', [
|
||||
'route' => 'chill_crud_person_relation_index',
|
||||
])->setExtras(['order' => 2120]);
|
||||
])->setExtras(['order' => 2130]);
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="alert alert-warning alert-with-actions">
|
||||
<div class="float-button bottom">
|
||||
<div class="box">
|
||||
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', accompanyingCourse) %}
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
@ -13,6 +13,8 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p>{{ 'Some peoples does not belong to any household currently. Add them to an household soon'|trans }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<div class="alert alert-danger {% if hasPersonLocation %}alert-with-actions{% endif %}">
|
||||
<div class="float-button bottom">
|
||||
<div class="box">
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', accompanyingCourse) %}
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
@ -14,6 +15,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p>
|
||||
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}</p>
|
||||
{% if not hasPersonLocation %}
|
||||
|
@ -14,7 +14,7 @@
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', period) %}
|
||||
<div class="item-col item-meta">
|
||||
{% set job_id = null %}
|
||||
{% if period.job is defined %}
|
||||
{% if period.job is not null %}
|
||||
{% set job_id = period.job.id %}
|
||||
{% endif %}
|
||||
<span
|
||||
|
@ -48,13 +48,66 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<div class="flex-table accompanyingcourse-list">
|
||||
{% for period in accompanying_periods %}
|
||||
|
||||
{# WARNING: this list is rendered in either person context or houshold context #}
|
||||
|
||||
{%- set acps = [] %}
|
||||
{%- set acpsClosed = [] %}
|
||||
{% for acp in accompanying_periods %}
|
||||
{% if acp.step == 'CLOSED' or (person is defined and acp.requestorPerson is not same as(person) and acp.openParticipationContainsPerson(person) is null ) %}
|
||||
{%- set acpsClosed = acpsClosed|merge([acp]) %}
|
||||
{% else %}
|
||||
{%- set acps = acps|merge([acp]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="flex-table accompanyingcourse-list">
|
||||
{% for period in acps %}
|
||||
{% include 'ChillPersonBundle:AccompanyingPeriod:_list_item.html.twig' with {
|
||||
'recordAction': _self.recordAction(period, contextEntity)
|
||||
} %}
|
||||
|
||||
{% else %}
|
||||
<p class="chill-no-data-statement">{{ 'Any accompanying periods are open'|trans }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if acpsClosed|length > 0 %}
|
||||
{% if person is defined %}
|
||||
{% set identifier = person.id %}
|
||||
{% else %}
|
||||
{% set identifier = household.id %}
|
||||
{% endif %}
|
||||
|
||||
<div class="accordion" id="member_{{ identifier }}">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="heading_{{ identifier }}">
|
||||
<button
|
||||
class="accordion-button collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapse_{{ identifier }}"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapse_{{ identifier }}">
|
||||
<span class="folded">{{ 'periods.show closed periods'|trans({ 'nb_items': acpsClosed|length }) }}</span>
|
||||
<span class="unfolded text-secondary">{{ 'periods.hide closed periods'|trans({ 'nb_items': acpsClosed|length }) }}</span>
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="collapse_{{ identifier }}"
|
||||
class="accordion-collapse collapse"
|
||||
aria-labelledby="heading_{{ identifier }}"
|
||||
data-bs-parent="#nonCurrent">
|
||||
|
||||
<div class="flex-table accompanyingcourse-list">
|
||||
{% for period in acpsClosed %}
|
||||
{% include 'ChillPersonBundle:AccompanyingPeriod:_list_item.html.twig' with {
|
||||
'recordAction': _self.recordAction(period, contextEntity)
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
@ -180,10 +180,16 @@
|
||||
{% if members|length > 0 %}
|
||||
<div class="flex-table list-household-members">
|
||||
{% for m in members %}
|
||||
{% if m.position.shareHousehold %}
|
||||
{% include '@ChillPerson/Household/_render_member.html.twig' with {
|
||||
'member': m,
|
||||
'customButtons': { 'before': _self.customButtons(m, household) }
|
||||
} %}
|
||||
{% else %}
|
||||
{% include '@ChillPerson/Household/_render_member.html.twig' with {
|
||||
'member': m,
|
||||
} %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
|
@ -0,0 +1,11 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock admin_content %}
|
@ -0,0 +1,41 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% embed '@ChillMain/CRUD/_index.html.twig' %}
|
||||
{% block table_entities_thead_tr %}
|
||||
<th>{{ 'Id'|trans }}</th>
|
||||
<th>{{ 'Label'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th> </th>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_entities_tbody %}
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.id }}</td>
|
||||
<td>{{ entity.label|localize_translatable_string }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.isActive -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_person_household_position_edit', { 'id': entity.id }) }}" class="btn btn-edit"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block actions_before %}
|
||||
<li class='cancel'>
|
||||
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans}}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@ -0,0 +1,12 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock admin_content %}
|
||||
|
@ -65,18 +65,18 @@
|
||||
<h3>{{ 'household.Members at same time'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% set simultaneous = p.household.getMembersDuringMembership(p) %}
|
||||
{% set simultaneous = p.household.getPersonsDuringMembership(p) %}
|
||||
{% if simultaneous|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ 'household.Any simultaneous members'|trans }}
|
||||
</p>
|
||||
{% else %}
|
||||
{% for m in simultaneous -%}
|
||||
{% for person in simultaneous -%}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: m.person.id },
|
||||
buttonText: m.person|chill_entity_render_string,
|
||||
isDead: m.person.deathdate is not null
|
||||
targetEntity: { name: 'person', id: person.id },
|
||||
buttonText: person|chill_entity_render_string,
|
||||
isDead: person.deathdate is not null
|
||||
} %}
|
||||
{%- endfor -%}
|
||||
{% endif %}
|
||||
|
@ -1,13 +1,15 @@
|
||||
{% macro button_person_after(person) %}
|
||||
{% set household = person.getCurrentHousehold %}
|
||||
{% if household is not null %}
|
||||
{% if household is not null and is_granted('CHILL_PERSON_HOUSEHOLD_SEE', household) %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_summary', { 'household_id': household.id }) }}" class="btn btn-sm btn-chill-beige"><i class="fa fa-home"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_accompanying_course_new', { 'person_id': [ person.id ]}) }}" class="btn btn-sm btn-create change-icon" title="{{ 'Create an accompanying period'|trans }}"><i class="fa fa-random"></i></a>
|
||||
</li>
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_CREATE', person) %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_accompanying_course_new', { 'person_id': [ person.id ]}) }}" class="btn btn-sm btn-create change-icon" title="{{ 'Create an accompanying period'|trans }}"><i class="fa fa-random"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro accompanying_period(acp, person) %}
|
||||
@ -233,7 +235,8 @@
|
||||
{%- set acpsClosed = [] %}
|
||||
{%- for acp in person.accompanyingPeriodInvolved %}
|
||||
{%- if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_SEE', acp) %}
|
||||
{% if acp.step == 'CLOSED' %}
|
||||
{# filter for "current" periods: either the person is a requestor, or is member of the period and not closed #}
|
||||
{% if acp.step == 'CLOSED' or (acp.requestorPerson is not same as(person) and acp.openParticipationContainsPerson(person) is null ) %}
|
||||
{%- set acpsClosed = acpsClosed|merge([acp]) %}
|
||||
{% else %}
|
||||
{%- set acps = acps|merge([acp]) %}
|
||||
|
@ -118,7 +118,7 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
||||
->generate(self::class)
|
||||
->addCheckFor(null, [self::CREATE, self::REASSIGN_BULK])
|
||||
->addCheckFor(AccompanyingPeriod::class, [self::TOGGLE_CONFIDENTIAL, ...self::ALL])
|
||||
->addCheckFor(Person::class, [self::SEE])
|
||||
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
||||
->build();
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
|
||||
'location' => Address::class,
|
||||
'locationPerson' => Person::class,
|
||||
'administrativeLocation' => Location::class,
|
||||
'pinnedComment' => AccompanyingPeriod\Comment::class,
|
||||
];
|
||||
|
||||
private ClosingMotiveRender $closingMotiveRender;
|
||||
@ -164,6 +165,8 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
|
||||
'location' => $this->normalizer->normalize($period->getLocation(), $format, $addressContext),
|
||||
'administrativeLocation' => $this->normalizer->normalize($period->getAdministrativeLocation(), $format, $administrativeLocationContext),
|
||||
'works' => $this->normalizer->normalize($period->getWorks(), $format, $workContext),
|
||||
'comments' => $this->normalizer->normalize($period->getComments(), $format, array_merge($context, ['docgen:expects' => AccompanyingPeriod\Comment::class])),
|
||||
'pinnedComment' => $this->normalizer->normalize($period->getPinnedComment(), $format, array_merge($context, ['docgen:expects' => AccompanyingPeriod\Comment::class])),
|
||||
];
|
||||
}
|
||||
|
||||
@ -183,6 +186,7 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
|
||||
'hasLocationPerson' => false,
|
||||
'hasAdministrativeLocation' => false,
|
||||
'works' => [],
|
||||
'comments' => [],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -135,4 +135,51 @@ final class HouseholdTest extends TestCase
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $second->getStartDate());
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $inside->getEndDate());
|
||||
}
|
||||
|
||||
public function testHouseholdGetPersonsDuringMembership()
|
||||
{
|
||||
$household = new Household();
|
||||
$person1 = new Person();
|
||||
$person2 = new Person();
|
||||
$personOut = new Person();
|
||||
|
||||
$household->addMember(
|
||||
$member1 = (new HouseholdMember())
|
||||
->setStartDate(new DateTimeImmutable('2021-01-01'))
|
||||
->setEndDate(new DateTimeImmutable('2021-12-01'))
|
||||
->setPerson($person1)
|
||||
);
|
||||
|
||||
$household->addMember(
|
||||
$member2a = (new HouseholdMember())
|
||||
->setStartDate(new DateTimeImmutable('2021-01-01'))
|
||||
->setEndDate(new DateTimeImmutable('2021-05-01'))
|
||||
->setPerson($person2)
|
||||
);
|
||||
|
||||
$household->addMember(
|
||||
$member2b = (new HouseholdMember())
|
||||
->setStartDate(new DateTimeImmutable('2021-11-01'))
|
||||
->setEndDate(new DateTimeImmutable('2022-06-01'))
|
||||
->setPerson($person2)
|
||||
);
|
||||
|
||||
$household->addMember(
|
||||
$memberOut = (new HouseholdMember())
|
||||
->setStartDate(new DateTimeImmutable('2019-01-01'))
|
||||
->setEndDate(new DateTimeImmutable('2019-12-01'))
|
||||
->setPerson($personOut)
|
||||
);
|
||||
|
||||
$this->assertCount(0, $household->getPersonsDuringMembership($memberOut));
|
||||
|
||||
$this->assertCount(1, $household->getPersonsDuringMembership($member1));
|
||||
$this->assertContains($person2, $household->getPersonsDuringMembership($member1));
|
||||
|
||||
$this->assertCount(1, $household->getPersonsDuringMembership($member2a));
|
||||
$this->assertContains($person1, $household->getPersonsDuringMembership($member2a));
|
||||
|
||||
$this->assertCount(1, $household->getPersonsDuringMembership($member2b));
|
||||
$this->assertContains($person1, $household->getPersonsDuringMembership($member2b));
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ final class AccompanyingPeriodDocGenNormalizerTest extends KernelTestCase
|
||||
'closingMotive' => '@ignored',
|
||||
'confidential' => true,
|
||||
'confidentialText' => 'confidentiel',
|
||||
'comments' => '@ignored',
|
||||
'pinnedComment' => '@ignored',
|
||||
'createdAt' => '@ignored',
|
||||
'createdBy' => '@ignored',
|
||||
'emergency' => true,
|
||||
|
@ -468,6 +468,12 @@ crud:
|
||||
add_new: Ajouter un nouveau
|
||||
title_new: Nouvelle position
|
||||
title_edit: Modifier la position
|
||||
person_household_composition_type:
|
||||
index:
|
||||
title: Composition
|
||||
add_new: Ajouter un nouveau
|
||||
title_new: Nouvelle composition
|
||||
title_edit: Modifier la composition
|
||||
person_relation:
|
||||
index:
|
||||
title: Relations de filiations
|
||||
|
Loading…
x
Reference in New Issue
Block a user