mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 17:28:23 +00:00 
			
		
		
		
	Merge branch 'feature/household-accept-members-without-position' into 'master'
An household can have members without position See merge request Chill-Projet/chill-bundles!189
This commit is contained in:
		| @@ -245,6 +245,16 @@ class Household | ||||
|         $members->getIterator() | ||||
|             ->uasort( | ||||
|                 function (HouseholdMember $a, HouseholdMember $b) { | ||||
|                     if ($a->getPosition() === NULL) { | ||||
|                         if ($b->getPosition() === NULL) { | ||||
|                             return 0; | ||||
|                         } else { | ||||
|                             return -1; | ||||
|                         } | ||||
|                     } elseif ($b->getPosition() === NULL) { | ||||
|                         return 1; | ||||
|                     } | ||||
|  | ||||
|                     if ($a->getPosition()->getOrdering() < $b->getPosition()->getOrdering()) { | ||||
|                         return -1; | ||||
|                     } | ||||
| @@ -334,6 +344,26 @@ class Household | ||||
|         return $this->getNonCurrentMembers($now)->matching($criteria); | ||||
|     } | ||||
|  | ||||
|     public function getCurrentMembersWithoutPosition(\DateTimeInterface $now = null) | ||||
|     { | ||||
|         $criteria = new Criteria(); | ||||
|         $expr = Criteria::expr(); | ||||
|  | ||||
|         $criteria->where($expr->isNull('position')); | ||||
|  | ||||
|         return $this->getCurrentMembers($now)->matching($criteria); | ||||
|     } | ||||
|  | ||||
|     public function getNonCurrentMembersWithoutPosition(\DateTimeInterface $now = null) | ||||
|     { | ||||
|         $criteria = new Criteria(); | ||||
|         $expr = Criteria::expr(); | ||||
|  | ||||
|         $criteria->where($expr->isNull('position')); | ||||
|  | ||||
|         return $this->getNonCurrentMembers($now)->matching($criteria); | ||||
|     } | ||||
|  | ||||
|     public function addMember(HouseholdMember $member): self | ||||
|     { | ||||
|         if (!$this->members->contains($member)) { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ class HouseholdMember | ||||
|     /** | ||||
|      * @ORM\ManyToOne(targetEntity=Position::class) | ||||
|      * @Serializer\Groups({"read"}) | ||||
|      * @Assert\NotNull(groups={"household_memberships"}) | ||||
|      * @Assert\NotNull(groups={"household_memberships_created"}) | ||||
|      */ | ||||
|     private ?Position $position = null; | ||||
|  | ||||
|   | ||||
| @@ -19,15 +19,17 @@ class MembersEditor | ||||
|  | ||||
|     private array $persistables = []; | ||||
|     private array $membershipsAffected = []; | ||||
|     private array $oldMembershipsHashes = []; | ||||
|  | ||||
|     public const VALIDATION_GROUP = 'household_memberships'; | ||||
|     public const VALIDATION_GROUP_CREATED = 'household_memberships_created'; | ||||
|     public const VALIDATION_GROUP_AFFECTED = 'household_memberships'; | ||||
|  | ||||
|     public function __construct(ValidatorInterface $validator, ?Household $household) | ||||
|     { | ||||
|         $this->validator = $validator; | ||||
|         $this->household = $household; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     public function addMovement(\DateTimeImmutable $date, Person $person, Position $position, ?bool $holder = false, ?string $comment = null): self | ||||
|     { | ||||
|         if (NULL === $this->household) { | ||||
| @@ -56,6 +58,7 @@ class MembersEditor | ||||
|                 if ($participation->getEndDate() === NULL || $participation->getEndDate() > $date) { | ||||
|                     $participation->setEndDate($date); | ||||
|                     $this->membershipsAffected[] = $participation; | ||||
|                     $this->oldMembershipsHashes[] = \spl_object_hash($participation); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -97,13 +100,18 @@ class MembersEditor | ||||
|     { | ||||
|         if ($this->hasHousehold()) { | ||||
|             $list = $this->validator | ||||
|                 ->validate($this->getHousehold(), null, [ self::VALIDATION_GROUP ]); | ||||
|                 ->validate($this->getHousehold(), null, [ self::VALIDATION_GROUP_AFFECTED ]); | ||||
|         } else { | ||||
|             $list = new ConstraintViolationList(); | ||||
|         } | ||||
|  | ||||
|         foreach ($this->membershipsAffected as $m) { | ||||
|             $list->addAll($this->validator->validate($m, null, [ self::VALIDATION_GROUP ])); | ||||
|             if (\in_array(\spl_object_hash($m), $this->oldMembershipsHashes)) { | ||||
|                 $list->addAll($this->validator->validate($m, null, [ self::VALIDATION_GROUP_AFFECTED ])); | ||||
|             } else { | ||||
|                 $list->addAll($this->validator->validate($m, null, [ self::VALIDATION_GROUP_CREATED, | ||||
|                     self::VALIDATION_GROUP_AFFECTED ])); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $list; | ||||
|   | ||||
| @@ -22,8 +22,11 @@ | ||||
|  | ||||
|                             {%- for m in members -%} | ||||
|                                 <span | ||||
|                                     class="badge-member{%- if m.holder %} holder{% endif -%}{%- if m.position.ordering >= 2 %} child{% endif -%}" | ||||
|                                     title="{{ m.position.label.fr }}"> | ||||
|                                     class="badge-member{%- if m.holder %} holder{% endif -%}" | ||||
|                                     {% if m.position is not null %} | ||||
|                                         title="{{ m.position.label.fr }}" | ||||
|                                     {% endif %} | ||||
|                                 > | ||||
|                                     <a href="{{ path('chill_person_view', { person_id: m.person.id}) }}"> | ||||
|                                         {%- if m.holder %} | ||||
|                                             <span class="fa-stack fa-holder" title="{{ 'household.holder'|trans }}"> | ||||
|   | ||||
| @@ -106,81 +106,95 @@ | ||||
|  | ||||
|     <h2 class="my-5">{{ 'household.Household members'|trans }}</h2> | ||||
|  | ||||
|     {% for p in positions %} | ||||
|     <div class="mb-5"> | ||||
|       <h3>{{ p.label|localize_translatable_string }} | ||||
|           {% if false == p.shareHousehold %} | ||||
|               <i class="chill-help-tooltip" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" | ||||
|                  title="{{ 'household.Those members does not share address'|trans }}"></i> | ||||
|           {% endif %} | ||||
|       </h3> | ||||
|     {% for p in positions|merge([ '_none' ]) %} | ||||
|  | ||||
|       {%- set members = household.currentMembersByPosition(p) %} | ||||
|         {% if p == '_none' %} | ||||
|             {% set members = household.currentMembersWithoutPosition %} | ||||
|             {% set old_members = household.nonCurrentMembersWithoutPosition %} | ||||
|         {% else %} | ||||
|             {%- set members = household.currentMembersByPosition(p) %} | ||||
|             {% set old_members = household.nonCurrentMembersByPosition(p) %} | ||||
|         {% endif %} | ||||
|  | ||||
|       {% macro customButtons(member, household) %} | ||||
|           <li> | ||||
|               <a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'allow_leave_without_household': true } ) }}" | ||||
|                  class="btn btn-sm btn-unlink" title="{{ 'household.person.leave'|trans }}"></a> | ||||
|           </li> | ||||
|           <li> | ||||
|               <a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'household': household.id} ) }}" | ||||
|                  class="btn btn-sm btn-misc" title="{{ 'household.Change position'|trans }}"><i class="fa fa-arrows-h"></i></a> | ||||
|           </li> | ||||
|       {% endmacro %} | ||||
|         {% if not (p == '_none' and members|length == 0 and old_members|length == 0) %} | ||||
|             <div class="mb-5"> | ||||
|                 {% if p != '_none' %} | ||||
|                   <h3>{{ p.label|localize_translatable_string }} | ||||
|                       {% if false == p.shareHousehold %} | ||||
|                           <i class="chill-help-tooltip" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" | ||||
|                              title="{{ 'household.Those members does not share address'|trans }}"></i> | ||||
|                       {% endif %} | ||||
|                   </h3> | ||||
|                 {% else %} | ||||
|                     <h3 class="chill-entity">{{ 'household.Members without position'|trans }}</h3> | ||||
|                 {% endif %} | ||||
|  | ||||
|       {% if members|length > 0 %} | ||||
|         <div class="flex-table list-household-members"> | ||||
|           {% for m in members %} | ||||
|               {% include '@ChillPerson/Household/_render_member.html.twig' with { | ||||
|                   'member': m, | ||||
|                   'customButtons': { 'after': _self.customButtons(m, household) } | ||||
|               } %} | ||||
|           {% endfor %} | ||||
|         </div> | ||||
|       {% else %} | ||||
|         <p class="chill-no-data-statement">{{ 'household.Any persons into this position'|trans }}</p> | ||||
|       {% endif %} | ||||
|  | ||||
|       {% set members = household.nonCurrentMembersByPosition(p) %} | ||||
|       {% if members|length > 0 %} | ||||
|               {% macro customButtons(member, household) %} | ||||
|                   <li> | ||||
|                       <a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'allow_leave_without_household': true } ) }}" | ||||
|                          class="btn btn-sm btn-unlink" title="{{ 'household.person.leave'|trans }}"></a> | ||||
|                   </li> | ||||
|                   <li> | ||||
|                       <a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'household': household.id} ) }}" | ||||
|                          class="btn btn-sm btn-misc" title="{{ 'household.Change position'|trans }}"><i class="fa fa-arrows-h"></i></a> | ||||
|                   </li> | ||||
|               {% endmacro %} | ||||
|  | ||||
|         <style> | ||||
|             button[aria-expanded="true"] > span.folded, | ||||
|             button[aria-expanded="false"] > span.unfolded { display: none; } | ||||
|             button[aria-expanded="false"] > span.folded, | ||||
|             button[aria-expanded="true"] > span.unfolded { display: inline; } | ||||
|         </style> | ||||
|         <div class="accordion" id="nonCurrent"> | ||||
|             <div class="accordion-item"> | ||||
|                 <h2 class="accordion-header" id="heading_{{ p.id }}"> | ||||
|                     <button | ||||
|                         class="accordion-button collapsed" | ||||
|                         type="button" | ||||
|                         data-bs-toggle="collapse" | ||||
|                         data-bs-target="#collapse_{{ p.id }}" | ||||
|                         aria-expanded="false" | ||||
|                         aria-controls="collapse_{{ p.id }}"> | ||||
|                         <span class="folded">{{ 'household.Show future or past memberships'|trans({'length': members|length}) }}</span> | ||||
|                         <span class="unfolded text-secondary">{{ 'household.Hide memberships'|trans }}</span> | ||||
|                     </button> | ||||
|                 </h2> | ||||
|                 <div id="collapse_{{ p.id }}" | ||||
|                     class="accordion-collapse collapse" | ||||
|                     aria-labelledby="heading_{{ p.id }}" | ||||
|                     data-bs-parent="#nonCurrent"> | ||||
|                     <div class="flex-table my-0 list-household-members"> | ||||
|                         {% for m in members %} | ||||
|                             {% include '@ChillPerson/Household/_render_member.html.twig' with { 'member': m } %} | ||||
|                         {% endfor %} | ||||
|               {% if members|length > 0 %} | ||||
|                 <div class="flex-table list-household-members"> | ||||
|                   {% for m in members %} | ||||
|                       {% include '@ChillPerson/Household/_render_member.html.twig' with { | ||||
|                           'member': m, | ||||
|                           'customButtons': { 'after': _self.customButtons(m, household) } | ||||
|                       } %} | ||||
|                   {% endfor %} | ||||
|                 </div> | ||||
|               {% else %} | ||||
|                 <p class="chill-no-data-statement">{{ 'household.Any persons into this position'|trans }}</p> | ||||
|               {% endif %} | ||||
|  | ||||
|               {% if old_members|length > 0 %} | ||||
|                 <style> | ||||
|                     button[aria-expanded="true"] > span.folded, | ||||
|                     button[aria-expanded="false"] > span.unfolded { display: none; } | ||||
|                     button[aria-expanded="false"] > span.folded, | ||||
|                     button[aria-expanded="true"] > span.unfolded { display: inline; } | ||||
|                 </style> | ||||
|                 <div class="accordion" id="nonCurrent"> | ||||
|                     <div class="accordion-item"> | ||||
|                         <h2 class="accordion-header" id="heading_{{ p == '_none' ? '_none' : p.id }}"> | ||||
|                             <button | ||||
|                                 class="accordion-button collapsed" | ||||
|                                 type="button" | ||||
|                                 data-bs-toggle="collapse" | ||||
|                                 data-bs-target="#collapse_{{ p == '_none' ? '_none' : p.id }}" | ||||
|                                 aria-expanded="false" | ||||
|                                 aria-controls="collapse_{{ p == '_none' ? '_none' : p.id }}"> | ||||
|                                 <span class="folded">{{ 'household.Show future or past memberships'|trans({'length': old_members|length}) }}</span> | ||||
|                                 <span class="unfolded text-secondary">{{ 'household.Hide memberships'|trans }}</span> | ||||
|                             </button> | ||||
|                         </h2> | ||||
|                         <div id="collapse_{{ p == '_none' ? '_none' : p.id }}" | ||||
|                             class="accordion-collapse collapse" | ||||
|                             aria-labelledby="heading_{{ p == '_none' ? '_none' : p.id }}" | ||||
|                             data-bs-parent="#nonCurrent"> | ||||
|                             <div class="flex-table my-0 list-household-members"> | ||||
|                                 {% for m in old_members %} | ||||
|                                     {% include '@ChillPerson/Household/_render_member.html.twig' with { 'member': m } %} | ||||
|                                 {% endfor %} | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|       {% endif %} | ||||
|               {% endif %} | ||||
|  | ||||
|     </div> | ||||
|             </div> | ||||
|         {% endif %} | ||||
|     {% endfor %} | ||||
|  | ||||
|  | ||||
|  | ||||
|     <ul class="record_actions"> | ||||
|       <li> | ||||
|         <a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'household': household.id }) }}" | ||||
|   | ||||
| @@ -77,6 +77,7 @@ household: | ||||
|     Household history for %name%: Historique des ménages pour {name} | ||||
|     Household shared: Ménages domiciliés | ||||
|     Household not shared: Ménage non domiciliés | ||||
|     Members without position: Membres non positionnés | ||||
|     Never in any household: Membre d'aucun ménage | ||||
|     Membership currently running: En cours | ||||
|     from: Depuis | ||||
|   | ||||
		Reference in New Issue
	
	Block a user