Feature: [export][acp] aggregator by course's duration

This commit is contained in:
Julien Fastré 2022-10-12 11:04:36 +02:00
parent 3a8640db43
commit d5efbd505c
2 changed files with 31 additions and 22 deletions

View File

@ -13,21 +13,23 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Export\Declarations;
use DateTimeImmutable;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
final class DurationAggregator implements AggregatorInterface final class DurationAggregator implements AggregatorInterface
{ {
private TranslatorInterface $translator;
private const CHOICES = [ private const CHOICES = [
'month', 'month',
'week', 'week',
'day' 'day',
]; ];
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator) public function __construct(TranslatorInterface $translator)
{ {
$this->translator = $translator; $this->translator = $translator;
@ -42,23 +44,29 @@ final class DurationAggregator implements AggregatorInterface
{ {
switch ($data['precision']) { switch ($data['precision']) {
case 'day': case 'day':
$qb->addSelect('(COALESCE(acp.closingDate, NOW()) - acp.openingDate) AS duration_aggregator'); $qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) AS duration_aggregator');
break; break;
case 'week': case 'week':
$qb->addSelect('EXTRACT (YEAR FROM AGE(COALESCE(acp.closingDate, NOW()), acp.openingDate) * 52 + $qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) / 7 AS duration_aggregator');
EXTRACT (WEEK FROM AGE(COALESCE(acp.closingDate, NOW()');
break; break;
case 'month':
$qb->addSelect('(EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate)) * 12 +
EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate))) AS duration_aggregator');
break;
default:
throw new LogicException('precision not supported: ' . $data['precision']);
} }
// TODO Pour avoir un interval plus précis (nécessaire ?): $qb
// adapter la fonction extract pour pouvoir l'utiliser avec des intervals: extract(month from interval) ->setParameter('now', new DateTimeImmutable('now'))
// et ajouter une fonction custom qui calcule plus précisément les intervals, comme doctrineum/date-interval ->addGroupBy('duration_aggregator')
// https://packagist.org/packages/doctrineum/date-interval#3.1.0 (mais composer fait un conflit de dépendance) ->addOrderBy('duration_aggregator');
$qb->addGroupBy('duration_aggregator');
$qb->addOrderBy('duration_aggregator');
} }
public function applyOn(): string public function applyOn(): string
@ -71,7 +79,7 @@ final class DurationAggregator implements AggregatorInterface
$builder->add('precision', ChoiceType::class, [ $builder->add('precision', ChoiceType::class, [
'choices' => array_combine(self::CHOICES, self::CHOICES), 'choices' => array_combine(self::CHOICES, self::CHOICES),
'label' => 'export.aggregator.course.duration.Precision', 'label' => 'export.aggregator.course.duration.Precision',
'choice_label' => fn (string $c) => 'export.aggregator.course.duration.'.$c, 'choice_label' => static fn (string $c) => 'export.aggregator.course.duration.' . $c,
'multiple' => false, 'multiple' => false,
'expanded' => true, 'expanded' => true,
]); ]);
@ -79,20 +87,16 @@ final class DurationAggregator implements AggregatorInterface
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
return function ($value): ?string { return static function ($value) use ($data) {
if ('_header' === $value) { if ('_header' === $value) {
return 'Rounded month duration'; return 'export.aggregator.course.duration.' . $data['precision'];
} }
if (null === $value) { if (null === $value) {
return $this->translator->trans('current duration'); // when closingDate is null return 0;
} }
if (0 === $value) { return $value;
return $this->translator->trans('duration 0 month');
}
return $value . $this->translator->trans(' months');
}; };
} }

View File

@ -951,3 +951,8 @@ export:
Group course by referrer's scope: Grouper les parcours par service du référent 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 Computation date for referrer: Date à laquelle le référent était actif
Referrer's scope: Service du référent de parcours Referrer's scope: Service du référent de parcours
duration:
day: Durée du parcours en jours
week: Durée du parcours en semaines
month: Durée du parcours en mois
Precision: Unité de la durée