diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php index 1498fc3a1..327b76a65 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerAggregator.php @@ -12,15 +12,20 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Repository\UserRepository; use Chill\MainBundle\Templating\Entity\UserRender; use Chill\PersonBundle\Export\Declarations; +use DateTimeImmutable; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; final class ReferrerAggregator implements AggregatorInterface { + private const A = 'acp_ref_agg_uhistory'; + + private const P = 'acp_ref_agg_date'; + private UserRender $userRender; private UserRepository $userRepository; @@ -40,12 +45,23 @@ final class ReferrerAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acpuser', $qb->getAllAliases(), true)) { - $qb->leftJoin('acp.user', 'acpuser'); - } - - $qb->addSelect('acpuser.id AS referrer_aggregator'); - $qb->addGroupBy('referrer_aggregator'); + $qb + ->addSelect('IDENTITY(' . self::A . '.user) AS referrer_aggregator') + ->addGroupBy('referrer_aggregator') + ->leftJoin('acp.userHistories', self::A) + ->andWhere( + $qb->expr()->orX( + $qb->expr()->isNull(self::A), + $qb->expr()->andX( + $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->orX( + $qb->expr()->isNull(self::A . '.endDate'), + $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + ) + ) + ) + ) + ->setParameter(self::P, $data['date_calc']); } public function applyOn(): string @@ -55,7 +71,13 @@ final class ReferrerAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder + ->add('date_calc', ChillDateType::class, [ + 'input' => 'datetime_immutable', + 'data' => new DateTimeImmutable('now'), + 'label' => 'export.aggregator.course.by_referrer.Computation date for referrer', + 'required' => true, + ]); } public function getLabels($key, array $values, $data) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php index 53ab10564..8781f6cad 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ReferrerFilter.php @@ -11,17 +11,23 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; -use Chill\MainBundle\Entity\User; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\ChillDateType; +use Chill\MainBundle\Form\Type\PickUserDynamicType; use Chill\MainBundle\Templating\Entity\UserRender; use Chill\PersonBundle\Export\Declarations; -use Doctrine\ORM\Query\Expr\Andx; +use DateTimeImmutable; use Doctrine\ORM\QueryBuilder; -use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; class ReferrerFilter implements FilterInterface { + private const A = 'acp_referrer_filter_uhistory'; + + private const P = 'acp_referrer_filter_date'; + + private const PU = 'acp_referrer_filter_users'; + private UserRender $userRender; public function __construct(UserRender $userRender) @@ -36,17 +42,22 @@ class ReferrerFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('acp.user', ':referrers'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('referrers', $data['accepted_referrers']); + $qb + ->join('acp.userHistories', self::A) + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->orX( + $qb->expr()->isNull(self::A . '.endDate'), + $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + ) + ) + ) + ->andWhere( + $qb->expr()->in(self::A . '.user', ':' . self::PU) + ) + ->setParameter(self::PU, $data['accepted_referrers']) + ->setParameter(self::P, $data['date_calc']); } public function applyOn(): string @@ -56,14 +67,16 @@ class ReferrerFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_referrers', EntityType::class, [ - 'class' => User::class, - 'choice_label' => function (User $u) { - return $this->userRender->renderString($u, []); - }, - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('accepted_referrers', PickUserDynamicType::class, [ + 'multiple' => true, + ]) + ->add('date_calc', ChillDateType::class, [ + 'input' => 'datetime_immutable', + 'data' => new DateTimeImmutable('now'), + 'label' => 'export.filter.course.by_referrer.Computation date for referrer', + 'required' => true, + ]); } public function describeAction($data, $format = 'string'): array diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index e55c391ef..a18442c2a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -14,9 +14,11 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use DateTimeImmutable; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -24,6 +26,14 @@ use Symfony\Component\Security\Core\Security; class UserJobFilter implements FilterInterface { + private const A = 'acp_ujob_filter_uhistory'; + + private const AU = 'acp_ujob_filter_uhistory_user'; + + private const P = 'acp_ujob_filter_date'; + + private const PJ = 'acp_ujob_filter_job'; + private Security $security; private TranslatableStringHelper $translatableStringHelper; @@ -48,10 +58,22 @@ class UserJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { $qb + ->join('acp.userHistories', self::A) ->andWhere( - $qb->expr()->in('acp.job', ':acp_user_job_filter_j') + $qb->expr()->andX( + $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->orX( + $qb->expr()->isNull(self::A . '.endDate'), + $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + ) + ) ) - ->setParameter('acp_user_job_filter_j', $data['jobs']); + ->setParameter(self::P, $data['date_calc']) + ->join(self::A . '.user', self::AU) + ->andWhere( + $qb->expr()->in(self::AU . '.userJob', ':' . self::PJ) + ) + ->setParameter(self::PJ, $data['jobs']); } public function applyOn() @@ -61,14 +83,21 @@ class UserJobFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('jobs', EntityType::class, [ - 'class' => UserJob::class, - 'choices' => $this->userJobRepository->findAllActive(), - 'multiple' => true, - 'expanded' => true, - 'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), - 'label' => 'Job', - ]); + $builder + ->add('jobs', EntityType::class, [ + 'class' => UserJob::class, + 'choices' => $this->userJobRepository->findAllActive(), + 'multiple' => true, + 'expanded' => true, + 'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), + 'label' => 'Job', + ]) + ->add('date_calc', ChillDateType::class, [ + 'input' => 'datetime_immutable', + 'data' => new DateTimeImmutable('now'), + 'label' => 'export.filter.course.by_user_scope.Computation date for referrer', + 'required' => true, + ]); } public function describeAction($data, $format = 'string') diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index c079b2bec..48a97f9f7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -14,9 +14,11 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use DateTimeImmutable; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -24,6 +26,14 @@ use Symfony\Component\Security\Core\Security; class UserScopeFilter implements FilterInterface { + private const A = 'acp_uscope_filter_uhistory'; + + private const AU = 'acp_uscope_filter_uhistory_user'; + + private const P = 'acp_uscope_filter_date'; + + private const PS = 'acp_uscope_filter_scopes'; + private ScopeRepositoryInterface $scopeRepository; private Security $security; @@ -47,14 +57,23 @@ class UserScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - foreach ($data['scopes'] as $key => $scope) { - /** @var Scope $scope */ - $qb - ->andWhere( - $qb->expr()->isMemberOf(':acp_scope_filter_s_' . $key, 'acp.scopes') + $qb + ->join('acp.userHistories', self::A) + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->orX( + $qb->expr()->isNull(self::A . '.endDate'), + $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + ) ) - ->setParameter('acp_scope_filter_s_' . $key, $scope); - } + ) + ->setParameter(self::P, $data['date_calc']) + ->join(self::A . '.user', self::AU) + ->andWhere( + $qb->expr()->in(self::AU . '.mainScope', ':' . self::PS) + ) + ->setParameter(self::PS, $data['scopes']); } public function applyOn() @@ -64,13 +83,20 @@ class UserScopeFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scopes', EntityType::class, [ - 'class' => Scope::class, - 'choices' => $this->scopeRepository->findAllActive(), - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choices' => $this->scopeRepository->findAllActive(), + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('date_calc', ChillDateType::class, [ + 'input' => 'datetime_immutable', + 'data' => new DateTimeImmutable('now'), + 'label' => 'export.filter.course.by_user_scope.Computation date for referrer', + 'required' => true, + ]); } public function describeAction($data, $format = 'string') diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 7e9fbfeaa..76fb12d18 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -947,6 +947,8 @@ notification: export: aggregator: course: + by_referrer: + Computation date for referrer: Date à laquelle le référent était actif by_user_scope: Group course by referrer's scope: Grouper les parcours par service du référent Computation date for referrer: Date à laquelle le référent était actif @@ -956,3 +958,10 @@ export: week: Durée du parcours en semaines month: Durée du parcours en mois Precision: Unité de la durée + filter: + course: + by_user_scope: + Computation date for referrer: Date à laquelle le référent était actif + by_referrer: + Computation date for referrer: Date à laquelle le référent était actif +