diff --git a/.changes/unreleased/Feature-20240617-142505.yaml b/.changes/unreleased/Feature-20240617-142505.yaml new file mode 100644 index 000000000..13a2ded4e --- /dev/null +++ b/.changes/unreleased/Feature-20240617-142505.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: '[export] add start date and end date on filters "filter course by referrer + job" and "filter course by referrer scope"' +time: 2024-06-17T14:25:05.041546007+02:00 +custom: + Issue: "282" diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index bfbe8e66d..7e6b1d185 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -14,22 +14,26 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; +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 UserScopeFilter implements FilterInterface +final readonly class UserScopeFilter implements FilterInterface { private const PREFIX = 'acp_filter_main_scope'; public function __construct( - private readonly ScopeRepositoryInterface $scopeRepository, - private readonly TranslatableStringHelper $translatableStringHelper, + private ScopeRepositoryInterface $scopeRepository, + private TranslatableStringHelper $translatableStringHelper, + private RollingDateConverterInterface $rollingDateConverter, ) { } @@ -38,47 +42,35 @@ class UserScopeFilter implements FilterInterface return null; } - public function alterQuery(QueryBuilder $qb, $data) + public function alterQuery(QueryBuilder $qb, $data): void { $p = self::PREFIX; - $qb - ->join( - '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") - ) - ) - ) + $qb->andWhere( + $qb->expr()->exists( + sprintf( + << :{$p}_startDate) + AND {$p}_userScopeHistory.startDate <= :{$p}_endDate + AND ({$p}_userScopeHistory.endDate IS NULL OR {$p}_userScopeHistory.endDate > :{$p}_startDate) + AND {$p}_userScopeHistory.scope IN (:{$p}_scopes) + DQL, + UserHistory::class, + UserScopeHistory::class, + ), ) - ->join( - UserScopeHistory::class, - "{$p}_scopeHistory", - Join::WITH, - $qb->expr()->andX( - $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_userHistory.user"), - $qb->expr()->andX( - $qb->expr()->lte("{$p}_scopeHistory.startDate", "{$p}_userHistory.startDate"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_scopeHistory.endDate"), - $qb->expr()->gt("{$p}_scopeHistory.endDate", "{$p}_userHistory.startDate") - ) - ) - ) - ) - ->andWhere($qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes")) - ->setParameter( - "{$p}_scopes", - $data['scopes'], - ) - ; + ) + ->setParameter("{$p}_scopes", $data['scopes']) + ->setParameter("{$p}_startDate", $this->rollingDateConverter->convert($data['start_date'])) + ->setParameter("{$p}_endDate", $this->rollingDateConverter->convert($data['end_date'])); } public function applyOn(): string @@ -95,20 +87,28 @@ class UserScopeFilter implements FilterInterface 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), 'multiple' => true, 'expanded' => true, + ]) + ->add('start_date', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_user_scope.Start from', + ]) + ->add('end_date', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_user_scope.Until', ]); } public function describeAction($data, $format = 'string') { return [ - 'export.filter.course.by_user_scope.Filtered by user main scope: only %scope%', [ - '%scope%' => implode( + 'exports.filter.course.by_user_scope.Filtered by user main scope: only scopes', [ + 'scopes' => implode( ', ', array_map( fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), $data['scopes'] instanceof Collection ? $data['scopes']->toArray() : $data['scopes'] ) ), + 'startDate' => $this->rollingDateConverter->convert($data['start_date']), + 'endDate' => $this->rollingDateConverter->convert($data['end_date']), ], ]; } @@ -117,9 +117,30 @@ class UserScopeFilter implements FilterInterface { return [ 'scopes' => [], + '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_scope.Filter by user scope'; diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserScopeFilterTest.php index ec98f1bfd..c4d839ad3 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserScopeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/UserScopeFilterTest.php @@ -50,11 +50,13 @@ final class UserScopeFilterTest extends AbstractFilterTest return [ [ - 'date_calc' => new RollingDate(RollingDate::T_TODAY), + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), 'scopes' => new ArrayCollection($scopes), ], [ - 'date_calc' => new RollingDate(RollingDate::T_TODAY), + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), 'scopes' => $scopes, ], ]; diff --git a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml index d6727f7c1..fdc79e4a0 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml +++ b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml @@ -145,6 +145,8 @@ exports: 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}" + by_user_scope: + "Filtered by user main scope: only scopes": "Filtré par service du référent entre le {startDate, date, short} et le {endDate, date, short}: uniquement {scopes}" 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 d6c10b89d..bb40df9a9 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1215,7 +1215,8 @@ export: 'Filtered by steps: only %step% and between %date_from% and %date_to%': 'Filtré par statut: seulement %step%, entre %date_from% et %date_to%' by_user_scope: Filter by user scope: Filtrer les parcours par service du référent - "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" + Start from: Référent et service depuis le + Until: Jusqu'au by_referrer: Computation date for referrer: Date à laquelle le référent était actif by_referrer_between_dates: