mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/master' into issue541_change_moving_date
This commit is contained in:
@@ -514,6 +514,8 @@ class Household
|
||||
|
||||
if ($iterator->valid()) {
|
||||
$current->setValidTo($iterator->current()->getValidFrom());
|
||||
} else {
|
||||
$current->setValidTo(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -276,25 +276,21 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
/**
|
||||
* The person's first name.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Assert\NotBlank(message="The firstname cannot be empty")
|
||||
* @Assert\Length(
|
||||
* max=255,
|
||||
* )
|
||||
*/
|
||||
private $firstName;
|
||||
private string $firstName = '';
|
||||
|
||||
/**
|
||||
* fullname canonical. Read-only field, which is calculated by
|
||||
* the database.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
*/
|
||||
private $fullnameCanonical;
|
||||
private string $fullnameCanonical = '';
|
||||
|
||||
/**
|
||||
* The person's gender.
|
||||
@@ -328,6 +324,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* targetEntity=HouseholdMember::class,
|
||||
* mappedBy="person"
|
||||
* )
|
||||
*
|
||||
* @var Collection|HouseholdMember[]
|
||||
*/
|
||||
private Collection $householdParticipations;
|
||||
|
||||
@@ -343,15 +341,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
/**
|
||||
* The person's last name.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Assert\NotBlank(message="The lastname cannot be empty")
|
||||
* @Assert\Length(
|
||||
* max=255,
|
||||
* )
|
||||
*/
|
||||
private $lastName;
|
||||
private string $lastName = '';
|
||||
|
||||
/**
|
||||
* The marital status of the person.
|
||||
@@ -1117,6 +1113,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
return $this->householdAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|HouseholdMember[]
|
||||
*/
|
||||
public function getHouseholdParticipations(): Collection
|
||||
{
|
||||
return $this->householdParticipations;
|
||||
@@ -1126,6 +1125,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* Get participation where the person does not share the household.
|
||||
*
|
||||
* Order by startDate, desc
|
||||
*
|
||||
* @return HouseholdMember[]
|
||||
*/
|
||||
public function getHouseholdParticipationsNotShareHousehold(): Collection
|
||||
{
|
||||
@@ -1146,6 +1147,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* Get participation where the person does share the household.
|
||||
*
|
||||
* Order by startDate, desc
|
||||
*
|
||||
* @return Collection|HouseholdMember[]
|
||||
*/
|
||||
public function getHouseholdParticipationsShareHousehold(): Collection
|
||||
{
|
||||
@@ -1565,18 +1568,14 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
|
||||
public function setEmail(?string $email): self
|
||||
{
|
||||
if (null === $email) {
|
||||
$email = '';
|
||||
}
|
||||
|
||||
$this->email = $email;
|
||||
$this->email = trim((string) $email);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFirstName(string $firstName): self
|
||||
public function setFirstName(?string $firstName): self
|
||||
{
|
||||
$this->firstName = $firstName;
|
||||
$this->firstName = (string) $firstName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -1602,9 +1601,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLastName(string $lastName): self
|
||||
public function setLastName(?string $lastName): self
|
||||
{
|
||||
$this->lastName = $lastName;
|
||||
$this->lastName = (string) $lastName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -29,8 +29,12 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final class PersonResourceType extends AbstractType
|
||||
{
|
||||
private PersonRenderInterface $personRender;
|
||||
|
||||
private ResourceKindRender $resourceKindRender;
|
||||
|
||||
private ThirdPartyRender $thirdPartyRender;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(ResourceKindRender $resourceKindRender, PersonRenderInterface $personRender, ThirdPartyRender $thirdPartyRender, TranslatorInterface $translator)
|
||||
|
@@ -61,8 +61,6 @@ class MembersEditor
|
||||
throw new LogicException('You must define a household first');
|
||||
}
|
||||
|
||||
$event = new PersonAddressMoveEvent($person);
|
||||
|
||||
$membership = (new HouseholdMember())
|
||||
->setStartDate($date)
|
||||
->setPerson($person)
|
||||
@@ -70,9 +68,15 @@ class MembersEditor
|
||||
->setHolder($holder)
|
||||
->setComment($comment);
|
||||
$this->household->addMember($membership);
|
||||
$event->setNextMembership($membership);
|
||||
|
||||
if ($position->getShareHousehold()) {
|
||||
// launch event only if moving to a "share household" position,
|
||||
// and if the destination household is different than the previous one
|
||||
$event = new PersonAddressMoveEvent($person);
|
||||
$event->setNextMembership($membership);
|
||||
|
||||
$counter = 0;
|
||||
|
||||
foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) {
|
||||
if ($participation === $membership) {
|
||||
continue;
|
||||
@@ -82,14 +86,25 @@ class MembersEditor
|
||||
continue;
|
||||
}
|
||||
|
||||
++$counter;
|
||||
|
||||
if ($participation->getEndDate() === null || $participation->getEndDate() > $date) {
|
||||
$event->setPreviousMembership($participation);
|
||||
$participation->setEndDate($date);
|
||||
$this->membershipsAffected[] = $participation;
|
||||
$this->oldMembershipsHashes[] = spl_object_hash($participation);
|
||||
|
||||
if ($participation->getHousehold() !== $this->household) {
|
||||
$event->setPreviousMembership($participation);
|
||||
$this->events[] = $event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send also the event if there was no participation before
|
||||
if (0 === $counter) {
|
||||
$this->events[] = $event;
|
||||
}
|
||||
|
||||
foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
|
||||
if ($participation->getHousehold() === $this->household
|
||||
&& $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()
|
||||
@@ -98,11 +113,30 @@ class MembersEditor
|
||||
$participation->setEndDate($membership->getStartDate());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if a members is moved to the same household than the one he belongs to,
|
||||
// we should make it leave the household
|
||||
if ($person->getCurrentHousehold($date) === $this->household) {
|
||||
$this->leaveMovement($date, $person);
|
||||
}
|
||||
|
||||
// if there are multiple belongings not sharing household, close the others
|
||||
foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
|
||||
if ($participation === $membership) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($participation->getHousehold() === $this->household
|
||||
&& ($participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate())
|
||||
&& $participation->getStartDate() <= $membership->getStartDate()
|
||||
) {
|
||||
$participation->setEndDate($membership->getStartDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->membershipsAffected[] = $membership;
|
||||
$this->persistables[] = $membership;
|
||||
$this->events[] = $event;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -88,7 +88,7 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
||||
->setExtras([
|
||||
'order' => 99999,
|
||||
]);
|
||||
|
||||
/*
|
||||
$menu->addChild($this->translator->trans('Person duplicate'), [
|
||||
'route' => 'chill_person_duplicate_view',
|
||||
'routeParameters' => [
|
||||
@@ -98,7 +98,7 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
||||
->setExtras([
|
||||
'order' => 99999,
|
||||
]);
|
||||
|
||||
*/
|
||||
if (
|
||||
'visible' === $this->showAccompanyingPeriod
|
||||
&& $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person'])
|
||||
|
@@ -136,8 +136,11 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
||||
$andWhereSearchClause = [];
|
||||
$andWhereSearchClauseArgs = [];
|
||||
|
||||
if ('' !== $default) {
|
||||
if ('' !== trim($default)) {
|
||||
foreach (explode(' ', $default) as $str) {
|
||||
if ('' === trim($str)) {
|
||||
continue;
|
||||
}
|
||||
$pertinence[] =
|
||||
'STRICT_WORD_SIMILARITY(LOWER(UNACCENT(?)), person.fullnamecanonical) + ' .
|
||||
"(person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%')::int + " .
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<label class="chill-no-data-statement">{{ $tc('resources.counter', counter) }}</label>
|
||||
</div>
|
||||
|
||||
<div class="flex-bloc mb-3">
|
||||
<div class="flex-table mb-3">
|
||||
<resource-item
|
||||
v-for="resource in resources"
|
||||
v-bind:resource="resource"
|
||||
|
@@ -138,12 +138,12 @@
|
||||
@go-to-generate-document="submitBeforeGenerate"
|
||||
>
|
||||
<template v-slot:title>
|
||||
<label class="col-sm-4 col-form-label">{{ $t('evaluation_generate_a_document') }}</label>
|
||||
<label class="col-form-label">{{ $t('evaluation_generate_a_document') }}</label>
|
||||
</template>
|
||||
</pick-template>
|
||||
<div>
|
||||
<label class="col-sm-4 col-form-label">{{ $t('document_upload') }}</label>
|
||||
<ul class="record_actions">
|
||||
<label class="col-form-label">{{ $t('document_upload') }}</label>
|
||||
<ul class="record_actions document-upload">
|
||||
<li>
|
||||
<add-async-upload
|
||||
:buttonTitle="$t('browse')"
|
||||
@@ -411,8 +411,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
input.document-title{
|
||||
input.document-title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
ul.document-upload {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
</style>
|
||||
|
@@ -45,7 +45,7 @@ const searchPersons = ({ query, options }, signal) => {
|
||||
const searchEntities = ({ query, options }, signal) => {
|
||||
let queryStr = parametersToString({ query, options });
|
||||
let url = `/api/1.0/search.json?${queryStr}`;
|
||||
return fetch(url)
|
||||
return fetch(url, { signal })
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
|
@@ -199,15 +199,26 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (query === this.search.query) {
|
||||
if (this.currentSearchQueryController !== undefined) {
|
||||
this.currentSearchQueryController.abort()
|
||||
if (this.search.currentSearchQueryController !== null) {
|
||||
this.search.currentSearchQueryController.abort();
|
||||
}
|
||||
this.currentSearchQueryController = new AbortController();
|
||||
searchEntities({ query, options: this.options }, this.currentSearchQueryController)
|
||||
.then(suggested => new Promise((resolve, reject) => {
|
||||
this.loadSuggestions(suggested.results);
|
||||
resolve();
|
||||
}));
|
||||
this.search.currentSearchQueryController = new AbortController();
|
||||
searchEntities({ query, options: this.options }, this.search.currentSearchQueryController.signal)
|
||||
.then(suggested => new Promise((resolve, reject) => {
|
||||
this.loadSuggestions(suggested.results);
|
||||
resolve();
|
||||
}))
|
||||
.catch(error => {
|
||||
if (error instanceof DOMException) {
|
||||
if (error.name === 'AbortError') {
|
||||
console.log('request aborted due to user continue typing');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
})
|
||||
;
|
||||
}
|
||||
}.bind(this), query.length > 3 ? 300 : 700);
|
||||
},
|
||||
|
@@ -1,16 +1,19 @@
|
||||
<div class="alert alert-warning alert-with-actions">
|
||||
<div class="float-button bottom"><div class="box">
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_accompanying_course_edit', { 'accompanying_period_id': accompanyingCourse.id, '_fragment': 'section-10' }) }}">
|
||||
<i class="fa fa-fw fa-crosshairs"></i>
|
||||
{{ 'fix it'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="float-button bottom">
|
||||
<div class="box">
|
||||
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_accompanying_course_edit', { 'accompanying_period_id': accompanyingCourse.id, '_fragment': 'section-10' }) }}">
|
||||
<i class="fa fa-fw fa-crosshairs"></i>
|
||||
{{ 'fix it'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>{{ 'Some peoples does not belong to any household currently. Add them to an household soon'|trans }}</p>
|
||||
</div>
|
||||
{{ 'Some peoples does not belong to any household currently. Add them to an household soon'|trans }}
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -184,25 +184,27 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mbloc col col-sm-6 col-lg-4">
|
||||
<div class="notification-counter">
|
||||
<h4 class="item-key">{{ 'notification.Notifications'|trans }}</h4>
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<div class="my-2">
|
||||
<a href="#notification-list">
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) }}
|
||||
|
||||
{% if accompanyingCourse.step != 'DRAFT' %}
|
||||
<div class="mbloc col col-sm-6 col-lg-4">
|
||||
<div class="notification-counter">
|
||||
<h4 class="item-key">{{ 'notification.Notifications'|trans }}</h4>
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<div class="my-2">
|
||||
<a href="#notification-list">
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-grid gap-2">
|
||||
<a class="btn btn-notify" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod', 'entityId': accompanyingCourse.id}) }}">
|
||||
{{ 'notification.Notify'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-grid gap-2">
|
||||
<a class="btn btn-notify" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod', 'entityId': accompanyingCourse.id}) }}">
|
||||
{{ 'notification.Notify'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="social-actions my-4">
|
||||
@@ -228,7 +230,7 @@
|
||||
{% include 'ChillActivityBundle:Activity:list_recent.html.twig' with { 'context': 'accompanyingCourse', 'no_action': true } %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
<div class="notification notification-list">
|
||||
{% set notifications = chill_list_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) %}
|
||||
{% if notifications is not empty %}
|
||||
|
@@ -128,11 +128,13 @@
|
||||
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork',
|
||||
w.id, [], suppEvaluations) }}
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
|
||||
></a>
|
||||
</li>
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', w) %}
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
|
||||
></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_DELETE', w) %}
|
||||
<li>
|
||||
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
|
||||
|
@@ -18,13 +18,7 @@
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
{% if works|length == 0 %}
|
||||
<p class="chill-no-data-statement">{{ 'accompanying_course_work.Any work'|trans }}
|
||||
<a class="btn btn-sm btn-create"
|
||||
title="{{ 'accompanying_course_work.create'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_new', { 'id': accompanyingCourse.id }) }}"
|
||||
></a>
|
||||
</p>
|
||||
|
||||
<p class="chill-no-data-statement">{{ 'accompanying_course_work.Any work'|trans }}</p>
|
||||
{% else %}
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
{% for w in works %}
|
||||
@@ -35,6 +29,7 @@
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_CREATE', accompanyingCourse) %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_new', { 'id': accompanyingCourse.id }) }}"
|
||||
@@ -43,6 +38,7 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@@ -116,14 +116,40 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="item-row separator">
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<div class="item-col item-meta">
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) }}
|
||||
|
||||
{% if show_pinned_comment|default(false) and period.pinnedComment is not empty%}
|
||||
<div class="item-row separator comment">
|
||||
<div style="width: 100%">
|
||||
<h4 class="item-key visually-hidden">{{ 'Pinned comment'|trans }}</h4>
|
||||
<blockquote class="chill-user-quote">
|
||||
{{ period.pinnedComment.content|u.truncate(750, '…', false)|chill_markdown_to_html }}
|
||||
{% if period.pinnedComment.content|length > 750 %}
|
||||
<a href="{{ chill_path_add_return_path('chill_person_accompanying_period_comment_list', {'accompanying_period_id': period.id}) }}">{{ 'Read more'|trans }}</a>
|
||||
{% endif %}
|
||||
<div class="metadata">
|
||||
{{ 'Last updated by'| trans }}
|
||||
<span class="user">
|
||||
{{ period.pinnedComment.updatedBy|chill_entity_render_box }}
|
||||
</span>
|
||||
{{ 'on'|trans ~ ' ' }}
|
||||
<span class="date">
|
||||
{{ period.pinnedComment.updatedAt|format_datetime("medium", "short") }}
|
||||
</span>
|
||||
</div>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if itemMeta is defined %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="item-row separator">
|
||||
{% if itemMeta is not defined %}
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
<div class="item-col item-meta">
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ itemMeta }}
|
||||
{% endif %}
|
||||
<div class="item-col">
|
||||
|
@@ -1,133 +1,139 @@
|
||||
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
|
||||
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
<div class="item-bloc evaluation-item bg-chill-llight-gray">
|
||||
<div class="item-row mb-2">
|
||||
<h1>{{ doc.title }}</h1>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
<span class="title_action">
|
||||
{{ evaluation.accompanyingPeriodWork.socialAction|chill_entity_render_string }}
|
||||
<ul class="small_in_title columns mt-1">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if evaluation.accompanyingPeriodWork.endDate %}
|
||||
{% if doc is null %}
|
||||
<div class="alert alert-warning">
|
||||
{{ 'workflow.doc for evaluation deleted'|trans }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
<div class="item-bloc evaluation-item bg-chill-llight-gray">
|
||||
<div class="item-row mb-2">
|
||||
<h1>{{ doc.title }}</h1>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
<span class="title_action">
|
||||
{{ evaluation.accompanyingPeriodWork.socialAction|chill_entity_render_string }}
|
||||
<ul class="small_in_title columns mt-1">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.endDate|format_date('short') }}</b>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<div class="item-col" style="width: 17%;">
|
||||
<h4 class="title_label">
|
||||
{{ 'Participants'|trans }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="item-col list">
|
||||
{% for p in evaluation.accompanyingPeriodWork.persons %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: p.deathdate is not null
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row column">
|
||||
<table class="obj-res-eval my-3" style="font-size: 110% !important;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="eval">
|
||||
<h4 class="title_label">
|
||||
{{ 'Évaluation'|trans }}
|
||||
</h4>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="eval">
|
||||
<ul class="eval_title">
|
||||
<li class="my-2">
|
||||
{{ evaluation.evaluation.title|localize_translatable_string }}
|
||||
<ul class="columns pt-2">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if evaluation.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.maxDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.maxDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.warningInterval and evaluation.warningInterval.d > 0 %}
|
||||
<li>
|
||||
{% set days = (evaluation.warningInterval.d + evaluation.warningInterval.m * 30) %}
|
||||
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
|
||||
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{% if evaluation.createdBy is not null %}
|
||||
<span class="item-key">créé par</span>
|
||||
<b>{{ evaluation.createdBy.username }}</b>
|
||||
{% endif %}
|
||||
{% if evaluation.createdAt is not null %}
|
||||
<span class="item-key">{{ 'le'|trans }}</span>
|
||||
<b>{{ evaluation.createdAt|format_date('short') }}</b>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
{% if evaluation.comment %}
|
||||
<blockquote class="chill-user-quote" style="margin-left: 0;">
|
||||
{{ evaluation.comment }}
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
{% if evaluation.accompanyingPeriodWork.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(evaluation) }}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<div class="item-col" style="width: 17%;">
|
||||
<h4 class="title_label">
|
||||
{{ 'Participants'|trans }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="item-col list">
|
||||
{% for p in evaluation.accompanyingPeriodWork.persons %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: p.deathdate is not null
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row column">
|
||||
<table class="obj-res-eval my-3" style="font-size: 110% !important;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="eval">
|
||||
<h4 class="title_label">
|
||||
{{ 'Évaluation'|trans }}
|
||||
</h4>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="eval">
|
||||
<ul class="eval_title">
|
||||
<li class="my-2">
|
||||
{{ evaluation.evaluation.title|localize_translatable_string }}
|
||||
<ul class="columns pt-2">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if evaluation.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.maxDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.maxDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.warningInterval and evaluation.warningInterval.d > 0 %}
|
||||
<li>
|
||||
{% set days = (evaluation.warningInterval.d + evaluation.warningInterval.m * 30) %}
|
||||
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
|
||||
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{% if evaluation.createdBy is not null %}
|
||||
<span class="item-key">créé par</span>
|
||||
<b>{{ evaluation.createdBy.username }}</b>
|
||||
{% endif %}
|
||||
{% if evaluation.createdAt is not null %}
|
||||
<span class="item-key">{{ 'le'|trans }}</span>
|
||||
<b>{{ evaluation.createdAt|format_date('short') }}</b>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
{% if evaluation.comment %}
|
||||
<blockquote class="chill-user-quote" style="margin-left: 0;">
|
||||
{{ evaluation.comment }}
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(evaluation) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if display_action is defined and display_action == true %}
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork) %}
|
||||
<ul class="record_actions">
|
||||
<li>{{ m.download_button(doc.storedObject, doc.title) }}</li>
|
||||
{% if chill_document_is_editable(doc.storedObject) %}
|
||||
{% if display_action is defined and display_action == true %}
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork) %}
|
||||
<ul class="record_actions">
|
||||
<li>{{ m.download_button(doc.storedObject, doc.title) }}</li>
|
||||
{% if chill_document_is_editable(doc.storedObject) %}
|
||||
<li>
|
||||
{{ doc.storedObject|chill_document_edit_button }}
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{{ doc.storedObject|chill_document_edit_button }}
|
||||
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
|
||||
{{ 'Show'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
|
||||
{{ 'Show'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@@ -11,7 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\BudgetBundle\Service\Summary\SummaryBudget;
|
||||
use Chill\BudgetBundle\Service\Summary\SummaryBudgetInterface;
|
||||
use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\Civility;
|
||||
@@ -23,6 +23,7 @@ use Chill\PersonBundle\Repository\Relationships\RelationshipRepository;
|
||||
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use libphonenumber\PhoneNumber;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
@@ -45,7 +46,7 @@ class PersonDocGenNormalizer implements
|
||||
|
||||
private RelationshipRepository $relationshipRepository;
|
||||
|
||||
private SummaryBudget $summaryBudget;
|
||||
private SummaryBudgetInterface $summaryBudget;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
@@ -56,7 +57,7 @@ class PersonDocGenNormalizer implements
|
||||
RelationshipRepository $relationshipRepository,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
SummaryBudget $summaryBudget
|
||||
SummaryBudgetInterface $summaryBudget
|
||||
) {
|
||||
$this->personRender = $personRender;
|
||||
$this->relationshipRepository = $relationshipRepository;
|
||||
@@ -71,6 +72,7 @@ class PersonDocGenNormalizer implements
|
||||
$dateContext = $context;
|
||||
$dateContext['docgen:expects'] = DateTimeInterface::class;
|
||||
$addressContext = array_merge($context, ['docgen:expects' => Address::class]);
|
||||
$phonenumberContext = array_merge($context, ['docgen:expects' => PhoneNumber::class]);
|
||||
$personResourceContext = array_merge($context, [
|
||||
'docgen:expects' => Person\PersonResource::class,
|
||||
// we simplify the list of attributes for the embedded persons
|
||||
@@ -113,9 +115,9 @@ class PersonDocGenNormalizer implements
|
||||
'maritalStatus' => null !== ($ms = $person->getMaritalStatus()) ? $this->translatableStringHelper->localize($ms->getName()) : '',
|
||||
'maritalStatusDate' => $this->normalizer->normalize($person->getMaritalStatusDate(), $format, $dateContext),
|
||||
'email' => $person->getEmail(),
|
||||
'firstPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber() ?? $person->getMobilenumber(), $format, $context),
|
||||
'fixPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $context),
|
||||
'mobilePhoneNumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
|
||||
'firstPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber() ?? $person->getMobilenumber(), $format, $phonenumberContext),
|
||||
'fixPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $phonenumberContext),
|
||||
'mobilePhoneNumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $phonenumberContext),
|
||||
'nationality' => null !== ($c = $person->getNationality()) ? $this->translatableStringHelper->localize($c->getName()) : '',
|
||||
'placeOfBirth' => $person->getPlaceOfBirth(),
|
||||
'memo' => $person->getMemo(),
|
||||
@@ -214,6 +216,14 @@ class PersonDocGenNormalizer implements
|
||||
$data['relations'] = [];
|
||||
}
|
||||
|
||||
if ($context['docgen:person:with-budget'] ?? false) {
|
||||
$data['budget']['person'] = $this->summaryBudget->getSummaryForPerson(null);
|
||||
|
||||
if ($context['docgen:person:with-household'] ?? false) {
|
||||
$data['budget']['household'] = $this->summaryBudget->getSummaryForHousehold(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@@ -208,8 +208,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
|
||||
'birthdate' => $this->normalizer->normalize($person->getBirthdate(), $format, $context),
|
||||
'deathdate' => $this->normalizer->normalize($person->getDeathdate(), $format, $context),
|
||||
'age' => $this->normalizer->normalize($person->getAge(), $format, $context),
|
||||
'phonenumber' => $this->normalizer->normalize($person->getPhonenumber()),
|
||||
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber()),
|
||||
'phonenumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $context),
|
||||
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
|
||||
'email' => $person->getEmail(),
|
||||
'gender' => $person->getGender(),
|
||||
];
|
||||
|
@@ -152,8 +152,25 @@ class AccompanyingPeriodContext implements
|
||||
$options = $template->getOptions();
|
||||
$persons = $entity->getCurrentParticipations()->map(static function (AccompanyingPeriodParticipation $p) {
|
||||
return $p->getPerson();
|
||||
})
|
||||
->toArray();
|
||||
});
|
||||
|
||||
foreach ($entity->getCurrentParticipations() as $p) {
|
||||
foreach ($p->getPerson()->getResources() as $r) {
|
||||
if (null !== $r->getPerson() && !$persons->contains($r->getPerson())) {
|
||||
$persons->add($r->getPerson());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $entity->getRequestorPerson() && !$persons->contains($entity->getRequestorPerson())) {
|
||||
$persons->add($entity->getRequestorPerson());
|
||||
}
|
||||
|
||||
foreach ($entity->getResources() as $r) {
|
||||
if (null !== $r->getPerson() && !$persons->contains($r->getPerson())) {
|
||||
$persons->add($r->getPerson());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['mainPerson', 'person1', 'person2'] as $key) {
|
||||
if ($options[$key] ?? false) {
|
||||
|
@@ -65,7 +65,7 @@ final class HouseholdApiControllerTest extends WebTestCase
|
||||
}
|
||||
|
||||
$reference = $em->createQueryBuilder()->select('ar')->from(AddressReference::class, 'ar')
|
||||
->setFirstResult(random_int(0, $nbReference))
|
||||
->setFirstResult(random_int(0, $nbReference - 1))
|
||||
->setMaxResults(1)
|
||||
->getQuery()->getSingleResult();
|
||||
|
||||
|
@@ -75,6 +75,7 @@ final class HouseholdTest extends TestCase
|
||||
|
||||
$lastAddress = new Address();
|
||||
$lastAddress->setValidFrom($yesterday = new DateTime('yesterday'));
|
||||
$lastAddress->setValidTo(new DateTime('tomorrow'));
|
||||
$household->addAddress($lastAddress);
|
||||
|
||||
$this->assertNull($lastAddress->getValidTo());
|
||||
@@ -82,6 +83,7 @@ final class HouseholdTest extends TestCase
|
||||
|
||||
$previousAddress = new Address();
|
||||
$previousAddress->setValidFrom($oneMonthAgo = new DateTime('1 month ago'));
|
||||
$previousAddress->setValidTo(new DateTime('now'));
|
||||
$household->addAddress($previousAddress);
|
||||
|
||||
$addresses = $household->getAddressesOrdered();
|
||||
@@ -95,6 +97,7 @@ final class HouseholdTest extends TestCase
|
||||
|
||||
$futureAddress = new Address();
|
||||
$futureAddress->setValidFrom($tomorrow = new DateTime('tomorrow'));
|
||||
$futureAddress->setValidTo(new DateTime('2150-01-01'));
|
||||
$household->addAddress($futureAddress);
|
||||
|
||||
$addresses = $household->getAddressesOrdered();
|
||||
|
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Tests\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Entity\Household\Position;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Event\Person\PersonAddressMoveEvent;
|
||||
@@ -39,6 +40,122 @@ final class MembersEditorTest extends TestCase
|
||||
$this->factory = $this->buildMembersEditorFactory();
|
||||
}
|
||||
|
||||
public function testAddingParticipationNotSharingHouseholdCloseTheOldOnes()
|
||||
{
|
||||
$person = new Person();
|
||||
$position = (new Position())->setShareHousehold(false);
|
||||
$household = new Household();
|
||||
|
||||
// set a first time the person in position
|
||||
$factory = $this->buildMembersEditorFactory();
|
||||
$editor = $factory->createEditor($household);
|
||||
|
||||
$editor->addMovement($aMonthAgo = new DateTimeImmutable('1 month ago'), $person, $position);
|
||||
|
||||
// set a second time the person in position
|
||||
$factory = $this->buildMembersEditorFactory();
|
||||
$editor = $factory->createEditor($household);
|
||||
|
||||
$editor->addMovement($yesterday = new DateTimeImmutable('yesterday'), $person, $position);
|
||||
|
||||
$this->assertCount(2, $person->getHouseholdParticipationsNotShareHousehold());
|
||||
|
||||
$startDates = [];
|
||||
$endDates = [];
|
||||
|
||||
foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
|
||||
$startDates[] = $participation->getStartDate();
|
||||
$endDates[] = $participation->getEndDate();
|
||||
}
|
||||
|
||||
$this->assertContains($aMonthAgo, $startDates);
|
||||
$this->assertContains($yesterday, $startDates);
|
||||
$this->assertContains($yesterday, $endDates);
|
||||
$this->assertContains(null, $endDates);
|
||||
}
|
||||
|
||||
/**
|
||||
* We test here a move for a person:.
|
||||
*
|
||||
* * which was in a position "sharing household"
|
||||
* * which move to the another household, in a position "not sharing household"
|
||||
*
|
||||
* The person should stays in the two households
|
||||
*/
|
||||
public function testMoveFromSharingHouseholdToNotSharingHousehouldInDifferentHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$household = new Household();
|
||||
$positionSharing = (new Position())->setShareHousehold(true);
|
||||
$positionNotSharing = (new Position())->setShareHousehold(false);
|
||||
$factory = $this->buildMembersEditorFactory();
|
||||
$editor = $factory->createEditor($household);
|
||||
|
||||
// we add the member to the household
|
||||
$editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionSharing);
|
||||
|
||||
// double check that the person is in the household
|
||||
$this->assertContains($person, $household->getCurrentPersons());
|
||||
|
||||
// we do the move to the position not sharing household
|
||||
$editor = $factory->createEditor($household2 = new Household());
|
||||
$editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing);
|
||||
|
||||
$sharings = $household->getCurrentMembers()->filter(static function (HouseholdMember $m) {
|
||||
return $m->getShareHousehold();
|
||||
});
|
||||
$notSharing = $household2->getCurrentMembers()->filter(static function (HouseholdMember $m) {
|
||||
return !$m->getShareHousehold();
|
||||
});
|
||||
|
||||
$this->assertCount(1, $notSharing);
|
||||
$this->assertCount(1, $sharings);
|
||||
|
||||
$getPerson = static function (HouseholdMember $m) { return $m->getPerson(); };
|
||||
|
||||
$this->assertContains($person, $notSharing->map($getPerson));
|
||||
}
|
||||
|
||||
/**
|
||||
* We test here a move for a person:.
|
||||
*
|
||||
* * which was in a position "sharing household"
|
||||
* * which move to the same household, in a position "not sharing household"
|
||||
*/
|
||||
public function testMoveFromSharingHouseholdToNotSharingHousehouldInSamehousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$household = new Household();
|
||||
$positionSharing = (new Position())->setShareHousehold(true);
|
||||
$positionNotSharing = (new Position())->setShareHousehold(false);
|
||||
$factory = $this->buildMembersEditorFactory();
|
||||
$editor = $factory->createEditor($household);
|
||||
|
||||
// we add the member to the household
|
||||
$editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionSharing);
|
||||
|
||||
// double check that the person is in the household
|
||||
$this->assertContains($person, $household->getCurrentPersons());
|
||||
|
||||
// we do the move to the position not sharing household
|
||||
$editor = $factory->createEditor($household);
|
||||
$editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing);
|
||||
|
||||
$sharings = $household->getCurrentMembers()->filter(static function (HouseholdMember $m) {
|
||||
return $m->getShareHousehold();
|
||||
});
|
||||
$notSharing = $household->getCurrentMembers()->filter(static function (HouseholdMember $m) {
|
||||
return !$m->getShareHousehold();
|
||||
});
|
||||
|
||||
$this->assertCount(1, $notSharing);
|
||||
$this->assertCount(0, $sharings);
|
||||
|
||||
$getPerson = static function (HouseholdMember $m) { return $m->getPerson(); };
|
||||
|
||||
$this->assertContains($person, $notSharing->map($getPerson));
|
||||
}
|
||||
|
||||
public function testMovePersonWithoutSharedHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
@@ -126,7 +243,7 @@ final class MembersEditorTest extends TestCase
|
||||
$this->assertEquals($date, $membership1->getEndDate());
|
||||
}
|
||||
|
||||
public function testPostMove()
|
||||
public function testPostMoveToAPositionNotSharingHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$position = (new Position())
|
||||
@@ -134,6 +251,86 @@ final class MembersEditorTest extends TestCase
|
||||
$household1 = new Household();
|
||||
$household2 = new Household();
|
||||
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
$eventDispatcher
|
||||
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
||||
->shouldNotBeCalled();
|
||||
$factory = $this->buildMembersEditorFactory(
|
||||
$eventDispatcher->reveal(),
|
||||
null
|
||||
);
|
||||
$editor = $factory->createEditor($household1);
|
||||
|
||||
$editor->addMovement(new DateTimeImmutable('now'), $person, $position);
|
||||
|
||||
$editor->postMove();
|
||||
}
|
||||
|
||||
public function testPostMoveToAPositionSharingHouseholdAndSameHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$position = (new Position())
|
||||
->setShareHousehold(true);
|
||||
$position2 = (new Position())
|
||||
->setShareHousehold(true);
|
||||
$household1 = new Household();
|
||||
|
||||
// set into the first household
|
||||
$editor = $this->buildMembersEditorFactory()
|
||||
->createEditor($household1);
|
||||
$editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $position);
|
||||
|
||||
// prepare for next move
|
||||
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
$eventDispatcher
|
||||
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
||||
->shouldNotBeCalled();
|
||||
$factory = $this->buildMembersEditorFactory(
|
||||
$eventDispatcher->reveal(),
|
||||
null
|
||||
);
|
||||
$editor = $factory->createEditor($household1);
|
||||
|
||||
$editor->addMovement(new DateTimeImmutable('now'), $person, $position2);
|
||||
|
||||
$editor->postMove();
|
||||
}
|
||||
|
||||
public function testPostMoveToAPositionSharingHouseholdFromDifferentHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$position = (new Position())
|
||||
->setShareHousehold(true);
|
||||
$household1 = new Household();
|
||||
$household2 = new Household();
|
||||
|
||||
// set into the first household
|
||||
$editor = $this->buildMembersEditorFactory()
|
||||
->createEditor($household1);
|
||||
$editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $position);
|
||||
|
||||
// perform now the movement
|
||||
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
$eventDispatcher
|
||||
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
||||
->shouldBeCalled();
|
||||
$factory = $this->buildMembersEditorFactory(
|
||||
$eventDispatcher->reveal(),
|
||||
null
|
||||
);
|
||||
$editor = $factory->createEditor($household2);
|
||||
|
||||
$editor->addMovement(new DateTimeImmutable('now'), $person, $position);
|
||||
|
||||
$editor->postMove();
|
||||
}
|
||||
|
||||
public function testPostMoveToAPositionSharingHouseholdFromNoHousehold()
|
||||
{
|
||||
$person = new Person();
|
||||
$position = (new Position())
|
||||
->setShareHousehold(true);
|
||||
$household1 = new Household();
|
||||
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
||||
$eventDispatcher
|
||||
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
||||
->shouldBeCalled();
|
||||
|
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Serializer\Normalizer;
|
||||
|
||||
use Chill\BudgetBundle\Service\Summary\SummaryBudgetInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
@@ -72,6 +73,17 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
||||
}
|
||||
|
||||
public function dataGeneratorNormalizationNullOrNotNullHaveSameKeys(): iterable
|
||||
{
|
||||
yield [['docgen:expects' => Person::class, 'groups' => ['docgen:read']]];
|
||||
|
||||
yield [['docgen:expects' => Person::class, 'groups' => ['docgen:read'], 'docgen:person:with-household' => true]];
|
||||
|
||||
yield [['docgen:expects' => Person::class, 'groups' => ['docgen:read'], 'docgen:person:with-relations' => true]];
|
||||
|
||||
yield [['docgen:expects' => Person::class, 'groups' => ['docgen:read'], 'docgen:person:with-budget' => true]];
|
||||
}
|
||||
|
||||
public function generateData()
|
||||
{
|
||||
$person = new Person();
|
||||
@@ -90,12 +102,16 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
yield [null, self::BLANK, 'normalization for a null person'];
|
||||
}
|
||||
|
||||
public function testNormalizationNullOrNotNullHaveSameKeys()
|
||||
/**
|
||||
* @dataProvider dataGeneratorNormalizationNullOrNotNullHaveSameKeys
|
||||
*
|
||||
* @param mixed $context
|
||||
*/
|
||||
public function testNormalizationNullOrNotNullHaveSameKeys($context)
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
$period = new Person();
|
||||
$notNullData = $this->buildPersonNormalizer()->normalize($period, 'docgen', ['docgen:expects' => Person::class]);
|
||||
$nullData = $this->buildPersonNormalizer()->normalize(null, 'docgen', ['docgen:expects' => Person::class]);
|
||||
$notNullData = $this->buildPersonNormalizer()->normalize($period, 'docgen', $context);
|
||||
$nullData = $this->buildPersonNormalizer()->normalize(null, 'docgen', $context);
|
||||
|
||||
$this->assertEqualsCanonicalizing(
|
||||
array_keys($notNullData),
|
||||
@@ -131,7 +147,6 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
|
||||
public function testNormalizePersonWithHousehold()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
$household = new Household();
|
||||
$person = new Person();
|
||||
$person
|
||||
@@ -172,7 +187,6 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
|
||||
public function testNormalizePersonWithRelationships()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
$person = (new Person())->setFirstName('Renaud')->setLastName('megane');
|
||||
$father = (new Person())->setFirstName('Clément')->setLastName('megane');
|
||||
$mother = (new Person())->setFirstName('Mireille')->setLastName('Mathieu');
|
||||
@@ -235,13 +249,25 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
?RelationshipRepository $relationshipRepository = null,
|
||||
?TranslatorInterface $translator = null,
|
||||
?TranslatableStringHelper $translatableStringHelper = null,
|
||||
?NormalizerInterface $normalizer = null
|
||||
?NormalizerInterface $normalizer = null,
|
||||
?SummaryBudgetInterface $summaryBudget = null
|
||||
): PersonDocGenNormalizer {
|
||||
if (null === $summaryBudget) {
|
||||
$summaryBudget = $this->prophesize(SummaryBudgetInterface::class);
|
||||
$summaryBudget->getSummaryForHousehold(Argument::any())->willReturn(
|
||||
['resources' => [], 'charges' => []]
|
||||
);
|
||||
$summaryBudget->getSummaryForPerson(Argument::any())->willReturn(
|
||||
['resources' => [], 'charges' => []]
|
||||
);
|
||||
}
|
||||
|
||||
$personDocGenNormalizer = new PersonDocGenNormalizer(
|
||||
$personRender ?? self::$container->get(PersonRender::class),
|
||||
$relationshipRepository ?? self::$container->get(RelationshipRepository::class),
|
||||
$translator ?? self::$container->get(TranslatorInterface::class),
|
||||
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class)
|
||||
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class),
|
||||
$summaryBudget->reveal(),
|
||||
);
|
||||
|
||||
if (null === $normalizer) {
|
||||
@@ -259,13 +285,31 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
||||
?PersonRender $personRender = null,
|
||||
?RelationshipRepository $relationshipRepository = null,
|
||||
?TranslatorInterface $translator = null,
|
||||
?TranslatableStringHelper $translatableStringHelper = null
|
||||
?TranslatableStringHelper $translatableStringHelper = null,
|
||||
?SummaryBudgetInterface $summaryBudget = null
|
||||
): PersonDocGenNormalizer {
|
||||
if (null === $relationshipRepository) {
|
||||
$relationshipRepository = $this->prophesize(RelationshipRepository::class);
|
||||
$relationshipRepository->findByPerson(Argument::type(Person::class))->willReturn([]);
|
||||
$relationshipRepository = $relationshipRepository->reveal();
|
||||
}
|
||||
|
||||
if (null === $summaryBudget) {
|
||||
$summaryBudget = $this->prophesize(SummaryBudgetInterface::class);
|
||||
$summaryBudget->getSummaryForHousehold(Argument::any())->willReturn(
|
||||
['resources' => [], 'charges' => []]
|
||||
);
|
||||
$summaryBudget->getSummaryForPerson(Argument::any())->willReturn(
|
||||
['resources' => [], 'charges' => []]
|
||||
);
|
||||
}
|
||||
|
||||
$normalizer = new PersonDocGenNormalizer(
|
||||
$personRender ?? self::$container->get(PersonRender::class),
|
||||
$relationshipRepository ?? self::$container->get(RelationshipRepository::class),
|
||||
$relationshipRepository,
|
||||
$translator ?? self::$container->get(TranslatorInterface::class),
|
||||
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class)
|
||||
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class),
|
||||
$summaryBudget->reveal()
|
||||
);
|
||||
$normalizerManager = $this->prophesize(NormalizerInterface::class);
|
||||
$normalizerManager->supportsNormalization(Argument::any(), 'docgen', Argument::any())->willReturn(true);
|
||||
|
@@ -48,6 +48,12 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
|
||||
{
|
||||
$doc = $this->getRelatedEntity($entityWorkflow);
|
||||
|
||||
if (null === $doc) {
|
||||
return [
|
||||
'persons' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'persons' => $doc->getAccompanyingPeriodWorkEvaluation()
|
||||
->getAccompanyingPeriodWork()->getPersons(),
|
||||
@@ -58,6 +64,10 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
|
||||
{
|
||||
$doc = $this->getRelatedEntity($entityWorkflow);
|
||||
|
||||
if (null === $doc) {
|
||||
return $this->translator->trans('workflow.doc for evaluation deleted');
|
||||
}
|
||||
|
||||
return $this->translator->trans(
|
||||
'workflow.Doc for evaluation (n°%eval%)',
|
||||
['%eval%' => $entityWorkflow->getRelatedEntityId()]
|
||||
@@ -98,7 +108,7 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
|
||||
|
||||
return [
|
||||
'entity_workflow' => $entityWorkflow,
|
||||
'evaluation' => $doc->getAccompanyingPeriodWorkEvaluation(),
|
||||
'evaluation' => null !== $doc ? $doc->getAccompanyingPeriodWorkEvaluation() : $doc,
|
||||
'doc' => $doc,
|
||||
];
|
||||
}
|
||||
|
@@ -584,6 +584,7 @@ My accompanying periods in draft: Mes parcours brouillons
|
||||
|
||||
workflow:
|
||||
Doc for evaluation (n°%eval%): Document de l'évaluation n°%eval%
|
||||
doc for evaluation deleted: Document supprimé dans une évaluation
|
||||
|
||||
period_by_user_list:
|
||||
Period by user: Parcours d'accompagnement par utilisateur
|
||||
|
Reference in New Issue
Block a user