mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 13:24:25 +00:00
Merge remote-tracking branch 'origin/master' into issues521_531_540
This commit is contained in:
commit
7d69ec6d6b
25
CHANGELOG.md
25
CHANGELOG.md
@ -11,9 +11,17 @@ and this project adheres to
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
<!-- write down unreleased development here -->
|
<!-- write down unreleased development here -->
|
||||||
|
* [main] notification toggle read: correct js syntax for compilation in production (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/548)
|
||||||
|
* [parcours] Display of interlocuteurs changed to flex-table in parcours edit page to prevent cut-off of information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/535)
|
||||||
|
* [activity] espace entre les boutons pour supprimer les documents
|
||||||
|
|
||||||
|
## Test releases
|
||||||
|
|
||||||
|
### continuous release in February and March
|
||||||
|
|
||||||
|
* Creation of PickCivilityType, and implementation in PersonType and ThirdpartyType
|
||||||
* [person] Accompanying course evaluation documents: disable the WOPI edit link if mimetype not supported and if no keyInfos
|
* [person] Accompanying course evaluation documents: disable the WOPI edit link if mimetype not supported and if no keyInfos
|
||||||
(https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/585)
|
(https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/585)
|
||||||
|
|
||||||
* [activity] display error messages above the form in creating a new location (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/481)
|
* [activity] display error messages above the form in creating a new location (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/481)
|
||||||
* [activity] show required field in activity edit/new by an asterix in the vuejs fields (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/494)
|
* [activity] show required field in activity edit/new by an asterix in the vuejs fields (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/494)
|
||||||
* [ACL] fix allow to see the course, event if the scope'course does not contains the scope's user
|
* [ACL] fix allow to see the course, event if the scope'course does not contains the scope's user
|
||||||
@ -77,8 +85,7 @@ and this project adheres to
|
|||||||
* [parcours] Create document buttons made sticky (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/532)
|
* [parcours] Create document buttons made sticky (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/532)
|
||||||
* [person] Trailing guillemet removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/530)
|
* [person] Trailing guillemet removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/530)
|
||||||
* [notification] Display of social action within workflow notification set to display block (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/537)
|
* [notification] Display of social action within workflow notification set to display block (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/537)
|
||||||
|
* [onthefly] trim trailing whitespace in email of person and thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/542)
|
||||||
## Test releases
|
|
||||||
|
|
||||||
### test release 2022-02-21
|
### test release 2022-02-21
|
||||||
|
|
||||||
@ -106,8 +113,6 @@ and this project adheres to
|
|||||||
* [bug]: fix confidential toggle of address in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/460)
|
* [bug]: fix confidential toggle of address in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/460)
|
||||||
|
|
||||||
|
|
||||||
## Test releases
|
|
||||||
* Creation of PickCivilityType, and implementation in PersonType and ThirdpartyType
|
|
||||||
|
|
||||||
### test release 2022-02-14
|
### test release 2022-02-14
|
||||||
|
|
||||||
@ -134,6 +139,7 @@ and this project adheres to
|
|||||||
* [address]: Correction residential address 'depuis le' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/459)
|
* [address]: Correction residential address 'depuis le' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/459)
|
||||||
* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414)
|
* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414)
|
||||||
* [Thirdparty_contact]: address blurred if confidential in view page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/450)
|
* [Thirdparty_contact]: address blurred if confidential in view page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/450)
|
||||||
|
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
|
||||||
|
|
||||||
|
|
||||||
### test release 2021-02-01
|
### test release 2021-02-01
|
||||||
@ -156,18 +162,9 @@ and this project adheres to
|
|||||||
* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
|
* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
|
||||||
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
||||||
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
|
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
|
||||||
|
|
||||||
|
|
||||||
## Test releases
|
|
||||||
=======
|
|
||||||
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
||||||
>>>>>>> issue422_and_others_on_AddPersons
|
|
||||||
|
|
||||||
=======
|
|
||||||
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
|
||||||
* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345)
|
|
||||||
|
|
||||||
>>>>>>> b0d50d315c8e00959a967badac9cf5057ab2b4bc
|
|
||||||
### test release 2021-01-31
|
### test release 2021-01-31
|
||||||
|
|
||||||
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
|
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
|
||||||
|
@ -460,8 +460,3 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartySearch.php
|
path: src/Bundle/ChillThirdPartyBundle/Search/ThirdPartySearch.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillThirdPartyBundle/Templating/Entity/ThirdPartyRender.php
|
|
||||||
|
|
||||||
|
@ -4,6 +4,13 @@ div.chill-dropzone__below-zone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul[data-collection-name="documents"] {
|
||||||
|
button.remove-entry {
|
||||||
|
margin: 0.5rem 0!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// do it in js does not work
|
// do it in js does not work
|
||||||
// document.addEventListener('DOMContentLoaded', e => {
|
// document.addEventListener('DOMContentLoaded', e => {
|
||||||
// const dropzoneBelow = document.querySelectorAll('div.chill-dropzone__below-zone');
|
// const dropzoneBelow = document.querySelectorAll('div.chill-dropzone__below-zone');
|
||||||
|
@ -23,7 +23,7 @@ use function count;
|
|||||||
/**
|
/**
|
||||||
* Helps to find a summary of the budget: the sum of resources and charges.
|
* Helps to find a summary of the budget: the sum of resources and charges.
|
||||||
*/
|
*/
|
||||||
class SummaryBudget
|
class SummaryBudget implements SummaryBudgetInterface
|
||||||
{
|
{
|
||||||
private const QUERY_CHARGE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, type FROM chill_budget.charge WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
|
private const QUERY_CHARGE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, type FROM chill_budget.charge WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
|
||||||
|
|
||||||
@ -52,26 +52,6 @@ class SummaryBudget
|
|||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEmptyChargeArray(): array
|
|
||||||
{
|
|
||||||
$keys = $this->configRepository->getChargesKeys();
|
|
||||||
$labels = $this->chargeLabels;
|
|
||||||
|
|
||||||
return array_combine($keys, array_map(function ($i) use ($labels) {
|
|
||||||
return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i])];
|
|
||||||
}, $keys));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEmptyResourceArray(): array
|
|
||||||
{
|
|
||||||
$keys = $this->configRepository->getResourcesKeys();
|
|
||||||
$labels = $this->resourcesLabels;
|
|
||||||
|
|
||||||
return array_combine($keys, array_map(function ($i) use ($labels) {
|
|
||||||
return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i])];
|
|
||||||
}, $keys));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSummaryForHousehold(?Household $household): array
|
public function getSummaryForHousehold(?Household $household): array
|
||||||
{
|
{
|
||||||
if (null === $household) {
|
if (null === $household) {
|
||||||
@ -101,8 +81,15 @@ class SummaryBudget
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSummaryForPerson(Person $person): array
|
public function getSummaryForPerson(?Person $person): array
|
||||||
{
|
{
|
||||||
|
if (null === $person) {
|
||||||
|
return [
|
||||||
|
'resources' => $this->getEmptyResourceArray(),
|
||||||
|
'charges' => $this->getEmptyChargeArray(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$rsm = $this->buildRsm();
|
$rsm = $this->buildRsm();
|
||||||
|
|
||||||
$resources = $this->em->createNativeQuery(self::QUERY_RESOURCE_BY_PERSON, $rsm)
|
$resources = $this->em->createNativeQuery(self::QUERY_RESOURCE_BY_PERSON, $rsm)
|
||||||
@ -128,6 +115,26 @@ class SummaryBudget
|
|||||||
return $rsm;
|
return $rsm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getEmptyChargeArray(): array
|
||||||
|
{
|
||||||
|
$keys = $this->configRepository->getChargesKeys();
|
||||||
|
$labels = $this->chargeLabels;
|
||||||
|
|
||||||
|
return array_combine($keys, array_map(function ($i) use ($labels) {
|
||||||
|
return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i])];
|
||||||
|
}, $keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getEmptyResourceArray(): array
|
||||||
|
{
|
||||||
|
$keys = $this->configRepository->getResourcesKeys();
|
||||||
|
$labels = $this->resourcesLabels;
|
||||||
|
|
||||||
|
return array_combine($keys, array_map(function ($i) use ($labels) {
|
||||||
|
return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i])];
|
||||||
|
}, $keys));
|
||||||
|
}
|
||||||
|
|
||||||
private function rowToArray(array $rows, string $kind): array
|
private function rowToArray(array $rows, string $kind): array
|
||||||
{
|
{
|
||||||
switch ($kind) {
|
switch ($kind) {
|
||||||
|
@ -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\BudgetBundle\Service\Summary;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helps to find a summary of the budget: the sum of resources and charges.
|
||||||
|
*/
|
||||||
|
interface SummaryBudgetInterface
|
||||||
|
{
|
||||||
|
public function getSummaryForHousehold(?Household $household): array;
|
||||||
|
|
||||||
|
public function getSummaryForPerson(?Person $person): array;
|
||||||
|
}
|
@ -33,11 +33,11 @@ class ApiController extends AbstractCRUDController
|
|||||||
* Base method for handling api action.
|
* Base method for handling api action.
|
||||||
*
|
*
|
||||||
* @param mixed $id
|
* @param mixed $id
|
||||||
* @param mixed $_format
|
* @param string $_format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function entityApi(Request $request, $id, $_format): Response
|
public function entityApi(Request $request, $id, ?string $_format = 'json'): Response
|
||||||
{
|
{
|
||||||
switch ($request->getMethod()) {
|
switch ($request->getMethod()) {
|
||||||
case Request::METHOD_GET:
|
case Request::METHOD_GET:
|
||||||
|
@ -8,30 +8,31 @@ window.addEventListener('DOMContentLoaded', function (e) {
|
|||||||
document.querySelectorAll('.notification_toggle_read_status')
|
document.querySelectorAll('.notification_toggle_read_status')
|
||||||
.forEach(function (el, i) {
|
.forEach(function (el, i) {
|
||||||
createApp({
|
createApp({
|
||||||
template: '<notification-read-toggle ' +
|
template: `<notification-read-toggle
|
||||||
':notificationId="notificationId" ' +
|
:notificationId="notificationId"
|
||||||
':buttonClass="buttonClass" ' +
|
:buttonClass="buttonClass"
|
||||||
':buttonNoText="buttonNoText" ' +
|
:buttonNoText="buttonNoText"
|
||||||
':showUrl="showUrl" ' +
|
:showUrl="showUrl"
|
||||||
':isRead="isRead"' +
|
:isRead="isRead"
|
||||||
'@markRead="onMarkRead" @markUnread="onMarkUnread"' +
|
@markRead="onMarkRead"
|
||||||
'></notification-read-toggle>',
|
@markUnread="onMarkUnread">
|
||||||
|
</notification-read-toggle>`,
|
||||||
components: {
|
components: {
|
||||||
NotificationReadToggle,
|
NotificationReadToggle,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
notificationId: +el.dataset.notificationId,
|
notificationId: el.dataset.notificationId,
|
||||||
buttonClass: el.dataset.buttonClass,
|
buttonClass: el.dataset.buttonClass,
|
||||||
buttonNoText: 'false' === el.dataset.buttonText,
|
buttonNoText: 'false' === el.dataset.buttonText,
|
||||||
showUrl: el.dataset.showButtonUrl,
|
showUrl: el.dataset.showButtonUrl,
|
||||||
isRead: 1 === +el.dataset.notificationCurrentIsRead,
|
isRead: 1 === el.dataset.notificationCurrentIsRead,
|
||||||
container: el.dataset.container
|
container: el.dataset.container
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
getContainer() {
|
getContainer() {
|
||||||
return document.querySelectorAll('div.' + this.container);
|
return document.querySelectorAll(`div.${this.container}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -81,7 +81,7 @@ export default {
|
|||||||
/// [Option] showUrl is href for show page second button.
|
/// [Option] showUrl is href for show page second button.
|
||||||
// When passed, the component return a button-group with 2 buttons.
|
// When passed, the component return a button-group with 2 buttons.
|
||||||
isButtonGroup() {
|
isButtonGroup() {
|
||||||
return !!this.showUrl
|
return this.showUrl;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -44,13 +44,21 @@ class DateNormalizer implements ContextAwareNormalizerInterface, DenormalizerInt
|
|||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case DateTime::class:
|
case DateTime::class:
|
||||||
return DateTime::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']);
|
$result = DateTime::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']);
|
||||||
|
break;
|
||||||
|
|
||||||
case DateTimeInterface::class:
|
case DateTimeInterface::class:
|
||||||
case DateTimeImmutable::class:
|
case DateTimeImmutable::class:
|
||||||
return DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']);
|
$result = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $data['datetime']);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (false === $result) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
|
||||||
throw new UnexpectedValueException();
|
throw new UnexpectedValueException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class PhonenumberNormalizer implements ContextAwareNormalizerInterface, Denormal
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $data
|
* @param string|null $data
|
||||||
* @param mixed $type
|
* @param mixed $type
|
||||||
* @param null|mixed $format
|
* @param null|mixed $format
|
||||||
*
|
*
|
||||||
@ -40,7 +40,7 @@ class PhonenumberNormalizer implements ContextAwareNormalizerInterface, Denormal
|
|||||||
*/
|
*/
|
||||||
public function denormalize($data, $type, $format = null, array $context = [])
|
public function denormalize($data, $type, $format = null, array $context = [])
|
||||||
{
|
{
|
||||||
if ('' === trim($data)) {
|
if ('' === trim((string) $data)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +514,8 @@ class Household
|
|||||||
|
|
||||||
if ($iterator->valid()) {
|
if ($iterator->valid()) {
|
||||||
$current->setValidTo($iterator->current()->getValidFrom());
|
$current->setValidTo($iterator->current()->getValidFrom());
|
||||||
|
} else {
|
||||||
|
$current->setValidTo(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,25 +276,21 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
/**
|
/**
|
||||||
* The person's first name.
|
* The person's first name.
|
||||||
*
|
*
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="string", length=255)
|
||||||
* @Assert\NotBlank(message="The firstname cannot be empty")
|
* @Assert\NotBlank(message="The firstname cannot be empty")
|
||||||
* @Assert\Length(
|
* @Assert\Length(
|
||||||
* max=255,
|
* max=255,
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
private $firstName;
|
private string $firstName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fullname canonical. Read-only field, which is calculated by
|
* fullname canonical. Read-only field, which is calculated by
|
||||||
* the database.
|
* the database.
|
||||||
*
|
*
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
* @ORM\Column(type="text", nullable=true)
|
* @ORM\Column(type="text", nullable=true)
|
||||||
*/
|
*/
|
||||||
private $fullnameCanonical;
|
private string $fullnameCanonical = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The person's gender.
|
* The person's gender.
|
||||||
@ -328,6 +324,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
* targetEntity=HouseholdMember::class,
|
* targetEntity=HouseholdMember::class,
|
||||||
* mappedBy="person"
|
* mappedBy="person"
|
||||||
* )
|
* )
|
||||||
|
*
|
||||||
|
* @var Collection|HouseholdMember[]
|
||||||
*/
|
*/
|
||||||
private Collection $householdParticipations;
|
private Collection $householdParticipations;
|
||||||
|
|
||||||
@ -343,15 +341,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
/**
|
/**
|
||||||
* The person's last name.
|
* The person's last name.
|
||||||
*
|
*
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="string", length=255)
|
||||||
* @Assert\NotBlank(message="The lastname cannot be empty")
|
* @Assert\NotBlank(message="The lastname cannot be empty")
|
||||||
* @Assert\Length(
|
* @Assert\Length(
|
||||||
* max=255,
|
* max=255,
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
private $lastName;
|
private string $lastName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The marital status of the person.
|
* The marital status of the person.
|
||||||
@ -1117,6 +1113,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this->householdAddresses;
|
return $this->householdAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection|HouseholdMember[]
|
||||||
|
*/
|
||||||
public function getHouseholdParticipations(): Collection
|
public function getHouseholdParticipations(): Collection
|
||||||
{
|
{
|
||||||
return $this->householdParticipations;
|
return $this->householdParticipations;
|
||||||
@ -1126,6 +1125,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
* Get participation where the person does not share the household.
|
* Get participation where the person does not share the household.
|
||||||
*
|
*
|
||||||
* Order by startDate, desc
|
* Order by startDate, desc
|
||||||
|
*
|
||||||
|
* @return HouseholdMember[]
|
||||||
*/
|
*/
|
||||||
public function getHouseholdParticipationsNotShareHousehold(): Collection
|
public function getHouseholdParticipationsNotShareHousehold(): Collection
|
||||||
{
|
{
|
||||||
@ -1146,6 +1147,8 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
* Get participation where the person does share the household.
|
* Get participation where the person does share the household.
|
||||||
*
|
*
|
||||||
* Order by startDate, desc
|
* Order by startDate, desc
|
||||||
|
*
|
||||||
|
* @return Collection|HouseholdMember[]
|
||||||
*/
|
*/
|
||||||
public function getHouseholdParticipationsShareHousehold(): Collection
|
public function getHouseholdParticipationsShareHousehold(): Collection
|
||||||
{
|
{
|
||||||
@ -1565,18 +1568,14 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
|
|
||||||
public function setEmail(?string $email): self
|
public function setEmail(?string $email): self
|
||||||
{
|
{
|
||||||
if (null === $email) {
|
$this->email = trim((string) $email);
|
||||||
$email = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->email = $email;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFirstName(string $firstName): self
|
public function setFirstName(?string $firstName): self
|
||||||
{
|
{
|
||||||
$this->firstName = $firstName;
|
$this->firstName = (string) $firstName;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -1602,9 +1601,9 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLastName(string $lastName): self
|
public function setLastName(?string $lastName): self
|
||||||
{
|
{
|
||||||
$this->lastName = $lastName;
|
$this->lastName = (string) $lastName;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,12 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||||||
|
|
||||||
final class PersonResourceType extends AbstractType
|
final class PersonResourceType extends AbstractType
|
||||||
{
|
{
|
||||||
|
private PersonRenderInterface $personRender;
|
||||||
|
|
||||||
private ResourceKindRender $resourceKindRender;
|
private ResourceKindRender $resourceKindRender;
|
||||||
|
|
||||||
|
private ThirdPartyRender $thirdPartyRender;
|
||||||
|
|
||||||
private TranslatorInterface $translator;
|
private TranslatorInterface $translator;
|
||||||
|
|
||||||
public function __construct(ResourceKindRender $resourceKindRender, PersonRenderInterface $personRender, ThirdPartyRender $thirdPartyRender, 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');
|
throw new LogicException('You must define a household first');
|
||||||
}
|
}
|
||||||
|
|
||||||
$event = new PersonAddressMoveEvent($person);
|
|
||||||
|
|
||||||
$membership = (new HouseholdMember())
|
$membership = (new HouseholdMember())
|
||||||
->setStartDate($date)
|
->setStartDate($date)
|
||||||
->setPerson($person)
|
->setPerson($person)
|
||||||
@ -70,9 +68,15 @@ class MembersEditor
|
|||||||
->setHolder($holder)
|
->setHolder($holder)
|
||||||
->setComment($comment);
|
->setComment($comment);
|
||||||
$this->household->addMember($membership);
|
$this->household->addMember($membership);
|
||||||
$event->setNextMembership($membership);
|
|
||||||
|
|
||||||
if ($position->getShareHousehold()) {
|
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) {
|
foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) {
|
||||||
if ($participation === $membership) {
|
if ($participation === $membership) {
|
||||||
continue;
|
continue;
|
||||||
@ -82,14 +86,25 @@ class MembersEditor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++$counter;
|
||||||
|
|
||||||
if ($participation->getEndDate() === null || $participation->getEndDate() > $date) {
|
if ($participation->getEndDate() === null || $participation->getEndDate() > $date) {
|
||||||
$event->setPreviousMembership($participation);
|
|
||||||
$participation->setEndDate($date);
|
$participation->setEndDate($date);
|
||||||
$this->membershipsAffected[] = $participation;
|
$this->membershipsAffected[] = $participation;
|
||||||
$this->oldMembershipsHashes[] = spl_object_hash($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) {
|
foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
|
||||||
if ($participation->getHousehold() === $this->household
|
if ($participation->getHousehold() === $this->household
|
||||||
&& $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()
|
&& $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()
|
||||||
@ -98,11 +113,30 @@ class MembersEditor
|
|||||||
$participation->setEndDate($membership->getStartDate());
|
$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->membershipsAffected[] = $membership;
|
||||||
$this->persistables[] = $membership;
|
$this->persistables[] = $membership;
|
||||||
$this->events[] = $event;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
->setExtras([
|
->setExtras([
|
||||||
'order' => 99999,
|
'order' => 99999,
|
||||||
]);
|
]);
|
||||||
|
/*
|
||||||
$menu->addChild($this->translator->trans('Person duplicate'), [
|
$menu->addChild($this->translator->trans('Person duplicate'), [
|
||||||
'route' => 'chill_person_duplicate_view',
|
'route' => 'chill_person_duplicate_view',
|
||||||
'routeParameters' => [
|
'routeParameters' => [
|
||||||
@ -98,7 +98,7 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
->setExtras([
|
->setExtras([
|
||||||
'order' => 99999,
|
'order' => 99999,
|
||||||
]);
|
]);
|
||||||
|
*/
|
||||||
if (
|
if (
|
||||||
'visible' === $this->showAccompanyingPeriod
|
'visible' === $this->showAccompanyingPeriod
|
||||||
&& $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person'])
|
&& $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person'])
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<label class="chill-no-data-statement">{{ $tc('resources.counter', counter) }}</label>
|
<label class="chill-no-data-statement">{{ $tc('resources.counter', counter) }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-bloc mb-3">
|
<div class="flex-table mb-3">
|
||||||
<resource-item
|
<resource-item
|
||||||
v-for="resource in resources"
|
v-for="resource in resources"
|
||||||
v-bind:resource="resource"
|
v-bind:resource="resource"
|
||||||
|
@ -138,12 +138,12 @@
|
|||||||
@go-to-generate-document="submitBeforeGenerate"
|
@go-to-generate-document="submitBeforeGenerate"
|
||||||
>
|
>
|
||||||
<template v-slot:title>
|
<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>
|
</template>
|
||||||
</pick-template>
|
</pick-template>
|
||||||
<div>
|
<div>
|
||||||
<label class="col-sm-4 col-form-label">{{ $t('document_upload') }}</label>
|
<label class="col-form-label">{{ $t('document_upload') }}</label>
|
||||||
<ul class="record_actions">
|
<ul class="record_actions document-upload">
|
||||||
<li>
|
<li>
|
||||||
<add-async-upload
|
<add-async-upload
|
||||||
:buttonTitle="$t('browse')"
|
:buttonTitle="$t('browse')"
|
||||||
@ -411,8 +411,11 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
input.document-title{
|
input.document-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
ul.document-upload {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -11,7 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
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\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper;
|
||||||
use Chill\MainBundle\Entity\Address;
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\MainBundle\Entity\Civility;
|
use Chill\MainBundle\Entity\Civility;
|
||||||
@ -45,7 +45,7 @@ class PersonDocGenNormalizer implements
|
|||||||
|
|
||||||
private RelationshipRepository $relationshipRepository;
|
private RelationshipRepository $relationshipRepository;
|
||||||
|
|
||||||
private SummaryBudget $summaryBudget;
|
private SummaryBudgetInterface $summaryBudget;
|
||||||
|
|
||||||
private TranslatableStringHelper $translatableStringHelper;
|
private TranslatableStringHelper $translatableStringHelper;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ class PersonDocGenNormalizer implements
|
|||||||
RelationshipRepository $relationshipRepository,
|
RelationshipRepository $relationshipRepository,
|
||||||
TranslatorInterface $translator,
|
TranslatorInterface $translator,
|
||||||
TranslatableStringHelper $translatableStringHelper,
|
TranslatableStringHelper $translatableStringHelper,
|
||||||
SummaryBudget $summaryBudget
|
SummaryBudgetInterface $summaryBudget
|
||||||
) {
|
) {
|
||||||
$this->personRender = $personRender;
|
$this->personRender = $personRender;
|
||||||
$this->relationshipRepository = $relationshipRepository;
|
$this->relationshipRepository = $relationshipRepository;
|
||||||
@ -214,6 +214,14 @@ class PersonDocGenNormalizer implements
|
|||||||
$data['relations'] = [];
|
$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;
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,8 +208,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
|
|||||||
'birthdate' => $this->normalizer->normalize($person->getBirthdate(), $format, $context),
|
'birthdate' => $this->normalizer->normalize($person->getBirthdate(), $format, $context),
|
||||||
'deathdate' => $this->normalizer->normalize($person->getDeathdate(), $format, $context),
|
'deathdate' => $this->normalizer->normalize($person->getDeathdate(), $format, $context),
|
||||||
'age' => $this->normalizer->normalize($person->getAge(), $format, $context),
|
'age' => $this->normalizer->normalize($person->getAge(), $format, $context),
|
||||||
'phonenumber' => $this->normalizer->normalize($person->getPhonenumber()),
|
'phonenumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $context),
|
||||||
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber()),
|
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
|
||||||
'email' => $person->getEmail(),
|
'email' => $person->getEmail(),
|
||||||
'gender' => $person->getGender(),
|
'gender' => $person->getGender(),
|
||||||
];
|
];
|
||||||
|
@ -65,7 +65,7 @@ final class HouseholdApiControllerTest extends WebTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
$reference = $em->createQueryBuilder()->select('ar')->from(AddressReference::class, 'ar')
|
$reference = $em->createQueryBuilder()->select('ar')->from(AddressReference::class, 'ar')
|
||||||
->setFirstResult(random_int(0, $nbReference))
|
->setFirstResult(random_int(0, $nbReference - 1))
|
||||||
->setMaxResults(1)
|
->setMaxResults(1)
|
||||||
->getQuery()->getSingleResult();
|
->getQuery()->getSingleResult();
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ final class HouseholdTest extends TestCase
|
|||||||
|
|
||||||
$lastAddress = new Address();
|
$lastAddress = new Address();
|
||||||
$lastAddress->setValidFrom($yesterday = new DateTime('yesterday'));
|
$lastAddress->setValidFrom($yesterday = new DateTime('yesterday'));
|
||||||
|
$lastAddress->setValidTo(new DateTime('tomorrow'));
|
||||||
$household->addAddress($lastAddress);
|
$household->addAddress($lastAddress);
|
||||||
|
|
||||||
$this->assertNull($lastAddress->getValidTo());
|
$this->assertNull($lastAddress->getValidTo());
|
||||||
@ -82,6 +83,7 @@ final class HouseholdTest extends TestCase
|
|||||||
|
|
||||||
$previousAddress = new Address();
|
$previousAddress = new Address();
|
||||||
$previousAddress->setValidFrom($oneMonthAgo = new DateTime('1 month ago'));
|
$previousAddress->setValidFrom($oneMonthAgo = new DateTime('1 month ago'));
|
||||||
|
$previousAddress->setValidTo(new DateTime('now'));
|
||||||
$household->addAddress($previousAddress);
|
$household->addAddress($previousAddress);
|
||||||
|
|
||||||
$addresses = $household->getAddressesOrdered();
|
$addresses = $household->getAddressesOrdered();
|
||||||
@ -95,6 +97,7 @@ final class HouseholdTest extends TestCase
|
|||||||
|
|
||||||
$futureAddress = new Address();
|
$futureAddress = new Address();
|
||||||
$futureAddress->setValidFrom($tomorrow = new DateTime('tomorrow'));
|
$futureAddress->setValidFrom($tomorrow = new DateTime('tomorrow'));
|
||||||
|
$futureAddress->setValidTo(new DateTime('2150-01-01'));
|
||||||
$household->addAddress($futureAddress);
|
$household->addAddress($futureAddress);
|
||||||
|
|
||||||
$addresses = $household->getAddressesOrdered();
|
$addresses = $household->getAddressesOrdered();
|
||||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Tests\Household;
|
namespace Chill\PersonBundle\Tests\Household;
|
||||||
|
|
||||||
use Chill\PersonBundle\Entity\Household\Household;
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
|
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||||
use Chill\PersonBundle\Entity\Household\Position;
|
use Chill\PersonBundle\Entity\Household\Position;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Event\Person\PersonAddressMoveEvent;
|
use Chill\PersonBundle\Event\Person\PersonAddressMoveEvent;
|
||||||
@ -39,6 +40,122 @@ final class MembersEditorTest extends TestCase
|
|||||||
$this->factory = $this->buildMembersEditorFactory();
|
$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()
|
public function testMovePersonWithoutSharedHousehold()
|
||||||
{
|
{
|
||||||
$person = new Person();
|
$person = new Person();
|
||||||
@ -126,7 +243,7 @@ final class MembersEditorTest extends TestCase
|
|||||||
$this->assertEquals($date, $membership1->getEndDate());
|
$this->assertEquals($date, $membership1->getEndDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPostMove()
|
public function testPostMoveToAPositionNotSharingHousehold()
|
||||||
{
|
{
|
||||||
$person = new Person();
|
$person = new Person();
|
||||||
$position = (new Position())
|
$position = (new Position())
|
||||||
@ -134,6 +251,86 @@ final class MembersEditorTest extends TestCase
|
|||||||
$household1 = new Household();
|
$household1 = new Household();
|
||||||
$household2 = new Household();
|
$household2 = new Household();
|
||||||
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
|
$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
|
$eventDispatcher
|
||||||
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
->dispatch(Argument::type(PersonAddressMoveEvent::class))
|
||||||
->shouldBeCalled();
|
->shouldBeCalled();
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Serializer\Normalizer;
|
namespace Serializer\Normalizer;
|
||||||
|
|
||||||
|
use Chill\BudgetBundle\Service\Summary\SummaryBudgetInterface;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
use Chill\PersonBundle\Entity\Household\Household;
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
@ -72,6 +73,17 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
$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()
|
public function generateData()
|
||||||
{
|
{
|
||||||
$person = new Person();
|
$person = new Person();
|
||||||
@ -90,12 +102,16 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
yield [null, self::BLANK, 'normalization for a null person'];
|
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();
|
$period = new Person();
|
||||||
$notNullData = $this->buildPersonNormalizer()->normalize($period, 'docgen', ['docgen:expects' => Person::class]);
|
$notNullData = $this->buildPersonNormalizer()->normalize($period, 'docgen', $context);
|
||||||
$nullData = $this->buildPersonNormalizer()->normalize(null, 'docgen', ['docgen:expects' => Person::class]);
|
$nullData = $this->buildPersonNormalizer()->normalize(null, 'docgen', $context);
|
||||||
|
|
||||||
$this->assertEqualsCanonicalizing(
|
$this->assertEqualsCanonicalizing(
|
||||||
array_keys($notNullData),
|
array_keys($notNullData),
|
||||||
@ -131,7 +147,6 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
|
|
||||||
public function testNormalizePersonWithHousehold()
|
public function testNormalizePersonWithHousehold()
|
||||||
{
|
{
|
||||||
$this->markTestSkipped();
|
|
||||||
$household = new Household();
|
$household = new Household();
|
||||||
$person = new Person();
|
$person = new Person();
|
||||||
$person
|
$person
|
||||||
@ -172,7 +187,6 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
|
|
||||||
public function testNormalizePersonWithRelationships()
|
public function testNormalizePersonWithRelationships()
|
||||||
{
|
{
|
||||||
$this->markTestSkipped();
|
|
||||||
$person = (new Person())->setFirstName('Renaud')->setLastName('megane');
|
$person = (new Person())->setFirstName('Renaud')->setLastName('megane');
|
||||||
$father = (new Person())->setFirstName('Clément')->setLastName('megane');
|
$father = (new Person())->setFirstName('Clément')->setLastName('megane');
|
||||||
$mother = (new Person())->setFirstName('Mireille')->setLastName('Mathieu');
|
$mother = (new Person())->setFirstName('Mireille')->setLastName('Mathieu');
|
||||||
@ -235,13 +249,25 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
?RelationshipRepository $relationshipRepository = null,
|
?RelationshipRepository $relationshipRepository = null,
|
||||||
?TranslatorInterface $translator = null,
|
?TranslatorInterface $translator = null,
|
||||||
?TranslatableStringHelper $translatableStringHelper = null,
|
?TranslatableStringHelper $translatableStringHelper = null,
|
||||||
?NormalizerInterface $normalizer = null
|
?NormalizerInterface $normalizer = null,
|
||||||
|
?SummaryBudgetInterface $summaryBudget = null
|
||||||
): PersonDocGenNormalizer {
|
): 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(
|
$personDocGenNormalizer = new PersonDocGenNormalizer(
|
||||||
$personRender ?? self::$container->get(PersonRender::class),
|
$personRender ?? self::$container->get(PersonRender::class),
|
||||||
$relationshipRepository ?? self::$container->get(RelationshipRepository::class),
|
$relationshipRepository ?? self::$container->get(RelationshipRepository::class),
|
||||||
$translator ?? self::$container->get(TranslatorInterface::class),
|
$translator ?? self::$container->get(TranslatorInterface::class),
|
||||||
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class)
|
$translatableStringHelper ?? self::$container->get(TranslatableStringHelperInterface::class),
|
||||||
|
$summaryBudget->reveal(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (null === $normalizer) {
|
if (null === $normalizer) {
|
||||||
@ -259,13 +285,31 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
|
|||||||
?PersonRender $personRender = null,
|
?PersonRender $personRender = null,
|
||||||
?RelationshipRepository $relationshipRepository = null,
|
?RelationshipRepository $relationshipRepository = null,
|
||||||
?TranslatorInterface $translator = null,
|
?TranslatorInterface $translator = null,
|
||||||
?TranslatableStringHelper $translatableStringHelper = null
|
?TranslatableStringHelper $translatableStringHelper = null,
|
||||||
|
?SummaryBudgetInterface $summaryBudget = null
|
||||||
): PersonDocGenNormalizer {
|
): 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(
|
$normalizer = new PersonDocGenNormalizer(
|
||||||
$personRender ?? self::$container->get(PersonRender::class),
|
$personRender ?? self::$container->get(PersonRender::class),
|
||||||
$relationshipRepository ?? self::$container->get(RelationshipRepository::class),
|
$relationshipRepository,
|
||||||
$translator ?? self::$container->get(TranslatorInterface::class),
|
$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 = $this->prophesize(NormalizerInterface::class);
|
||||||
$normalizerManager->supportsNormalization(Argument::any(), 'docgen', Argument::any())->willReturn(true);
|
$normalizerManager->supportsNormalization(Argument::any(), 'docgen', Argument::any())->willReturn(true);
|
||||||
|
@ -762,7 +762,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
*/
|
*/
|
||||||
public function setEmail($email = null)
|
public function setEmail($email = null)
|
||||||
{
|
{
|
||||||
$this->email = $email;
|
$this->email = trim((string) $email);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,12 @@ final class ThirdPartyACLAwareRepository implements ThirdPartyACLAwareRepository
|
|||||||
{
|
{
|
||||||
$qb = $this->thirdPartyRepository->createQueryBuilder('tp');
|
$qb = $this->thirdPartyRepository->createQueryBuilder('tp');
|
||||||
|
|
||||||
|
$qb->leftJoin('tp.parent', 'parent')
|
||||||
|
->andWhere($qb->expr()->andX(
|
||||||
|
'tp.active = \'TRUE\'',
|
||||||
|
$qb->expr()->orX($qb->expr()->isNull('parent'), 'parent.active = \'TRUE\'')
|
||||||
|
));
|
||||||
|
|
||||||
if (null !== $filterString) {
|
if (null !== $filterString) {
|
||||||
$qb->andWhere($qb->expr()->like('tp.canonicalized', 'LOWER(UNACCENT(:filterString))'))
|
$qb->andWhere($qb->expr()->like('tp.canonicalized', 'LOWER(UNACCENT(:filterString))'))
|
||||||
->setParameter('filterString', '%' . $filterString . '%');
|
->setParameter('filterString', '%' . $filterString . '%');
|
||||||
|
@ -109,14 +109,15 @@ class ThirdPartyApiSearch implements SearchApiInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$query
|
$query
|
||||||
->setSelectPertinence(implode(' + ', $pertinence).' + 1', array_merge(
|
->setSelectPertinence(implode(' + ', $pertinence) . ' + 1', array_merge(
|
||||||
[],
|
[],
|
||||||
...$pertinenceArgs
|
...$pertinenceArgs
|
||||||
))
|
))
|
||||||
->andWhereClause(implode(' AND ', $wheres), array_merge(
|
->andWhereClause(implode(' AND ', $wheres)
|
||||||
[],
|
. ' AND tparty.active IS TRUE and (parent.active IS TRUE OR parent IS NULL)', array_merge(
|
||||||
...$whereArgs
|
[],
|
||||||
));
|
...$whereArgs
|
||||||
|
));
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class ThirdPartyNormalizer implements NormalizerAwareInterface, NormalizerInterf
|
|||||||
}, $thirdParty->getTypesAndCategories()),
|
}, $thirdParty->getTypesAndCategories()),
|
||||||
'profession' => $this->normalizer->normalize($thirdParty->getProfession(), $format, $context),
|
'profession' => $this->normalizer->normalize($thirdParty->getProfession(), $format, $context),
|
||||||
'address' => $this->normalizer->normalize($thirdParty->getAddress(), $format, ['address_rendering' => 'short']),
|
'address' => $this->normalizer->normalize($thirdParty->getAddress(), $format, ['address_rendering' => 'short']),
|
||||||
'telephone' => $this->normalizer->normalize($thirdParty->getTelephone()),
|
'telephone' => $this->normalizer->normalize($thirdParty->getTelephone(), $format, $context),
|
||||||
'email' => $thirdParty->getEmail(),
|
'email' => $thirdParty->getEmail(),
|
||||||
'isChild' => $thirdParty->isChild(),
|
'isChild' => $thirdParty->isChild(),
|
||||||
'parent' => $this->normalizer->normalize($thirdParty->getParent(), $format, $context),
|
'parent' => $this->normalizer->normalize($thirdParty->getParent(), $format, $context),
|
||||||
|
@ -71,13 +71,13 @@ class ThirdPartyRender extends AbstractChillEntityRender
|
|||||||
$civility = '';
|
$civility = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($entity->getAcronym())) {
|
if ('' !== (string) $entity->getAcronym()) {
|
||||||
$acronym = ' (' . $entity->getAcronym() . ')';
|
$acronym = ' (' . $entity->getAcronym() . ')';
|
||||||
} else {
|
} else {
|
||||||
$acronym = '';
|
$acronym = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$firstname = empty($entity->getFirstname()) ? '' : $entity->getFirstname();
|
$firstname = ('' === $entity->getFirstname()) ? '' : $entity->getFirstname();
|
||||||
|
|
||||||
return $civility . $firstname . ' ' . $entity->getName() . $acronym;
|
return $civility . $firstname . ' ' . $entity->getName() . $acronym;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user