diff --git a/.changes/unreleased/Feature-20240617-162110.yaml b/.changes/unreleased/Feature-20240617-162110.yaml new file mode 100644 index 000000000..c6801b08e --- /dev/null +++ b/.changes/unreleased/Feature-20240617-162110.yaml @@ -0,0 +1,5 @@ +kind: Feature +body: '[export] add date range on "group course by scope''s referrer"' +time: 2024-06-17T16:21:10.342069726+02:00 +custom: + Issue: "282" diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index b0a44bcd1..c183cff70 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -13,20 +13,25 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Export\DataTransformerInterface; +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\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -readonly class ReferrerScopeAggregator implements AggregatorInterface +readonly class ReferrerScopeAggregator implements AggregatorInterface, DataTransformerInterface { private const PREFIX = 'acp_agg_referrer_scope'; public function __construct( private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, + private RollingDateConverterInterface $rollingDateConverter, ) { } @@ -47,11 +52,16 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", 'acp.id'), $qb->expr()->andX( + // check that the user is referrer when the accompanying period is opened $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->expr()->andX( + "{$p}_userHistory.startDate <= :{$p}_endDate", + "COALESCE({$p}_userHistory.endDate, CURRENT_TIMESTAMP()) > :{$p}_startDate" ) ) ) @@ -67,9 +77,15 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface $qb->expr()->isNull("{$p}_scopeHistory.endDate"), $qb->expr()->gt("{$p}_scopeHistory.endDate", "{$p}_userHistory.startDate") ) + ), + $qb->expr()->andX( + "{$p}_scopeHistory.startDate <= :{$p}_endDate", + "COALESCE({$p}_scopeHistory.endDate, CURRENT_TIMESTAMP()) > :{$p}_startDate" ) ) ) + ->setParameter("{$p}_startDate", $this->rollingDateConverter->convert($data['start_date'])) + ->setParameter("{$p}_endDate", $this->rollingDateConverter->convert($data['end_date'])) ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -81,11 +97,34 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { + $builder + ->add('start_date', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_referrer_scope.Referrer and scope after', + 'required' => true, + ]) + ->add('end_date', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_referrer_scope.Until', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return [ + '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(); + $data = []; + + $data['start_date'] = $before['start_date'] ?? new RollingDate(RollingDate::T_FIXED_DATE, new \DateTimeImmutable('1970-01-01')); + $data['end_date'] = $before['end_date'] ?? $default['end_date']; + + return $data; } public function getLabels($key, array $values, $data) diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php index 539b856ec..399a333b7 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php @@ -14,6 +14,7 @@ namespace Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Repository\ScopeRepositoryInterface; use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; @@ -48,16 +49,46 @@ final class ReferrerScopeAggregatorTest extends AbstractAggregatorTest return new ReferrerScopeAggregator( $scopeRepository->reveal(), $translatableStringHelper->reveal(), - $dateConverter->reveal() + new RollingDateConverter(), ); } public function getFormData() { return [ - [ - 'date_calc' => new RollingDate(RollingDate::T_TODAY), - ], + ['start_date' => new RollingDate(RollingDate::T_WEEK_CURRENT_START), 'end_date' => new RollingDate(RollingDate::T_TODAY)], + ]; + } + + /** + * @dataProvider provideBeforeData + */ + public function testDataTransformer(?array $before, array $expected): void + { + $actual = $this->getAggregator()->transformData($before); + + self::assertEqualsCanonicalizing(array_keys($expected), array_keys($actual)); + foreach (['start_date', 'end_date'] as $key) { + self::assertInstanceOf(RollingDate::class, $actual[$key]); + self::assertEquals($expected[$key]->getRoll(), $actual[$key]->getRoll(), "Check that the roll is the same for {$key}"); + } + } + + public function provideBeforeData(): iterable + { + yield [ + null, + ['start_date' => new RollingDate(RollingDate::T_FIXED_DATE, new \DateTimeImmutable('1970-01-01')), 'end_date' => new RollingDate(RollingDate::T_TODAY)], + ]; + + yield [ + [], + ['start_date' => new RollingDate(RollingDate::T_FIXED_DATE, new \DateTimeImmutable('1970-01-01')), 'end_date' => new RollingDate(RollingDate::T_TODAY)], + ]; + + yield [ + ['start_date' => new RollingDate(RollingDate::T_WEEK_CURRENT_START), 'end_date' => new RollingDate(RollingDate::T_TODAY)], + ['start_date' => new RollingDate(RollingDate::T_WEEK_CURRENT_START), 'end_date' => new RollingDate(RollingDate::T_TODAY)], ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index fc95da2ea..d3922de26 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1061,6 +1061,9 @@ export: by_referrer: Referrer after: Référent après le Until: Jusqu'au + by_referrer_scope: + Referrer and scope after: Référent et service après le + Until: Jusqu'au by_user_scope: Group course by referrer's scope: Grouper les parcours par service du référent Referrer's scope: Service du référent de parcours