diff --git a/.changes/unreleased/Feature-20230817-131059.yaml b/.changes/unreleased/Feature-20230817-131059.yaml
new file mode 100644
index 000000000..29de8ec34
--- /dev/null
+++ b/.changes/unreleased/Feature-20230817-131059.yaml
@@ -0,0 +1,6 @@
+kind: Feature
+body: Add locations in Aside Activity. By default, suggest user location, otherwise
+ a select with all locations.
+time: 2023-08-17T13:10:59.152278661+02:00
+custom:
+ Issue: "133"
diff --git a/.changes/unreleased/Feature-20230817-131152.yaml b/.changes/unreleased/Feature-20230817-131152.yaml
new file mode 100644
index 000000000..bf9a165bf
--- /dev/null
+++ b/.changes/unreleased/Feature-20230817-131152.yaml
@@ -0,0 +1,6 @@
+kind: Feature
+body: 'Adapt Aside Activity exports: display location, filter by location, group by
+ location'
+time: 2023-08-17T13:11:52.911356021+02:00
+custom:
+ Issue: "133"
diff --git a/.changes/unreleased/Fixed-20230817-131239.yaml b/.changes/unreleased/Fixed-20230817-131239.yaml
new file mode 100644
index 000000000..6fc62f433
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230817-131239.yaml
@@ -0,0 +1,5 @@
+kind: Fixed
+body: Missing translation in Work Actions exports
+time: 2023-08-17T13:12:39.159627128+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230822-142809.yaml b/.changes/unreleased/Fixed-20230822-142809.yaml
new file mode 100644
index 000000000..b22477135
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230822-142809.yaml
@@ -0,0 +1,6 @@
+kind: Fixed
+body: "Corrects a typing error in 2 filters, which caused an \nerror when trying to
+ reedit a saved export\n\n"
+time: 2023-08-22T14:28:09.485466139+02:00
+custom:
+ Issue: "135"
diff --git a/.changes/unreleased/Fixed-20230829-181332.yaml b/.changes/unreleased/Fixed-20230829-181332.yaml
new file mode 100644
index 000000000..bf77afcf9
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230829-181332.yaml
@@ -0,0 +1,6 @@
+kind: Fixed
+body: '[household] when moving a person to a sharing position to a not-sharing position
+ on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member.'
+time: 2023-08-29T18:13:32.799479781+02:00
+custom:
+ Issue: "136"
diff --git a/.changes/unreleased/Fixed-20230829-181837.yaml b/.changes/unreleased/Fixed-20230829-181837.yaml
new file mode 100644
index 000000000..447e8379d
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230829-181837.yaml
@@ -0,0 +1,6 @@
+kind: Fixed
+body: |
+ Add missing translation for comment field placeholder in repositionning household editor.
+time: 2023-08-29T18:18:37.691526331+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/Fixed-20230906-154856.yaml b/.changes/unreleased/Fixed-20230906-154856.yaml
new file mode 100644
index 000000000..73fb2dc48
--- /dev/null
+++ b/.changes/unreleased/Fixed-20230906-154856.yaml
@@ -0,0 +1,5 @@
+kind: Fixed
+body: Do not send an email to creator twice when adding a comment to a notification
+time: 2023-09-06T15:48:56.991246312+02:00
+custom:
+ Issue: ""
diff --git a/.changes/unreleased/UX-20230829-181733.yaml b/.changes/unreleased/UX-20230829-181733.yaml
new file mode 100644
index 000000000..981f2c272
--- /dev/null
+++ b/.changes/unreleased/UX-20230829-181733.yaml
@@ -0,0 +1,6 @@
+kind: UX
+body: |
+ Uniformize badge-person in household banner (background, size)
+time: 2023-08-29T18:17:33.190396543+02:00
+custom:
+ Issue: ""
diff --git a/docs/source/_static/code/exports/CountPerson.php b/docs/source/_static/code/exports/CountPerson.php
index be800e52c..5d9cb2c2f 100644
--- a/docs/source/_static/code/exports/CountPerson.php
+++ b/docs/source/_static/code/exports/CountPerson.php
@@ -94,7 +94,7 @@ class CountPerson implements ExportInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
// we gather all center the user choose.
- $centers = array_map(static fn($el) => $el['center'], $acl);
+ $centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->entityManager->createQueryBuilder();
diff --git a/docs/source/development/user-interface/widgets/ChillMainConfiguration.php b/docs/source/development/user-interface/widgets/ChillMainConfiguration.php
index 9eca0ae76..cdad6b42b 100644
--- a/docs/source/development/user-interface/widgets/ChillMainConfiguration.php
+++ b/docs/source/development/user-interface/widgets/ChillMainConfiguration.php
@@ -56,7 +56,7 @@ class ChillMainConfiguration implements ConfigurationInterface
->end() // end of widgets
->end() // end of root/children
->end() // end of root
-;
+ ;
return $treeBuilder;
}
diff --git a/rector.php b/rector.php
index c2e752c32..b8975b970 100644
--- a/rector.php
+++ b/rector.php
@@ -2,6 +2,13 @@
declare(strict_types=1);
+/*
+ * 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.
+ */
+
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
diff --git a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
index 1e911ff08..17545c1af 100644
--- a/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
+++ b/src/Bundle/ChillActivityBundle/Controller/ActivityController.php
@@ -320,7 +320,6 @@ final class ActivityController extends AbstractController
private function buildFilterOrder(AccompanyingPeriod|Person $associated): FilterOrderHelper
{
-
$filterBuilder = $this->filterOrderHelperFactory->create(self::class);
$types = $this->activityACLAwareRepository->findActivityTypeByAssociated($associated);
$jobs = $this->activityACLAwareRepository->findUserJobByAssociated($associated);
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
index 807ba3903..66ab40e48 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php
@@ -22,11 +22,11 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class EmergencyFilter implements FilterInterface
{
private const CHOICES = [
- 'activity is emergency' => true,
- 'activity is not emergency' => false,
+ 'activity is emergency' => 'true',
+ 'activity is not emergency' => 'false',
];
- private const DEFAULT_CHOICE = false;
+ private const DEFAULT_CHOICE = 'false';
private TranslatorInterface $translator;
diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
index 1544dd764..7925f861b 100644
--- a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
+++ b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
@@ -322,7 +322,7 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
$counter++;
}
- foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
+ foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
if (!$this->security->isGranted(ActivityVoter::SEE, $participation->getAccompanyingPeriod())) {
continue;
}
diff --git a/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php
index ce4f318e3..74f1d2bd0 100644
--- a/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php
+++ b/src/Bundle/ChillActivityBundle/Tests/Repository/ActivityDocumentACLAwareRepositoryTest.php
@@ -122,5 +122,4 @@ class ActivityDocumentACLAwareRepositoryTest extends KernelTestCase
yield [$person, $scopes, true, null, new \DateTimeImmutable("1 week ago"), "content"];
yield [$person, [], true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), "content"];
}
-
}
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Controller/AsideActivityController.php b/src/Bundle/ChillAsideActivityBundle/src/Controller/AsideActivityController.php
index 8481f24eb..25cb2a557 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Controller/AsideActivityController.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Controller/AsideActivityController.php
@@ -33,6 +33,7 @@ final class AsideActivityController extends CRUDController
$asideActivity = new AsideActivity();
$asideActivity->setAgent($this->getUser());
+ $asideActivity->setLocation($this->getUser()->getCurrentLocation());
$duration = $request->query->get('duration', '300');
$duration = DateTime::createFromFormat('U', $duration);
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php
index 3dc205f09..412bb873e 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php
@@ -14,6 +14,7 @@ namespace Chill\AsideActivityBundle\Entity;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Entity\User;
+use Chill\MainBundle\Entity\Location;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
@@ -60,9 +61,10 @@ class AsideActivity implements TrackCreationInterface, TrackUpdateInterface
private ?int $id = null;
/**
- * @ORM\Column(type="string", length=100, nullable=true)
+ * @ORM\ManyToOne(targetEntity=Location::class)
+ * @ORM\JoinColumn(nullable=true)
*/
- private $location;
+ private ?Location $location = null;
/**
* @ORM\Column(type="text", nullable=true)
@@ -115,7 +117,7 @@ class AsideActivity implements TrackCreationInterface, TrackUpdateInterface
return $this->id;
}
- public function getLocation(): ?string
+ public function getLocation(): ?Location
{
return $this->location;
}
@@ -175,7 +177,7 @@ class AsideActivity implements TrackCreationInterface, TrackUpdateInterface
return $this;
}
- public function setLocation(?string $location): self
+ public function setLocation(?Location $location): self
{
$this->location = $location;
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByLocationAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByLocationAggregator.php
new file mode 100644
index 000000000..c6a35e3d7
--- /dev/null
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByLocationAggregator.php
@@ -0,0 +1,100 @@
+locationRepository->find($value)) {
+ return '';
+ }
+
+ return $l->getName();
+ };
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getQueryKeys($data): array
+ {
+ return ['by_aside_activity_location_aggregator'];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle(): string
+ {
+ return 'export.aggregator.Group by aside activity location';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function addRole(): ?string
+ {
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function alterQuery(QueryBuilder $qb, $data): void
+ {
+ $qb->addSelect('IDENTITY(aside.location) AS by_aside_activity_location_aggregator')
+ ->addGroupBy('by_aside_activity_location_aggregator');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function applyOn(): string
+ {
+ return Declarations::ASIDE_ACTIVITY_TYPE;
+ }
+}
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
index b46e120b5..93b0c495d 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
@@ -23,6 +23,7 @@ use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
+use Chill\MainBundle\Repository\LocationRepository;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use DateTimeInterface;
@@ -58,6 +59,7 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
CenterRepositoryInterface $centerRepository,
AsideActivityCategoryRepository $asideActivityCategoryRepository,
CategoryRender $categoryRender,
+ private LocationRepository $locationRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->em = $em;
@@ -73,6 +75,7 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
public function buildForm(FormBuilderInterface $builder)
{
}
+
public function getFormDefaultData(): array
{
return [];
@@ -145,6 +148,19 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
return $this->categoryRender->renderString($c, []);
};
+ case 'location':
+ return function ($value) {
+ if ('_header' === $value) {
+ return 'export.aside_activity.location';
+ }
+
+ if (null === $value || '' === $value || null === $l = $this->locationRepository->find($value)) {
+ return '';
+ }
+
+ return $l->getName();
+ };
+
case 'main_scope':
return function ($value) {
if ('_header' === $value) {
@@ -191,6 +207,7 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
'date',
'duration',
'note',
+ 'location',
];
}
@@ -226,6 +243,7 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
->addSelect('IDENTITY(aside.type) AS aside_activity_type')
->addSelect('aside.date')
->addSelect('aside.duration')
+ ->addSelect('IDENTITY(aside.location) AS location')
->addSelect('aside.note');
return $qb;
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByLocationFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByLocationFilter.php
new file mode 100644
index 000000000..f2808eca1
--- /dev/null
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByLocationFilter.php
@@ -0,0 +1,105 @@
+add('locations', PickUserLocationType::class);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormDefaultData(): array
+ {
+ $user = $this->security->getUser();
+
+ if ($user instanceof User) {
+ return [
+ 'locations' => $user->getCurrentLocation(),
+ ];
+ }
+
+ return [
+ 'locations' => null,
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function describeAction($data, $format = 'string'): array
+ {
+ $locations = $data['locations']->map(fn (Location $l): string => $l->getName());
+
+ return ['export.filter.Filtered by aside activity location: only %location%', [
+ '%location%' => implode(', ', $locations),
+ ]];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function addRole(): ?string
+ {
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function alterQuery(QueryBuilder $qb, $data): void
+ {
+ $clause = $qb->expr()->in('aside.location', ':locations');
+
+ $qb->andWhere($clause);
+ $qb->setParameter('locations', $data['locations']);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function applyOn(): string
+ {
+ return Declarations::ASIDE_ACTIVITY_TYPE;
+ }
+}
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php
index 727287972..2a6068424 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php
@@ -13,13 +13,16 @@ namespace Chill\AsideActivityBundle\Form;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Form\Type\PickAsideActivityCategoryType;
+use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
+use Chill\MainBundle\Form\Type\PickUserLocationType;
use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeZone;
+use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
@@ -77,7 +80,9 @@ final class AsideActivityFormType extends AbstractType
->add('note', ChillTextareaType::class, [
'label' => 'Note',
'required' => false,
- ]);
+ ])
+ ->add('location', PickUserLocationType::class)
+ ;
foreach (['duration'] as $fieldName) {
$builder->get($fieldName)
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig
index 5ffc73684..1e2711bfe 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig
+++ b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig
@@ -39,6 +39,9 @@
{% endif %}
+ {%- if entity.location.name is defined -%}
+
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/view.html.twig b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/view.html.twig
index 75da9a444..8fb487d31 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/view.html.twig
+++ b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/view.html.twig
@@ -22,6 +22,13 @@
{{ 'Created for'|trans }}
{{ entity.agent }}
+
+ {{ 'Asideactivity location'|trans }}
+ {%- if entity.location.name is defined -%}
+ {{ entity.location.name }}
+ {%- else -%}
+ {{ 'No data given'|trans }}
+ {%- endif -%}
{{ 'Activity data'|trans }}
diff --git a/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml b/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml
index a29413e15..40cb120da 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml
+++ b/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml
@@ -46,19 +46,27 @@ services:
tags:
- { name: chill.export_filter, alias: 'aside_activity_user_filter' }
+ Chill\AsideActivityBundle\Export\Filter\ByLocationFilter:
+ tags:
+ - { name: chill.export_filter, alias: 'aside_activity_location_filter' }
+
## Aggregators
chill.aside_activity.export.type_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator
tags:
- - { name: chill.export_aggregator, alias: activity_type_aggregator }
+ - { name: chill.export_aggregator, alias: 'activity_type_aggregator' }
chill.aside_activity.export.user_job_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByUserJobAggregator
tags:
- - { name: chill.export_aggregator, alias: aside_activity_user_job_aggregator }
+ - { name: chill.export_aggregator, alias: 'aside_activity_user_job_aggregator' }
chill.aside_activity.export.user_scope_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByUserScopeAggregator
tags:
- - { name: chill.export_aggregator, alias: aside_activity_user_scope_aggregator }
+ - { name: chill.export_aggregator, alias: 'aside_activity_user_scope_aggregator' }
+
+ Chill\AsideActivityBundle\Export\Aggregator\ByLocationAggregator:
+ tags:
+ - { name: chill.export_aggregator, alias: 'aside_activity_location_aggregator' }
diff --git a/src/Bundle/ChillAsideActivityBundle/src/migrations/Version20230816112809.php b/src/Bundle/ChillAsideActivityBundle/src/migrations/Version20230816112809.php
new file mode 100644
index 000000000..bde8af1e3
--- /dev/null
+++ b/src/Bundle/ChillAsideActivityBundle/src/migrations/Version20230816112809.php
@@ -0,0 +1,39 @@
+addSql('DROP INDEX chill_asideactivity.IDX_A866DA0E64D218E');
+ $this->addSql('ALTER TABLE chill_asideactivity.AsideActivity DROP CONSTRAINT FK_A866DA0E64D218E');
+ $this->addSql('ALTER TABLE chill_asideactivity.AsideActivity DROP location_id');
+ $this->addSql('ALTER TABLE chill_asideactivity.AsideActivity ADD location VARCHAR(100) DEFAULT NULL');
+ }
+
+ public function up(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE chill_asideactivity.asideactivity ADD location_id INT DEFAULT NULL');
+ $this->addSql('ALTER TABLE chill_asideactivity.asideactivity DROP location');
+ $this->addSql('ALTER TABLE chill_asideactivity.asideactivity ADD CONSTRAINT FK_A866DA0E64D218E FOREIGN KEY (location_id) REFERENCES chill_main_location (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('CREATE INDEX IDX_A866DA0E64D218E ON chill_asideactivity.asideactivity (location_id)');
+ }
+}
diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
index 25d07bd22..6028193db 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
+++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml
@@ -26,6 +26,7 @@ Users: Utilisateurs
Emergency: Urgent
by: "Par "
location: Lieu
+Asideactivity location: Localisation de l'activité
# Crud
crud:
@@ -182,6 +183,7 @@ export:
duration: Durée
note: Note
id: Identifiant
+ location: Localisation
Exports of aside activities: Exports des activités annexes
Count aside activities: Nombre d'activités annexes
@@ -202,11 +204,16 @@ export:
Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs
'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%"
Filter by user scope: Filtrer les activités annexes par service d'utilisateur
+ Filter by aside activity location: Filtrer les activités annexes par localisation
+ 'Filtered by aside activity location: only %location%': "Filtré par localisation: uniquement %location%"
aggregator:
Group by aside activity type: Grouper les activités annexes par type d'activité
Aside activity type: Type d'activité annexe
Aggregate by user job: Grouper les activités annexes par métier des utilisateurs
Aggregate by user scope: Grouper les activités annexes par service des utilisateurs
+ Aside activity location: Localisation des activités annexe
+ Group by aside activity location: Grouper les activités annexes par localisation
+ Aside activity localisation: Localisation
# ROLES
CHILL_ASIDE_ACTIVITY_STATS: Statistiques pour les activités annexes
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
index 5ffb7c01f..84ec77e6b 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/CalendarRangeFilter.php
@@ -29,11 +29,11 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class CalendarRangeFilter implements FilterInterface
{
private const CHOICES = [
- 'Not made within a calendar range' => true,
- 'Made within a calendar range' => false,
+ 'Not made within a calendar range' => 'true',
+ 'Made within a calendar range' => 'false',
];
- private const DEFAULT_CHOICE = false;
+ private const DEFAULT_CHOICE = 'false';
private TranslatorInterface $translator;
diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
index c70072a47..c3632d2db 100644
--- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
+++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
@@ -65,5 +65,4 @@ final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
default => throw new UserAbsenceSyncException("this status is not documented by Microsoft")
};
}
-
}
diff --git a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
index 6675f7c7e..1040f9f0a 100644
--- a/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
+++ b/src/Bundle/ChillCalendarBundle/Service/GenericDoc/Providers/AccompanyingPeriodCalendarGenericDocProvider.php
@@ -190,6 +190,4 @@ final readonly class AccompanyingPeriodCalendarGenericDocProvider implements Gen
return $query;
}
-
-
}
diff --git a/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php
index 089477fda..2ceab8b1f 100644
--- a/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php
+++ b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderTest.php
@@ -172,5 +172,4 @@ class MSUserAbsenceReaderTest extends TestCase
"User is absent: absence is always enabled"
];
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php
index 70c41db50..9a0650b2d 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForAccompanyingPeriodController.php
@@ -94,5 +94,4 @@ final readonly class GenericDocForAccompanyingPeriodController
]
));
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php
index 3484e0904..e010c41c5 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/GenericDocForPerson.php
@@ -91,5 +91,4 @@ final readonly class GenericDocForPerson
]
));
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php
index 30e07a841..b1631bb24 100644
--- a/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/FetchQuery.php
@@ -82,7 +82,6 @@ class FetchQuery implements FetchQueryInterface
}
unset($this->wheres[$index], $this->whereParams[$index], $this->whereTypes[$index]);
-
}
public function removeJoinClause(int $index): void
@@ -92,7 +91,6 @@ class FetchQuery implements FetchQueryInterface
}
unset($this->joins[$index], $this->joinParams[$index], $this->joinTypes[$index]);
-
}
public function getSelectKeyString(): string
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php
index 0d3cb1c32..bffa19b53 100644
--- a/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/GenericDocForAccompanyingPeriodProviderInterface.php
@@ -27,5 +27,4 @@ interface GenericDocForAccompanyingPeriodProviderInterface
* Return true if the user is allowed to see some documents for this provider.
*/
public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool;
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php
index fd36f7976..fe03a8b00 100644
--- a/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Providers/AccompanyingCourseDocumentGenericDocProvider.php
@@ -143,5 +143,4 @@ final readonly class AccompanyingCourseDocumentGenericDocProvider implements Gen
return $query;
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php
index 2dee0ed0b..8bb97a9b9 100644
--- a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocExtensionRuntime.php
@@ -46,5 +46,4 @@ final readonly class GenericDocExtensionRuntime implements RuntimeExtensionInter
throw new \LogicException("no renderer found");
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php
index 940001f4a..cdd28ac70 100644
--- a/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php
+++ b/src/Bundle/ChillDocStoreBundle/GenericDoc/Twig/GenericDocRendererInterface.php
@@ -20,5 +20,4 @@ interface GenericDocRendererInterface
public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string;
public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array;
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
index 26a42b894..12506581c 100644
--- a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
+++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
@@ -98,7 +98,6 @@ final readonly class PersonDocumentACLAwareRepository implements PersonDocumentA
continue;
}
$orPersonId[] = $participation->getPerson()->getId();
-
}
if ([] === $orPersonId) {
diff --git a/src/Bundle/ChillDocStoreBundle/Tests/GenericDoc/FetchQueryToSqlBuilderTest.php b/src/Bundle/ChillDocStoreBundle/Tests/GenericDoc/FetchQueryToSqlBuilderTest.php
index 02be9460f..f55b889a9 100644
--- a/src/Bundle/ChillDocStoreBundle/Tests/GenericDoc/FetchQueryToSqlBuilderTest.php
+++ b/src/Bundle/ChillDocStoreBundle/Tests/GenericDoc/FetchQueryToSqlBuilderTest.php
@@ -54,9 +54,6 @@ class FetchQueryToSqlBuilderTest extends KernelTestCase
);
self::assertEquals(['foo', 'bar_baz', 'baz'], $params);
self::assertEquals([Types::STRING, Types::STRING, Types::STRING], $types);
-
-
-
}
public function testToSqlWithoutWhere(): void
@@ -85,5 +82,4 @@ class FetchQueryToSqlBuilderTest extends KernelTestCase
self::assertEquals([], $params);
self::assertEquals([], $types);
}
-
}
diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Repository/PersonDocumentACLAwareRepositoryTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Repository/PersonDocumentACLAwareRepositoryTest.php
index fd611042c..bb372a150 100644
--- a/src/Bundle/ChillDocStoreBundle/Tests/Repository/PersonDocumentACLAwareRepositoryTest.php
+++ b/src/Bundle/ChillDocStoreBundle/Tests/Repository/PersonDocumentACLAwareRepositoryTest.php
@@ -142,7 +142,6 @@ class PersonDocumentACLAwareRepositoryTest extends KernelTestCase
yield [$period, new DateTimeImmutable('2 years ago'), new DateTimeImmutable('1 year ago'), null];
yield [$period, null, null, 'test'];
yield [$period, new DateTimeImmutable('2 years ago'), new DateTimeImmutable('1 year ago'), 'test'];
-
}
public function provideDataBuildFetchQueryForPerson(): iterable
@@ -154,5 +153,4 @@ class PersonDocumentACLAwareRepositoryTest extends KernelTestCase
yield [null, null, 'test'];
yield [new DateTimeImmutable('2 years ago'), new DateTimeImmutable('1 year ago'), 'test'];
}
-
}
diff --git a/src/Bundle/ChillEventBundle/Search/EventSearch.php b/src/Bundle/ChillEventBundle/Search/EventSearch.php
index 6bb3d435d..504d04130 100644
--- a/src/Bundle/ChillEventBundle/Search/EventSearch.php
+++ b/src/Bundle/ChillEventBundle/Search/EventSearch.php
@@ -152,7 +152,7 @@ class EventSearch extends AbstractSearch
$orWhere = $qb->expr()->orX();
foreach ($reachableCenters as $center) {
- $n = $n+1;
+ $n = $n + 1;
$circles = $this->authorizationHelper->getReachableScopes(
$this->security->getUser(),
'CHILL_EVENT_SEE',
diff --git a/src/Bundle/ChillMainBundle/Cron/CronManager.php b/src/Bundle/ChillMainBundle/Cron/CronManager.php
index a3e82a170..322000cb3 100644
--- a/src/Bundle/ChillMainBundle/Cron/CronManager.php
+++ b/src/Bundle/ChillMainBundle/Cron/CronManager.php
@@ -88,7 +88,6 @@ class CronManager implements CronManagerInterface
foreach ($orderedJobs as $job) {
if ($job->canRun($lasts[$job->getKey()] ?? null)) {
if (array_key_exists($job->getKey(), $lasts)) {
-
$executionData = $lasts[$job->getKey()]->getLastExecutionData();
$this->entityManager
diff --git a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php
index 51d1b3974..b0d80176b 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php
@@ -122,7 +122,6 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
foreach ($helper->getUserPickers() as $name => [
'label' => $label, 'options' => $opts
]) {
-
$userPickersBuilder->add(
$name,
PickUserDynamicType::class,
@@ -136,7 +135,6 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
$builder->add($userPickersBuilder);
}
-
}
public static function buildCheckboxChoices(array $choices, array $trans = []): array
diff --git a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php
index 5290492b1..8facf00b9 100644
--- a/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php
+++ b/src/Bundle/ChillMainBundle/Notification/Email/NotificationMailer.php
@@ -40,13 +40,18 @@ class NotificationMailer
public function postPersistComment(NotificationComment $comment, PostPersistEventArgs $eventArgs): void
{
- foreach (
- array_merge(
- $comment->getNotification()->getAddressees()->toArray(),
- [$comment->getNotification()->getSender()]
- ) as $dest
- ) {
- if (null === $dest->getEmail() || $comment->getCreatedBy() !== $dest) {
+ $dests = [$comment->getNotification()->getSender(), ...$comment->getNotification()->getAddressees()->toArray()];
+
+ $uniqueDests = [];
+ foreach ($dests as $dest) {
+ // avoid duplication
+ if (in_array(spl_object_hash($dest), $uniqueDests, true)) {
+ continue;
+ }
+ $uniqueDests[] = spl_object_hash($dest);
+
+ // do not send if the sender does not have any email, nor to the creator of the comment
+ if (null === $dest->getEmail() || $comment->getCreatedBy() === $dest) {
continue;
}
$email = new TemplatedEmail();
diff --git a/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php b/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php
index 0b80730fe..c8ab200fc 100644
--- a/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Cron/CronJobDatabaseInteractionTest.php
@@ -65,7 +65,6 @@ class CronJobDatabaseInteractionTest extends KernelTestCase
// run a second time
$manager->run();
}
-
}
class JobWithReturn implements CronJobInterface
diff --git a/src/Bundle/ChillMainBundle/Tests/Notification/Email/NotificationMailerTest.php b/src/Bundle/ChillMainBundle/Tests/Notification/Email/NotificationMailerTest.php
new file mode 100644
index 000000000..c00804e0b
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Notification/Email/NotificationMailerTest.php
@@ -0,0 +1,128 @@
+setEmail('user1@foo.com');
+ $user2 = (new User())->setEmail('user2@foo.com');
+ $user3 = (new User())->setEmail('user3@foo.com');
+
+ $notification = new Notification();
+ $notification
+ ->setTitle('test notification')
+ ->setSender($user1)
+ ->addAddressee($user2)
+ ->addAddressee($user3)
+ ;
+
+ $comment = (new NotificationComment())
+ ->setContent("foo bar baz")
+ ->setCreatedBy($user2)
+ ;
+ $notification->addComment($comment);
+
+ $mailer = $this->prophesize(MailerInterface::class);
+
+ // a mail only to user1 and user3 should have been sent
+ $mailer->send(Argument::that(function (Email $email) {
+ foreach ($email->getTo() as $address) {
+ if ($address->getAddress() === 'user1@foo.com' || $address->getAddress() === 'user3@foo.com') {
+ return true;
+ }
+ }
+
+ return false;
+ }))->shouldBeCalledTimes(2);
+
+ $objectManager = $this->prophesize(EntityManagerInterface::class);
+
+ $mailer = $this->buildNotificationMailer($mailer->reveal());
+ $mailer->postPersistComment($comment, new PostPersistEventArgs($comment, $objectManager->reveal()));
+ }
+
+ public function testPostPersistCommentDestWithNullEmail(): void
+ {
+ $user1 = (new User())->setEmail('user1@foo.com');
+ $user2 = (new User())->setEmail('user2@foo.com');
+ $user3 = (new User())->setEmail(null);
+
+ $notification = new Notification();
+ $notification
+ ->setTitle('test notification')
+ ->setSender($user1)
+ ->addAddressee($user2)
+ ->addAddressee($user3)
+ ;
+
+ $comment = (new NotificationComment())
+ ->setContent("foo bar baz")
+ ->setCreatedBy($user2)
+ ;
+ $notification->addComment($comment);
+
+ $mailer = $this->prophesize(MailerInterface::class);
+
+ // a mail only to user1 and user3 should have been sent
+ $mailer->send(Argument::that(function (Email $email) {
+ foreach ($email->getTo() as $address) {
+ if ($address->getAddress() === 'user1@foo.com') {
+ return true;
+ }
+ }
+
+ return false;
+ }))->shouldBeCalledTimes(1);
+
+ $objectManager = $this->prophesize(EntityManagerInterface::class);
+
+ $mailer = $this->buildNotificationMailer($mailer->reveal());
+ $mailer->postPersistComment($comment, new PostPersistEventArgs($comment, $objectManager->reveal()));
+ }
+
+ private function buildNotificationMailer(
+ MailerInterface $mailer = null,
+ ): NotificationMailer {
+ return new NotificationMailer(
+ $mailer,
+ new NullLogger(),
+ new Translator('fr')
+ );
+ }
+
+
+
+}
diff --git a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJobTest.php b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJobTest.php
index 69eeca2da..9e83f2e7e 100644
--- a/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJobTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Services/AddressGeographicalUnit/CollateAddressWithReferenceOrPostalCodeCronJobTest.php
@@ -64,5 +64,4 @@ class CollateAddressWithReferenceOrPostalCodeCronJobTest extends TestCase
yield [new \DateTimeImmutable('2023-07-10T12:00:00'), new \DateTimeImmutable('2023-07-01T12:00:00'), true];
yield [new \DateTimeImmutable('2023-07-10T12:00:00'), null, true];
}
-
}
diff --git a/src/Bundle/ChillPersonBundle/Controller/PersonController.php b/src/Bundle/ChillPersonBundle/Controller/PersonController.php
index 2d4732289..ce6d6bb38 100644
--- a/src/Bundle/ChillPersonBundle/Controller/PersonController.php
+++ b/src/Bundle/ChillPersonBundle/Controller/PersonController.php
@@ -214,7 +214,7 @@ final class PersonController extends AbstractController
{
$person = new Person();
- $authorizedCenters =$this->authorizationHelper->getReachableCenters($this->getUser(), PersonVoter::CREATE);
+ $authorizedCenters = $this->authorizationHelper->getReachableCenters($this->getUser(), PersonVoter::CREATE);
if (1 === count($authorizedCenters)) {
$person->setCenter($authorizedCenters[0]);
diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php
index 2b2564091..cc391c612 100644
--- a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php
+++ b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php
@@ -55,6 +55,14 @@ class MembersEditor
$this->eventDispatcher = $eventDispatcher;
}
+ /**
+ * Add a person to the household
+ *
+ * The person is added to the household associated with this editor's instance.
+ *
+ * If the person is also a member of another household, or the same household at the same position, the person
+ * is not associated any more with the previous household.
+ */
public function addMovement(DateTimeImmutable $date, Person $person, ?Position $position, ?bool $holder = false, ?string $comment = null): self
{
if (null === $this->household) {
@@ -69,68 +77,66 @@ class MembersEditor
->setComment($comment);
$this->household->addMember($membership);
- if (null !== $position) {
- 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);
+ if ($membership->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;
+ $counter = 0;
- foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) {
- if ($participation === $membership) {
- continue;
- }
-
- if ($participation->getStartDate() > $membership->getStartDate()) {
- continue;
- }
-
- ++$counter;
-
- if ($participation->getEndDate() === null || $participation->getEndDate() > $date) {
- $participation->setEndDate($date);
- $this->membershipsAffected[] = $participation;
- $this->oldMembershipsHashes[] = spl_object_hash($participation);
-
- if ($participation->getHousehold() !== $this->household) {
- $event->setPreviousMembership($participation);
- $this->events[] = $event;
- }
- }
+ foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) {
+ if ($participation === $membership) {
+ continue;
}
- // send also the event if there was no participation before
- if (0 === $counter) {
- $this->events[] = $event;
+ if ($participation->getStartDate() > $membership->getStartDate()) {
+ continue;
}
- foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
- if ($participation->getHousehold() === $this->household
- && $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()
- && $participation->getStartDate() <= $membership->getStartDate()
- ) {
- $participation->setEndDate($membership->getStartDate());
+ ++$counter;
+
+ if ($participation->getEndDate() === null || $participation->getEndDate() > $date) {
+ $participation->setEndDate($date);
+ $this->membershipsAffected[] = $participation;
+ $this->oldMembershipsHashes[] = spl_object_hash($participation);
+
+ if ($participation->getHousehold() !== $this->household) {
+ $event->setPreviousMembership($participation);
+ $this->events[] = $event;
}
}
- } 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);
+ }
+
+ // 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()
+ && $participation->getStartDate() <= $membership->getStartDate()
+ ) {
+ $participation->setEndDate($membership->getStartDate());
+ }
+ }
+ } else {
+ // if there are multiple belongings not sharing household, close the others
+ foreach ($person->getHouseholdParticipations() as $participation) {
+ if ($participation === $membership) {
+ continue;
}
- // 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()
- ) {
+ if ($participation->getHousehold() === $this->household
+ && ($participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate())
+ && $participation->getStartDate() <= $membership->getStartDate()
+ ) {
+ if ($participation->getShareHousehold()) {
+ // if a members is moved to the same household than the one he belongs to,
+ // we should make it leave the household
+ $this->leaveMovement($date, $person);
+ } else {
$participation->setEndDate($membership->getStartDate());
}
}
@@ -158,6 +164,15 @@ class MembersEditor
return null !== $this->household;
}
+ /**
+ * Makes a person leave the household.
+ *
+ * Makes a person leave the household **associated with this editor**.
+ *
+ * @param DateTimeImmutable $date
+ * @param Person $person
+ * @return $this
+ */
public function leaveMovement(
DateTimeImmutable $date,
Person $person
@@ -167,8 +182,9 @@ class MembersEditor
$criteria->where(
$expr->andX(
- $expr->lt('startDate', $date),
- $expr->isNull('endDate')
+ $expr->lte('startDate', $date),
+ $expr->isNull('endDate'),
+ $expr->eq('shareHousehold', true)
)
);
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss b/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss
index 59a9b05db..24f947100 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss
+++ b/src/Bundle/ChillPersonBundle/Resources/public/chill/chillperson.scss
@@ -207,10 +207,11 @@ div.banner {
span.badge-member {
flex-shrink: 0; flex-grow: 0; flex-basis: auto;
color: $white;
+ background-color: transparentize($white, 0.85);
border: 1px solid transparentize($white, 0.75);
border-bottom: 3px solid transparentize( shade-color( $chill-green, 20%), 0.3);
border-radius: 8px;
- padding: 0.2em 0.7em;
+ padding: 0.0em 0.5em;
margin-bottom: 0.2em;
margin-right: 0.3em;
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/PersonComment.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/PersonComment.vue
index cb9a02d51..8f61a74d1 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/PersonComment.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/PersonComment.vue
@@ -1,7 +1,7 @@
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/js/i18n.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/js/i18n.js
index 66246058f..170b2651b 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/js/i18n.js
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/js/i18n.js
@@ -53,6 +53,7 @@ const appMessages = {
persons_to_positionnate: 'Usagers à positionner',
holder: "Titulaire",
comment: "Commentaire",
+ comment_placeholder: "Associer un commentaire",
},
app: {
next: 'Suivant',
diff --git a/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php b/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php
index 8ec7ee573..c3fb702e9 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php
@@ -74,6 +74,55 @@ final class MembersEditorTest extends TestCase
$this->assertContains(null, $endDates);
}
+ /**
+ * We test that a leave move is possible when member startdate is same as current date
+ *
+ */
+ public function testLeaveMovementInSameHouseholdFromShareHouseholdToNotShareHouseholdOnSameDate()
+ {
+ $person = new Person();
+ $household = new Household();
+
+ $factory = $this->buildMembersEditorFactory();
+
+ $positionSharing = (new Position())->setShareHousehold(true);
+ $positionNotSharing = (new Position())->setShareHousehold(false);
+
+ // create add move
+ $editor = $factory->createEditor($household);
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing);
+ $editor->postMove();
+
+ self::assertContains($person, $household->getCurrentPersons());
+ self::assertSame($household, $person->getCurrentHousehold());
+ self::assertCount(1, $household->getMembers());
+
+ // create leave move
+ $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
+ $eventDispatcher
+ ->dispatch(Argument::type(PersonAddressMoveEvent::class))
+ ->shouldBeCalled();
+ $factory = $this->buildMembersEditorFactory(
+ $eventDispatcher->reveal(),
+ null
+ );
+ $editor = $factory->createEditor($household);
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing);
+ $editor->postMove();
+
+ $participations = $household->getMembers();
+ self::assertCount(2, $participations);
+
+ $sharing = $participations->filter(fn (HouseholdMember $hm) => $hm->getShareHousehold());
+ self::assertCount(1, $sharing);
+
+ $notSharing = $participations->filter(fn (HouseholdMember $hm) => !$hm->getShareHousehold());
+ self::assertCount(1, $notSharing);
+
+ self::assertNotNull($sharing[0]->getEndDate());
+ self::assertEquals(new DateTimeImmutable('today'), $sharing[0]->getEndDate());
+ }
+
/**
* We test here a move for a person:.
*
@@ -98,8 +147,17 @@ final class MembersEditorTest extends TestCase
$this->assertContains($person, $household->getCurrentPersons());
// we do the move to the position not sharing household
+ $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
+ $eventDispatcher
+ ->dispatch(Argument::type(PersonAddressMoveEvent::class))
+ ->shouldNotBeCalled();
+ $factory = $this->buildMembersEditorFactory(
+ $eventDispatcher->reveal(),
+ null
+ );
$editor = $factory->createEditor($household2 = new Household());
$editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing);
+ $editor->postMove();
$sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold());
$notSharing = $household2->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold());
@@ -118,7 +176,7 @@ final class MembersEditorTest extends TestCase
* * which was in a position "sharing household"
* * which move to the same household, in a position "not sharing household"
*/
- public function testMoveFromSharingHouseholdToNotSharingHousehouldInSamehousehold()
+ public function testMoveFromSharingHouseholdToNotSharingHousehouldInSamehouseholdOnDifferentDate()
{
$person = new Person();
$household = new Household();
@@ -134,8 +192,17 @@ final class MembersEditorTest extends TestCase
$this->assertContains($person, $household->getCurrentPersons());
// we do the move to the position not sharing household
+ $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
+ $eventDispatcher
+ ->dispatch(Argument::type(PersonAddressMoveEvent::class))
+ ->shouldBeCalled();
+ $factory = $this->buildMembersEditorFactory(
+ $eventDispatcher->reveal(),
+ null
+ );
$editor = $factory->createEditor($household);
$editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing);
+ $editor->postMove();
$sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold());
$notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold());
@@ -148,6 +215,84 @@ final class MembersEditorTest extends TestCase
$this->assertContains($person, $notSharing->map($getPerson));
}
+ /**
+ * We test here a move for a person:.
+ *
+ * * which was in a position "not sharing household"
+ * * which move to the same household, in a position "sharing household"
+ */
+ public function testMoveFromNotSharingHouseholdToSharingHousehouldInSamehousehold()
+ {
+ $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, at the position "not sharing"
+ $editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionNotSharing);
+
+ // double check that the person is in the household
+ $this->assertContains($person, $household->getCurrentPersons());
+
+ // we do the move to the position sharing household
+ $editor = $factory->createEditor($household);
+ $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionSharing);
+
+ self::assertCount(2, $household->getMembers());
+
+ $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold());
+ $notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold());
+
+ $this->assertCount(0, $notSharing);
+ $this->assertCount(1, $sharings);
+
+ $getPerson = static fn (HouseholdMember $m) => $m->getPerson();
+
+ $this->assertContains($person, $sharings->map($getPerson));
+ $this->assertNotContains($person, $notSharing->map($getPerson));
+ }
+
+ /**
+ * We test here a move for a person:.
+ *
+ * * which was in a position "not sharing household"
+ * * which move to the same household, in a position "sharing household"
+ */
+ public function testMoveFromNotSharingHouseholdToSharingHousehouldInSamehouseholdOnSameDate()
+ {
+ $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, at the position "not sharing"
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing);
+
+ // double check that the person is in the household
+ $this->assertContains($person, $household->getCurrentPersons());
+
+ // we do the move to the position sharing household
+ $editor = $factory->createEditor($household);
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing);
+
+ self::assertCount(2, $household->getMembers());
+
+ $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold());
+ $notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold());
+
+ $this->assertCount(0, $notSharing);
+ $this->assertCount(1, $sharings);
+
+ $getPerson = static fn (HouseholdMember $m) => $m->getPerson();
+
+ $this->assertContains($person, $sharings->map($getPerson));
+ $this->assertNotContains($person, $notSharing->map($getPerson));
+ }
+
public function testMovePersonWithoutSharedHousehold()
{
$person = new Person();
@@ -235,13 +380,26 @@ final class MembersEditorTest extends TestCase
$this->assertEquals($date, $membership1->getEndDate());
}
- public function testPostMoveToAPositionNotSharingHousehold()
+ public function testPostMoveToAPositionNotSharingHouseholdOnSameDay()
{
$person = new Person();
- $position = (new Position())
+ $positionNotSharing = (new Position())
->setShareHousehold(false);
+ $positionSharing = (new Position())->setShareHousehold(true);
$household1 = new Household();
$household2 = new Household();
+
+ $factory = $this->buildMembersEditorFactory();
+ $editor = $factory->createEditor($household1);
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing);
+ $editor->postMove();
+
+ self::assertContains($person, $household1->getCurrentPersons());
+ self::assertContains($person, $household1->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => $m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertSame($household1, $person->getCurrentHousehold());
+
$eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
$eventDispatcher
->dispatch(Argument::type(PersonAddressMoveEvent::class))
@@ -250,11 +408,78 @@ final class MembersEditorTest extends TestCase
$eventDispatcher->reveal(),
null
);
- $editor = $factory->createEditor($household1);
-
- $editor->addMovement(new DateTimeImmutable('now'), $person, $position);
+ $editor = $factory->createEditor($household2);
+ $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing);
$editor->postMove();
+
+ // $household1 still contains $person
+ self::assertContains($person, $household1->getCurrentPersons());
+ self::assertContains($person, $household1->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => $m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertSame($household1, $person->getCurrentHousehold());
+
+ // $household2 contains $person at non-sharing position
+ self::assertContains($person, $household2->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => !$m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertContains(
+ $household2,
+ $person->getHouseholdParticipationsNotShareHousehold()
+ ->map(fn (HouseholdMember $hm) => $hm->getHousehold())
+ );
+ }
+
+ public function testPostMoveToAPositionNotSharingHouseholdOnDifferentDays()
+ {
+ $person = new Person();
+ $positionNotSharing = (new Position())
+ ->setShareHousehold(false);
+ $positionSharing = (new Position())->setShareHousehold(true);
+ $household1 = new Household();
+ $household2 = new Household();
+
+ $factory = $this->buildMembersEditorFactory();
+ $editor = $factory->createEditor($household1);
+ $editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $positionSharing);
+ $editor->postMove();
+
+ self::assertContains($person, $household1->getCurrentPersons());
+ self::assertContains($person, $household1->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => $m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertSame($household1, $person->getCurrentHousehold());
+
+ $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
+ $eventDispatcher
+ ->dispatch(Argument::type(PersonAddressMoveEvent::class))
+ ->shouldNotBeCalled();
+ $factory = $this->buildMembersEditorFactory(
+ $eventDispatcher->reveal(),
+ null
+ );
+ $editor = $factory->createEditor($household2);
+
+ $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing);
+ $editor->postMove();
+
+ // $household1 still contains $person
+ self::assertContains($person, $household1->getCurrentPersons());
+ self::assertContains($person, $household1->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => $m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertSame($household1, $person->getCurrentHousehold());
+
+ // $household2 contains $person at non-sharing position
+ self::assertContains($person, $household2->getCurrentMembers()
+ ->filter(fn (HouseholdMember $m) => !$m->getShareHousehold())
+ ->map(fn (HouseholdMember $m) => $m->getPerson()));
+ self::assertContains(
+ $household2,
+ $person->getHouseholdParticipationsNotShareHousehold()
+ ->map(fn (HouseholdMember $hm) => $hm->getHousehold())
+ );
}
public function testPostMoveToAPositionSharingHouseholdAndSameHousehold()
diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php
index f9f888999..b5f656702 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php
@@ -108,7 +108,7 @@ class AccompanyingPeriodContextTest extends KernelTestCase
): void {
$context = $this->buildContext();
$template = new DocGeneratorTemplate();
- $template->setName(["fr" =>"test"])->setContext(AccompanyingPeriodContext::class)
+ $template->setName(["fr" => "test"])->setContext(AccompanyingPeriodContext::class)
->setDescription("description")->setActive(true)
->setOptions($options);
diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php
index 71fce8c92..fa99a5363 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php
@@ -102,7 +102,7 @@ final class PersonContextTest extends KernelTestCase
self::$container->get(ThirdPartyRepository::class)
);
$template = new DocGeneratorTemplate();
- $template->setName(["fr" =>"test"])->setContext(AccompanyingPeriodContext::class)
+ $template->setName(["fr" => "test"])->setContext(AccompanyingPeriodContext::class)
->setDescription("description")->setActive(true)
->setOptions($options);
diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Relationship/RelationshipNoDuplicateValidator.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Relationship/RelationshipNoDuplicateValidator.php
index 5b1038287..f8538cd09 100644
--- a/src/Bundle/ChillPersonBundle/Validator/Constraints/Relationship/RelationshipNoDuplicateValidator.php
+++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Relationship/RelationshipNoDuplicateValidator.php
@@ -47,11 +47,9 @@ class RelationshipNoDuplicateValidator extends ConstraintValidator
foreach ($relationships as $r) {
if (spl_object_hash($r) !== spl_object_hash($value)
- and
- (
+ and (
($r->getFromPerson() === $fromPerson and $r->getToPerson() === $toPerson)
- ||
- ($r->getFromPerson() === $toPerson and $r->getToPerson() === $fromPerson)
+ || ($r->getFromPerson() === $toPerson and $r->getToPerson() === $fromPerson)
)
) {
$this->context->buildViolation($constraint->message)
diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
index 892bb0dfd..12ec6ea29 100644
--- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
@@ -1225,6 +1225,7 @@ export:
acpw:
List of accompanying period works: Liste des actions
List description: Génère une liste des actions d'accompagnement, filtrée sur différents paramètres.
+ Date of calculation for associated elements: Date de calcul des éléments associés
help_description: L'agent traitant de l'action sera valide à cette date
id: Identifiant de l'action
startDate: Date de début
diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskStateRepository.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskStateRepository.php
index 2d64c69a0..c0d596e09 100644
--- a/src/Bundle/ChillTaskBundle/Repository/SingleTaskStateRepository.php
+++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskStateRepository.php
@@ -43,5 +43,4 @@ class SingleTaskStateRepository
return $states;
}
-
}