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

View File

@ -951,3 +951,8 @@ export:
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
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