diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index ab1048144..1837a4a9b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -11,17 +11,28 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepository; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; use function in_array; final readonly class JobAggregator implements AggregatorInterface { - public function __construct(private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_work_action_agg_user_job'; + + public function __construct( + private RollingDateConverter $rollingDateConverter, + private UserJobRepository $jobRepository, + private TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +41,31 @@ final readonly class JobAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acpwuser', $qb->getAllAliases(), true)) { - $qb->leftJoin('acpw.referrers', 'acpwuser'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(acpwuser.userJob) as job_aggregator') - ->addGroupBy('job_aggregator'); + $qb + ->leftJoin("acpw.referrers", "{$p}_user") + ->leftJoin( + UserJobHistory::class, + "{$p}_history", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_history.user", "{$p}_user") + ) + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) as {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +75,14 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.acpw.agent_job:Calc Date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -63,7 +96,9 @@ final readonly class JobAggregator implements AggregatorInterface return ''; } - $j = $this->jobRepository->find($value); + if (null === $j = $this->jobRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $j->getLabel() @@ -73,11 +108,11 @@ final readonly class JobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['job_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string { - return 'Group by treating agent job'; + return 'export.acpw.agent_job:Group by treating agent job'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php index 77d1fdfcc..cd070aca8 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php @@ -41,7 +41,7 @@ final class UserJobAggregatorTest extends AbstractAggregatorTest { return [ [ - 'job_at' => new RollingDate(RollingDate::T_TODAY) + 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), ], ]; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php index 39cc20083..5a20fc3b1 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators\JobAggregator; @@ -39,7 +40,9 @@ final class JobAggregatorTest extends AbstractAggregatorTest public function getFormData(): array { return [ - [], + [ + 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), + ], ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 0dd982ae4..d6f6eef4d 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -465,10 +465,6 @@ Group course by scope: Grouper les parcours par service 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%" -export.acp.referrer_job: - Group by user job: Grouper les parcours par métier du référent - Calc date: Date de calcul du métier du référent - Filter by social issue: Filtrer les parcours par problématiques sociales Accepted socialissues: Problématiques sociales "Filtered by socialissues: only %socialissues%": "Filtré par problématique sociale: uniquement %socialissues%" @@ -608,7 +604,6 @@ Filter by scope: Filtrer par service Filter by treating agent job: Filtrer les actions par métier de l'agent traitant "Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" -Group by treating agent job: Grouper les actions par métier de l'agent traitant Filter by treating agent: Filtrer les actions par agent traitant Accepted agents: Agent traitant @@ -1004,6 +999,14 @@ notification: personId: Identifiant de l'usager export: + acp: + referrer_job: + Group by user job: Grouper les parcours par métier du référent + Calc date: Date de calcul du métier du référent + acpw: + agent_job: + Group by treating agent job: Grouper les actions par métier de l'agent traitant + Calc date: Date de calcul du métier de l'agent traitant export: acp_stats: avg_duration: Moyenne de la durée de participation de chaque usager concerné