diff --git a/.changes/unreleased/Feature-20231018-113825.yaml b/.changes/unreleased/Feature-20231018-113825.yaml new file mode 100644 index 000000000..f8922b356 --- /dev/null +++ b/.changes/unreleased/Feature-20231018-113825.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: '[export] Add a filter "grouping accompanying period by opening date" and "trouping + accompanying period by closing date"' +time: 2023-10-18T11:38:25.80362952+02:00 +custom: + Issue: "172" diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/DateAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/DateAggregator.php index f7315140e..9d9e5ed61 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/DateAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/DateAggregator.php @@ -73,7 +73,6 @@ class DateAggregator implements AggregatorInterface 'choices' => self::CHOICES, 'multiple' => false, 'expanded' => true, - 'empty_data' => self::DEFAULT_CHOICE, ]); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingDateAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingDateAggregator.php new file mode 100644 index 000000000..ce96c40c9 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ClosingDateAggregator.php @@ -0,0 +1,88 @@ +add('frequency', ChoiceType::class, [ + 'choices' => array_combine( + array_map(fn (DateGroupingChoiceEnum $c) => 'export.enum.frequency.'.$c->value, DateGroupingChoiceEnum::cases()), + array_map(fn (DateGroupingChoiceEnum $c) => $c->value, DateGroupingChoiceEnum::cases()), + ), + 'label' => 'export.aggregator.course.by_closing_date.frequency', + 'multiple' => false, + 'expanded' => true, + ]); + } + + public function getFormDefaultData(): array + { + return [ + 'frequency' => 'year', + ]; + } + + public function getLabels($key, array $values, mixed $data) + { + return function (null|string $value): string { + if ('_header' === $value) { + return 'export.aggregator.course.by_closing_date.header'; + } + + return (string) $value; + }; + } + + public function getQueryKeys($data) + { + return [self::PREFIX.'_closing_date']; + } + + public function getTitle() + { + return 'export.aggregator.course.by_closing_date.title'; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $p = self::PREFIX; + + $qb->addSelect(sprintf("TO_CHAR(acp.closingDate, '%s') AS {$p}_closing_date", $data['frequency'])); + $qb->addGroupBy("{$p}_closing_date"); + $qb->addOrderBy("{$p}_closing_date", 'DESC'); + } + + public function applyOn() + { + return Declarations::ACP_TYPE; + } +} diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregator.php new file mode 100644 index 000000000..bf71d04d8 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregator.php @@ -0,0 +1,88 @@ +add('frequency', ChoiceType::class, [ + 'choices' => array_combine( + array_map(fn (DateGroupingChoiceEnum $c) => 'export.enum.frequency.'.$c->value, DateGroupingChoiceEnum::cases()), + array_map(fn (DateGroupingChoiceEnum $c) => $c->value, DateGroupingChoiceEnum::cases()), + ), + 'label' => 'export.aggregator.course.by_opening_date.frequency', + 'multiple' => false, + 'expanded' => true, + ]); + } + + public function getFormDefaultData(): array + { + return [ + 'frequency' => 'year', + ]; + } + + public function getLabels($key, array $values, mixed $data) + { + return function (null|string $value): string { + if ('_header' === $value) { + return 'export.aggregator.course.by_opening_date.header'; + } + + return (string) $value; + }; + } + + public function getQueryKeys($data) + { + return [self::PREFIX.'_opening_date']; + } + + public function getTitle() + { + return 'export.aggregator.course.by_opening_date.title'; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $p = self::PREFIX; + + $qb->addSelect(sprintf("TO_CHAR(acp.openingDate, '%s') AS {$p}_opening_date", $data['frequency'])); + $qb->addGroupBy("{$p}_opening_date"); + $qb->addOrderBy("{$p}_opening_date", 'DESC'); + } + + public function applyOn() + { + return Declarations::ACP_TYPE; + } +} diff --git a/src/Bundle/ChillPersonBundle/Export/Enum/DateGroupingChoiceEnum.php b/src/Bundle/ChillPersonBundle/Export/Enum/DateGroupingChoiceEnum.php new file mode 100644 index 000000000..2b1ffc816 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Enum/DateGroupingChoiceEnum.php @@ -0,0 +1,19 @@ +get(ClosingDateAggregator::class); + self::$entityManager = self::$container->get(EntityManagerInterface::class); + } + + public function getAggregator() + { + return self::$closingDateAggregator; + } + + public function getFormData() + { + yield ['frequency' => 'YYYY']; + yield ['frequency' => 'YYYY-MM']; + yield ['frequency' => 'YYYY-IV']; + } + + public function getQueryBuilders() + { + self::bootKernel(); + self::$entityManager = self::$container->get(EntityManagerInterface::class); + + $data = [ + self::$entityManager->createQueryBuilder() + ->select('count(acp.id)') + ->from(AccompanyingPeriod::class, 'acp'), + ]; + + self::ensureKernelShutdown(); + + return $data; + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregatorTest.php new file mode 100644 index 000000000..77d26b278 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/OpeningDateAggregatorTest.php @@ -0,0 +1,66 @@ +get(OpeningDateAggregator::class); + self::$entityManager = self::$container->get(EntityManagerInterface::class); + } + + public function getAggregator() + { + return self::$openingDateAggregator; + } + + public function getFormData() + { + yield ['frequency' => 'YYYY']; + yield ['frequency' => 'YYYY-MM']; + yield ['frequency' => 'YYYY-IV']; + } + + public function getQueryBuilders() + { + self::bootKernel(); + self::$entityManager = self::$container->get(EntityManagerInterface::class); + + $data = [ + self::$entityManager->createQueryBuilder() + ->select('count(acp.id)') + ->from(AccompanyingPeriod::class, 'acp'), + ]; + + self::ensureKernelShutdown(); + + return $data; + } +} diff --git a/src/Bundle/ChillPersonBundle/config/services/exports_accompanying_course.yaml b/src/Bundle/ChillPersonBundle/config/services/exports_accompanying_course.yaml index c5a2dba68..4eaaf67b0 100644 --- a/src/Bundle/ChillPersonBundle/config/services/exports_accompanying_course.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/exports_accompanying_course.yaml @@ -251,3 +251,11 @@ services: Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators\ScopeWorkingOnCourseAggregator: tags: - { name: chill.export_aggregator, alias: accompanyingcourse_scope_working_on_course_aggregator } + + Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators\OpeningDateAggregator: + tags: + - { name: chill.export_aggregator, alias: accompanyingcourse_opening_date_aggregator } + + Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators\ClosingDateAggregator: + tags: + - { name: chill.export_aggregator, alias: accompanyingcourse_closing_date_aggregator } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 097b5e79f..0c5a0fe57 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -981,6 +981,11 @@ notification: personId: Identifiant de l'usager export: + enum: + frequency: + YYYY-IW: par semaine + YYYY-MM: par mois + YYYY: par année export: acp_stats: avg_duration: Moyenne de la durée de participation de chaque usager concerné @@ -1037,6 +1042,14 @@ export: Calc date: Date de calcul du service de l'intervenant by_scope: Group course by scope: Grouper les parcours par service + by_opening_date: + title: Grouper les parcours par date d'ouverture + frequency: Intervalle de regroupement + header: Date d'ouverture des parcours (période) + by_closing_date: + title: Grouper les parcours par date de cloture + frequency: Intervalle de regroupement + header: Date de cloture des parcours (période) course_work: by_treating_agent: