From cbd9489810fcf0e80b1a4f36d9a57d4340ef9080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 5 Jun 2024 16:04:18 +0200 Subject: [PATCH] Add startDate and endDate on UserJobFilter --- .../UserJobFilter.php | 108 +++++++++++------- .../UserJobFilterTest.php | 6 +- .../translations/messages+intl-icu.fr.yaml | 2 + .../translations/messages.fr.yml | 3 +- 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index d6bc25198..120d0a70e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -13,23 +13,28 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; +use Chill\MainBundle\Export\DataTransformerFilterInterface; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory; use Chill\PersonBundle\Export\Declarations; use Doctrine\Common\Collections\Collection; -use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; -class UserJobFilter implements FilterInterface +final readonly class UserJobFilter implements FilterInterface, DataTransformerFilterInterface { private const PREFIX = 'acp_filter_user_job'; public function __construct( - private readonly TranslatableStringHelper $translatableStringHelper, - private readonly UserJobRepositoryInterface $userJobRepository, + private TranslatableStringHelper $translatableStringHelper, + private UserJobRepositoryInterface $userJobRepository, + private RollingDateConverterInterface $rollingDateConverter, ) { } @@ -42,42 +47,31 @@ class UserJobFilter implements FilterInterface { $p = self::PREFIX; - $qb - ->leftJoin( - 'acp.userHistories', - "{$p}_userHistory", - Join::WITH, - $qb->expr()->andX( - $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", 'acp.id'), - $qb->expr()->andX( - $qb->expr()->gte('COALESCE(acp.closingDate, CURRENT_TIMESTAMP())', "{$p}_userHistory.startDate"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt('COALESCE(acp.closingDate, CURRENT_TIMESTAMP())', "{$p}_userHistory.endDate") - ) - ) - ) - ) - ->leftJoin( - UserJobHistory::class, - "{$p}_jobHistory", - Join::WITH, - $qb->expr()->andX( - $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.user"), - $qb->expr()->andX( - $qb->expr()->lte("{$p}_jobHistory.startDate", "{$p}_userHistory.startDate"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_jobHistory".'.endDate'), - $qb->expr()->gt("{$p}_jobHistory.endDate", "{$p}_userHistory.startDate") - ) - ) - ) - ) - ->andWhere($qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job")) - ->setParameter( - "{$p}_job", - $data['jobs'], + $qb->andWhere( + $qb->expr()->exists( + sprintf( + << :{$p}_startDate) + AND {$p}_userJobHistory.startDate <= :{$p}_endDate + AND ({$p}_userJobHistory.endDate IS NULL OR {$p}_userJobHistory.endDate > :{$p}_startDate) + AND {$p}_userJobHistory.job IN (:{$p}_jobs) + DQL, + UserHistory::class, + UserJobHistory::class, + ), ) + ) + ->setParameter("{$p}_jobs", $data['jobs']) + ->setParameter("{$p}_startDate", $this->rollingDateConverter->convert($data['start_date'])) + ->setParameter("{$p}_endDate", $this->rollingDateConverter->convert($data['end_date'])) ; } @@ -96,20 +90,29 @@ class UserJobFilter implements FilterInterface 'expanded' => true, 'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), 'label' => 'Job', - ]); + ]) + ->add('start_date', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_user_job.Start from', + ]) + ->add('end_date', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_user_job.Until', + ]) + ; } public function describeAction($data, $format = 'string') { return [ - 'export.filter.course.by_user_job.Filtered by user job: only %job%', [ - '%job%' => implode( + 'exports.filter.course.by_user_job.Filtered by user job: only job', [ + 'job' => implode( ', ', array_map( fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), $data['jobs'] instanceof Collection ? $data['jobs']->toArray() : $data['jobs'] ) ), + 'startDate' => $this->rollingDateConverter->convert($data['start_date']), + 'endDate' => $this->rollingDateConverter->convert($data['end_date']), ], ]; } @@ -118,9 +121,30 @@ class UserJobFilter implements FilterInterface { return [ 'jobs' => [], + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), ]; } + public function transformData(?array $before): array + { + $default = $this->getFormDefaultData(); + + if (null === $before) { + return $default; + } + + if (!array_key_exists('start_date', $before) || null === $before['start_date']) { + $before['start_date'] = $default['start_date']; + } + + if (!array_key_exists('end_date', $before) || null === $before['end_date']) { + $before['end_date'] = $default['end_date']; + } + + return $before; + } + public function getTitle(): string { return 'export.filter.course.by_user_job.Filter by user job'; diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserJobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserJobFilterTest.php index 560fe26a7..72ed60fb4 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserJobFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserJobFilterTest.php @@ -50,12 +50,14 @@ final class UserJobFilterTest extends AbstractFilterTest yield [ 'jobs' => new ArrayCollection($jobs), - 'date_calc' => new RollingDate(RollingDate::T_TODAY), + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), ]; yield [ 'jobs' => $jobs, - 'date_calc' => new RollingDate(RollingDate::T_TODAY), + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml index a268ac6c4..d6727f7c1 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml +++ b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml @@ -143,6 +143,8 @@ exports: by_referrer_between_dates: description: >- Filtré par référent du parcours, entre deux dates: depuis le {start_date, date, medium}, jusqu'au {end_date, date, medium}, seulement {agents} + by_user_job: + "Filtered by user job: only job": "Filtré par métier du référent entre le {startDate, date, short} et le {endDate, date, short}: uniquement {job}" work: by_treating_agent: Filtered by treating agent at date: >- diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index fbd33dfd2..d6c10b89d 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1232,7 +1232,8 @@ export: 'Filtered by creator job: only %jobs%': "Filtré par métier du créateur: uniquement %jobs%" by_user_job: Filter by user job: Filtrer les parcours par métier du référent - "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" + Start from: Référent et métier depuis le + Until: Jusqu'au by_social_action: title: Filtrer les parcours par action d'accompagnement Accepted socialactions: Actions d'accompagnement