mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +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:
commit
e1677cd2b6
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user