From 68d28f3e28c4f33ea031f90090d47f07021fa36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 10:58:41 +0200 Subject: [PATCH] Fix filtres and scopes to take into account job and scope when the refferrer is add to the accompanying period work --- .../Export/Export/ListActivityHelper.php | 6 +- .../translations/messages.fr.yml | 3 + .../src/Export/Export/ListAsideActivity.php | 7 +- .../Export/Export/ListAsideActivityTest.php | 43 +++++++++ src/Bundle/ChillMainBundle/Entity/User.php | 8 +- .../Export/Helper/ExportAddressHelper.php | 4 +- .../Export/Helper/UserHelper.php | 90 ++++++++++++++----- .../Resources/views/Entity/user.html.twig | 8 +- .../Templating/Entity/UserRender.php | 15 +++- .../SocialWorkAggregators/JobAggregator.php | 39 +++----- .../ReferrerAggregator.php | 2 +- .../SocialWorkAggregators/ScopeAggregator.php | 39 +++----- .../Export/Export/ListEvaluation.php | 6 +- .../Filter/SocialWorkFilters/JobFilter.php | 38 ++------ .../Filter/SocialWorkFilters/ScopeFilter.php | 37 ++------ .../Helper/ListAccompanyingPeriodHelper.php | 15 ++-- .../JobAggregatorTest.php | 5 +- .../ScopeAggregatorTest.php | 5 +- .../Export/ListAccompanyingPeriodTest.php | 53 +++++++++++ .../Export/ListAccompanyingPeriodWorkTest.php | 49 ++++++++++ .../Export/Export/ListEvaluationTest.php | 49 ++++++++++ .../SocialWorkFilters/JobFilterTest.php | 1 - .../SocialWorkFilters/ScopeFilterTest.php | 1 - .../translations/messages.fr.yml | 2 + 24 files changed, 352 insertions(+), 173 deletions(-) create mode 100644 src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php diff --git a/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php b/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php index 84d94c000..ea43d387d 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php @@ -57,7 +57,7 @@ class ListActivityHelper ->addSelect('AGGREGATE(actPerson.id) AS personsNames') ->leftJoin('activity.users', 'users_u') ->addSelect('AGGREGATE(users_u.id) AS usersIds') - ->addSelect('AGGREGATE(users_u.id) AS usersNames') + ->addSelect('AGGREGATE(JSON_BUILD_OBJECT(\'uid\', users_u.id, \'d\', activity.date)) AS usersNames') ->leftJoin('activity.thirdParties', 'thirdparty') ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds') ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames') @@ -68,9 +68,9 @@ class ListActivityHelper ->leftJoin('activity.location', 'location') ->addSelect('location.name AS locationName') ->addSelect('activity.sentReceived') - ->addSelect('IDENTITY(activity.createdBy) AS createdBy') + ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy') ->addSelect('activity.createdAt') - ->addSelect('IDENTITY(activity.updatedBy) AS updatedBy') + ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy') ->addSelect('activity.updatedAt') ->addGroupBy('activity.id') ->addGroupBy('location.id'); diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 3496f7a52..8deebbb8c 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -395,6 +395,9 @@ export: by_creator_scope: Group activity by creator scope: Grouper les échanges par service du créateur de l'échange Calc date: Date de calcul du service du créateur de l'échange + by_creator_job: + Group activity by creator job: Grouper les échanges par service du créateur de l'échange + Calc date: Date de calcul du service du créateur de l'échange generic_doc: filter: diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php index f01c3efc2..0981c6bf8 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php @@ -182,7 +182,10 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn { $qb = $this->em->createQueryBuilder() ->from(AsideActivity::class, 'aside') - ->leftJoin('aside.agent', 'agent'); + ->leftJoin('aside.agent', 'agent') + ->leftJoin('agent.scopeHistories', 'scopeHistories') + ->andWhere('scopeHistories.startDate <= aside.date AND (scopeHistories.endDate IS NULL or scopeHistories.endDate > aside.date)') + ; $qb ->addSelect('aside.id AS id') @@ -190,7 +193,7 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn ->addSelect('aside.updatedAt AS updatedAt') ->addSelect('IDENTITY(aside.agent) AS agent_id') ->addSelect('IDENTITY(aside.createdBy) AS creator_id') - ->addSelect('IDENTITY(agent.mainScope) AS main_scope') /// + ->addSelect('IDENTITY(scopeHistories.scope) AS main_scope') ->addSelect('IDENTITY(agent.mainCenter) AS main_center') ->addSelect('IDENTITY(aside.type) AS aside_activity_type') ->addSelect('aside.date') diff --git a/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php b/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php new file mode 100644 index 000000000..6bd29ef1d --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php @@ -0,0 +1,43 @@ +listAsideActivity = self::$container->get(ListAsideActivity::class); + } + + public function testExecuteQuery(): void + { + $qb = $this->listAsideActivity->initiateQuery([], [], []) + ->setMaxResults(1); + + $results = $qb->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY); + + self::assertIsArray($results, "smoke test: test that the result is an array"); + } +} diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 33c8be166..5df70134b 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -292,9 +292,7 @@ class User implements UserInterface, \Stringable $sortedScopeHistories = $scopeHistories->toArray(); - usort($sortedScopeHistories, function ($a, $b) { - return $a->getStartDate() < $b->getStartDate() ? 1 : -1; - }); + usort($sortedScopeHistories, fn ($a, $b) => $a->getStartDate() < $b->getStartDate() ? 1 : -1); return new ArrayCollection($sortedScopeHistories); } @@ -346,9 +344,7 @@ class User implements UserInterface, \Stringable $sortedJobHistories = $jobHistories->toArray(); - usort($sortedJobHistories, function ($a, $b) { - return $a->getStartDate() < $b->getStartDate() ? 1 : -1; - }); + usort($sortedJobHistories, fn ($a, $b) => $a->getStartDate() < $b->getStartDate() ? 1 : -1); return new ArrayCollection($sortedJobHistories); } diff --git a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php index 01bd7f2fc..a3e4bae86 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php @@ -281,9 +281,9 @@ class ExportAddressHelper }; case 'country': - return function ($value) use ($key) { + return function ($value) use ($sanitizedKey, $translationPrefix) { if ('_header' === $value) { - return 'export.list.acp' . $key; + return $translationPrefix . $sanitizedKey; } if (null === $value) { diff --git a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php index 996f8d925..44c2f260f 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php @@ -20,21 +20,64 @@ class UserHelper { public function __construct(private readonly UserRender $userRender, private readonly UserRepositoryInterface $userRepository) {} + /** + * Return a callable that will transform a value into a string representing a user + * + * The callable may receive as argument: + * + * - an int or a string, the id of the user; + * - a string containing a json which will be decoded, and will have this structure: array{uid: int, d: string}. The job and scopes will be shown at this date + * + * @param string $key the key of the content + * @param array $values the list of values + * @param string $header the header's content + */ public function getLabel($key, array $values, string $header): callable { - return function ($value) use ($header) { + return function (null|int|string $value) use ($header) { if ('_header' === $value) { return $header; } - if (null === $value || null === $user = $this->userRepository->find($value)) { + if (null === $value) { return ''; } - return $this->userRender->renderString($user, []); + if (is_numeric($value)) { + $uid = $value; + $date = null; + } else { + $decode = json_decode($value, true, 512, JSON_THROW_ON_ERROR); + $uid = $decode['uid']; + + if (null === $uid) { + return ''; + } + + $date = new \DateTimeImmutable($decode['d']); + } + + if (null === $user = $this->userRepository->find($uid)) { + return ''; + } + + return $this->userRender->renderString($user, ['at' => $date]); }; } + /** + * Return a callable that will transform a value into a string representing a user + * + * The callable may receive as argument: + * + * - an int or a string, the id of the user; + * - a string containing a json which will be decoded, and will have this structure: array{uid: int, d: string}. The job and scopes will be shown at this date * @param $key + * + * @param string $key the key of the element + * @param array $values a list of values + * @param string $header the header's content + * @return callable + */ public function getLabelMulti($key, array $values, string $header): callable { return function ($value) use ($header) { @@ -46,31 +89,36 @@ class UserHelper return ''; } - $decoded = json_decode((string) $value, null, 512, JSON_THROW_ON_ERROR); + $decoded = json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR); if (0 === count($decoded)) { return ''; } + $asStrings = []; - return - implode( - '|', - array_map( - function (int $userId) { - $user = $this->userRepository->find($userId); + foreach ($decoded as $userId) { + if (is_array($userId)) { + $uid = $userId['uid']; + $date = new \DateTimeImmutable($userId['d']); + } else { + $uid = $userId; + $date = null; + } - if (null === $user) { - return ''; - } + if (null === $uid) { + continue; + } - return $this->userRender->renderString($user, []); - }, - array_unique( - array_filter($decoded, static fn (?int $userId) => null !== $userId), - SORT_NUMERIC - ) - ) - ); + $user = $this->userRepository->find($uid); + + if (null === $user) { + continue; + } + + $asStrings[$uid] = $this->userRender->renderString($user, ['absence' => false, 'at' => $date]); + } + + return implode('|', $asStrings); }; } } diff --git a/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig index ad05a5a2c..c95308610 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig @@ -1,10 +1,10 @@ {{- user.label }} - {%- if opts['user_job'] and user.userJob is not null %} - ({{ user.userJob.label|localize_translatable_string }}) + {%- if opts['user_job'] and user.userJob(opts['at']) is not null %} + ({{ user.userJob(opts['at']).label|localize_translatable_string }}) {%- endif -%} - {%- if opts['main_scope'] and user.mainScope is not null %} - ({{ user.mainScope.name|localize_translatable_string }}) + {%- if opts['main_scope'] and user.mainScope(opts['at']) is not null %} + ({{ user.mainScope(opts['at']).name|localize_translatable_string }}) {%- endif -%} {%- if opts['absence'] and user.isAbsent %} {{ 'absence.A'|trans }} diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php index 0878453b2..c26664bf1 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php @@ -28,10 +28,14 @@ class UserRender implements ChillEntityRenderInterface 'main_scope' => true, 'user_job' => true, 'absence' => true, + 'at' => null, ]; public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly \Twig\Environment $engine, private readonly TranslatorInterface $translator) {} + /** + * @param mixed $entity + */ public function renderBox($entity, array $options): string { $opts = array_merge(self::DEFAULT_OPTIONS, $options); @@ -42,20 +46,23 @@ class UserRender implements ChillEntityRenderInterface ]); } + /** + * @param mixed $entity + */ public function renderString($entity, array $options): string { $opts = array_merge(self::DEFAULT_OPTIONS, $options); $str = $entity->getLabel(); - if (null !== $entity->getUserJob() && $opts['user_job']) { + if (null !== $entity->getUserJob($opts['at']) && $opts['user_job']) { $str .= ' (' . $this->translatableStringHelper - ->localize($entity->getUserJob()->getLabel()) . ')'; + ->localize($entity->getUserJob($opts['at'])->getLabel()) . ')'; } - if (null !== $entity->getMainScope() && $opts['main_scope']) { + if (null !== $entity->getMainScope($opts['at']) && $opts['main_scope']) { $str .= ' (' . $this->translatableStringHelper - ->localize($entity->getMainScope()->getName()) . ')'; + ->localize($entity->getMainScope($opts['at'])->getName()) . ')'; } if ($entity->isAbsent() && $opts['absence']) { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index 6012bbcab..c95d4ef37 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -11,13 +11,16 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserJobHistory; +use Chill\MainBundle\Entity\UserJob; 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\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; @@ -29,7 +32,6 @@ final readonly class JobAggregator implements AggregatorInterface private const PREFIX = 'acp_work_action_agg_user_job'; public function __construct( - private RollingDateConverter $rollingDateConverter, private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -44,27 +46,16 @@ final readonly class JobAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin("acpw.referrers", "{$p}_user") ->leftJoin( - UserJobHistory::class, - "{$p}_history", + UserJob::class, + "{$p}_job", 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']) + 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history + JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.jobHistories {$p}_job_history + WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND IDENTITY({$p}_job_history.job) = {$p}_job.id AND {$p}_job_history.startDate <= {$p}_ref_history.startDate + AND ({$p}_job_history.endDate IS NULL or {$p}_job_history.endDate >= {$p}_ref_history.startDate))" ) + ->addSelect("{$p}_job.id as {$p}_select") ->addGroupBy("{$p}_select"); } @@ -73,17 +64,11 @@ final readonly class JobAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course_work.by_agent_job.Calc date', - 'required' => true - ]); - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { - return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php index 6af106715..3bec8730b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php @@ -65,7 +65,7 @@ final readonly class ReferrerAggregator implements AggregatorInterface $r = $this->userRepository->find($value); - return $this->userRender->renderString($r, []); + return $this->userRender->renderString($r, ['absence' => false, 'user_job' => false, 'main_scope' => false]); }; } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php index b6c799079..6fc158dad 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php @@ -11,13 +11,16 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; +use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepository; use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; @@ -29,7 +32,6 @@ final readonly class ScopeAggregator implements AggregatorInterface private const PREFIX = 'acp_work_action_agg_user_scope'; public function __construct( - private RollingDateConverter $rollingDateConverter, private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -44,27 +46,16 @@ final readonly class ScopeAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin("acpw.referrers", "{$p}_user") ->leftJoin( - UserScopeHistory::class, - "{$p}_history", + Scope::class, + "{$p}_scope", 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.scope) as {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) + 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history + JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.scopeHistories {$p}_scope_history + WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND IDENTITY({$p}_scope_history.scope) = {$p}_scope.id AND {$p}_scope_history.startDate <= {$p}_ref_history.startDate + AND ({$p}_scope_history.endDate IS NULL or {$p}_scope_history.endDate >= {$p}_ref_history.startDate))" ) + ->addSelect("{$p}_scope.id as {$p}_select") ->addGroupBy("{$p}_select"); } @@ -73,17 +64,11 @@ final readonly class ScopeAggregator implements AggregatorInterface return Declarations::SOCIAL_WORK_ACTION_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course_work.by_agent_scope.Calc date', - 'required' => true, - ]); - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data) diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php index 34646dbd0..253b4f34c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php @@ -132,7 +132,7 @@ class ListEvaluation implements ListInterface, GroupedExportInterface ); }, 'createdBy', 'updatedBy', 'acpw_acp_user' => $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key), - 'acpw_referrers' => $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key), + 'acpw_referrers' => $this->userHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key), 'acpw_persons_id' => $this->aggregateStringHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key), 'acpw_persons' => $this->personHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key), 'eval_title' => $this->translatableStringExportLabelHelper @@ -252,8 +252,8 @@ class ListEvaluation implements ListInterface, GroupedExportInterface // referrers => at date XXXX $qb - ->addSelect('(SELECT IDENTITY(history.user) FROM ' . UserHistory::class . ' history ' . - 'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS acpw_referrers'); + ->addSelect('(SELECT JSON_BUILD_OBJECT(\'uid\', IDENTITY(history.user), \'d\', history.startDate) FROM ' . UserHistory::class . ' history ' . + 'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS referrers'); // persons $qb diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php index 2ad01c3ff..c0de87d65 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr\Andx; @@ -32,7 +33,6 @@ class JobFilter implements FilterInterface private const PREFIX = 'acp_work_action_filter_user_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -46,30 +46,14 @@ class JobFilter implements FilterInterface { $p = self::PREFIX; - $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") - ) - ) - ) - ->andWhere( - $qb->expr()->in("{$p}_history.job", ":{$p}_job") - ) - ->setParameters([ - "{$p}_job" => $data["job"], - "{$p}_at" => $this->rollingDateConverter->convert($data['job_at']) - ]); + $qb->andWhere( + 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history + JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.jobHistories {$p}_job_history + WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND {$p}_job_history.job IN (:{$p}_job) AND {$p}_job_history.startDate <= {$p}_ref_history.startDate + AND ({$p}_job_history.endDate IS NULL or {$p}_job_history.endDate >= {$p}_ref_history.startDate))" + ); + + $qb->setParameter("{$p}_job", $data["job"]); } public function applyOn(): string @@ -88,10 +72,6 @@ class JobFilter implements FilterInterface 'multiple' => true, 'expanded' => true, ]) - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.filter.work.by_user_job.Calc date', - 'required' => true, - ]) ; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php index c5041aa6c..ce9b4e585 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php @@ -18,6 +18,7 @@ use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; @@ -30,7 +31,6 @@ class ScopeFilter implements FilterInterface private const PREFIX = 'acp_work_action_filter_user_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -44,30 +44,13 @@ class ScopeFilter implements FilterInterface { $p = self::PREFIX; - $qb - ->leftJoin("acpw.referrers", "{$p}_user") - ->leftJoin( - UserScopeHistory::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") - ) - ) - ) - ->andWhere( - $qb->expr()->in("{$p}_history.scope", ":{$p}_scope") - ) - ->setParameters([ - "{$p}_scope" => $data["scope"], - "{$p}_at" => $this->rollingDateConverter->convert($data['scope_at']) - ]); + $qb->andWhere( + 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history + JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.scopeHistories {$p}_scope_history + WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND {$p}_scope_history.scope IN (:{$p}_scope) AND {$p}_scope_history.startDate <= {$p}_ref_history.startDate + AND ({$p}_scope_history.endDate IS NULL or {$p}_scope_history.endDate >= {$p}_ref_history.startDate))" + ) + ->setParameter("{$p}_scope", $data["scope"]); } public function applyOn() @@ -86,10 +69,6 @@ class ScopeFilter implements FilterInterface 'multiple' => true, 'expanded' => true, ]) - ->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.filter.work.by_user_scope.Calc date', - 'required' => true, - ]) ; } diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php index 7349c5457..1531b0489 100644 --- a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php +++ b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php @@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Export\Helper\DateTimeHelper; use Chill\MainBundle\Export\Helper\ExportAddressHelper; +use Chill\MainBundle\Export\Helper\UserHelper; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; @@ -59,8 +60,10 @@ final readonly class ListAccompanyingPeriodHelper 'scopes', 'socialIssues', 'acpCreatedAt', + 'acpCreatedBy_id', 'acpCreatedBy', 'acpUpdatedAt', + 'acpUpdatedBy_id', 'acpUpdatedBy', ]; @@ -75,6 +78,7 @@ final readonly class ListAccompanyingPeriodHelper private SocialIssueRender $socialIssueRender, private TranslatableStringHelperInterface $translatableStringHelper, private TranslatorInterface $translator, + private UserHelper $userHelper, ) {} public function getQueryKeys($data) @@ -104,6 +108,7 @@ final readonly class ListAccompanyingPeriodHelper return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR)); }, + 'acpCreatedBy', 'acpUpdatedBy', 'referrer' => $this->userHelper->getLabel($key, $values, 'export.list.acp.' . $key), 'locationPersonName', 'requestorPerson' => function ($value) use ($key) { if ('_header' === $value) { return 'export.list.acp.' . $key; @@ -204,11 +209,11 @@ final readonly class ListAccompanyingPeriodHelper // add the field which are simple association $qb - ->leftJoin('acp.createdBy', "acp_created_by_t") - ->addSelect('acp_created_by_t.label AS acpCreatedBy'); + ->addSelect('IDENTITY(acp.createdBy) AS acpCreatedBy_id') + ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(acp.createdBy), \'d\', acp.createdAt) AS acpCreatedBy'); $qb - ->leftJoin('acp.updatedBy', "acp_updated_by_t") - ->addSelect('acp_updated_by_t.label AS acpUpdatedBy'); + ->addSelect('IDENTITY(acp.updatedBy) AS acpUpdatedBy_id') + ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(acp.updatedBy), \'d\', acp.updatedAt) AS acpUpdatedBy'); foreach (['origin' => 'label', 'closingMotive' => 'name', 'job' => 'label', 'administrativeLocation' => 'name'] as $entity => $field) { $qb @@ -230,7 +235,7 @@ final readonly class ListAccompanyingPeriodHelper // referree at date $qb - ->addSelect('referrer_t.label AS referrer') + ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(userHistory.user), \'d\', userHistory.startDate) AS referrer') ->addSelect('userHistory.startDate AS referrerSince') ->leftJoin('acp.userHistories', 'userHistory') ->leftJoin('userHistory.user', 'referrer_t') diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php index 5a20fc3b1..dfd6db053 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php @@ -40,9 +40,7 @@ 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')), - ], + [], ]; } @@ -57,7 +55,6 @@ final class JobAggregatorTest extends AbstractAggregatorTest ->select('count(acp.id)') ->from(AccompanyingPeriod::class, 'acp') ->join('acp.works', 'acpw') - ->join('acpw.referrers', 'acpwuser'), ]; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php index 0bb9fba13..3cd8c93fe 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php @@ -40,9 +40,7 @@ final class ScopeAggregatorTest extends AbstractAggregatorTest public function getFormData(): array { return [ - [ - 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), - ], + [], ]; } @@ -57,7 +55,6 @@ final class ScopeAggregatorTest extends AbstractAggregatorTest ->select('count(acp.id)') ->from(AccompanyingPeriod::class, 'acp') ->join('acp.works', 'acpw') - ->join('acpw.referrers', 'acpwuser'), ]; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php new file mode 100644 index 000000000..24a49bab3 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php @@ -0,0 +1,53 @@ +listAccompanyingPeriod = self::$container->get(ListAccompanyingPeriod::class); + $this->centerRepository = self::$container->get(CenterRepositoryInterface::class); + } + + public function testQuery(): void + { + $centers = $this->centerRepository->findAll(); + + $query = $this->listAccompanyingPeriod->initiateQuery([], array_map(fn (Center $c) => ['center' => $c ], $centers), $exportOpts = ['calc_date' => new RollingDate(RollingDate::T_TODAY)]); + + $query->setMaxResults(1); + + $actual = $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY); + + self::assertIsArray($actual); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php new file mode 100644 index 000000000..3467f15a7 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php @@ -0,0 +1,49 @@ +listAccompanyingPeriodWork = self::$container->get(ListAccompanyingPeriodWork::class); + $this->centerRepository = self::$container->get(CenterRepositoryInterface::class); + } + + public function testQuery(): void + { + $centers = $this->centerRepository->findAll(); + + $query = $this->listAccompanyingPeriodWork->initiateQuery([], array_map(fn (Center $c) => ['center' => $c], $centers), ['calc_date' => new RollingDate(RollingDate::T_TODAY)]); + $query->setMaxResults(1); + + self::assertIsArray($query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY)); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php new file mode 100644 index 000000000..d7db24a82 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php @@ -0,0 +1,49 @@ +listEvaluation = self::$container->get(ListEvaluation::class); + $this->centerRepository = self::$container->get(CenterRepositoryInterface::class); + } + + public function testQuery(): void + { + $centers = $this->centerRepository->findAll(); + + $query = $this->listEvaluation->initiateQuery([], array_map(fn (Center $c) => ['center' => $c], $centers), ['calc_date' => new RollingDate(RollingDate::T_TODAY)]); + $query->setMaxResults(1); + + self::assertIsArray($query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY)); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php index f5836c18c..e8ed85ad4 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php @@ -51,7 +51,6 @@ final class JobFilterTest extends AbstractFilterTest return [ [ 'job' => new ArrayCollection($jobs), - 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')) ] ]; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php index f2ffce2e4..c3e29f71e 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php @@ -50,7 +50,6 @@ final class ScopeFilterTest extends AbstractFilterTest return [ [ 'scope' => $scopes, - 'scope_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 639de0443..542471149 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1187,7 +1187,9 @@ export: origin: Origine du parcours acpClosingMotive: Motif de fermeture acpJob: Métier du parcours + acpCreatedBy_id: Créé par (identifiant) acpCreatedBy: Créé par + acpUpdatedBy_id: Dernière modificaton par (identifiant) acpUpdatedBy: Dernière modification par administrativeLocation: Location administrative step: Etape