diff --git a/config/packages/chill_aside_activity.yaml b/config/packages/chill_aside_activity.yaml new file mode 100644 index 000000000..eb5c2d70e --- /dev/null +++ b/config/packages/chill_aside_activity.yaml @@ -0,0 +1,2 @@ +chill_aside_activity: + show_concerned_persons_count: hidden diff --git a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/ChillAsideActivityExtension.php b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/ChillAsideActivityExtension.php index 056f29ba1..6fa123146 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/ChillAsideActivityExtension.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/ChillAsideActivityExtension.php @@ -25,6 +25,7 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte $config = $this->processConfiguration($configuration, $configs); $container->setParameter('chill_aside_activity.form.time_duration', $config['form']['time_duration']); + $container->setParameter('chill_aside_activity.show_concerned_persons_count', 'visible' === $config['show_concerned_persons_count']); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader->load('services.yaml'); @@ -38,6 +39,24 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte { $this->prependRoute($container); $this->prependCruds($container); + $this->prependTwigConfig($container); + } + + protected function prependTwigConfig(ContainerBuilder $container) + { + // Get the configuration for this bundle + $chillAsideActivityConfig = $container->getExtensionConfig($this->getAlias()); + $config = $this->processConfiguration($this->getConfiguration($chillAsideActivityConfig, $container), $chillAsideActivityConfig); + + // Add configuration to twig globals + $twigConfig = [ + 'globals' => [ + 'chill_aside_activity_config' => [ + 'show_concerned_persons_count' => 'visible' === $config['show_concerned_persons_count'], + ], + ], + ]; + $container->prependExtensionConfig('twig', $twigConfig); } protected function prependCruds(ContainerBuilder $container) diff --git a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php index 241a545a8..66f3d3c86 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php @@ -141,6 +141,12 @@ class Configuration implements ConfigurationInterface ->end() ->end() ->end() + ->end() + ->enumNode('show_concerned_persons_count') + ->values(['hidden', 'visible']) + ->defaultValue('hidden') + ->info('Show the concerned persons count field in aside activity forms and views') + ->end() ->end(); return $treeBuilder; diff --git a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php index b7671c61a..0082deaf9 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php @@ -62,6 +62,10 @@ class AsideActivity implements TrackCreationInterface, TrackUpdateInterface #[ORM\ManyToOne(targetEntity: User::class)] private User $updatedBy; + #[Assert\GreaterThanOrEqual(0)] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, nullable: true)] + private ?int $concernedPersonsCount = 0; + public function getAgent(): ?User { return $this->agent; @@ -186,4 +190,16 @@ class AsideActivity implements TrackCreationInterface, TrackUpdateInterface return $this; } + + public function getConcernedPersonsCount(): ?int + { + return $this->concernedPersonsCount; + } + + public function setConcernedPersonsCount(?int $concernedPersonsCount): self + { + $this->concernedPersonsCount = $concernedPersonsCount; + + return $this; + } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByConcernedPersonsCountAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByConcernedPersonsCountAggregator.php new file mode 100644 index 000000000..444c49269 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByConcernedPersonsCountAggregator.php @@ -0,0 +1,86 @@ +addSelect('aside.concernedPersonsCount AS by_concerned_persons_count_aggregator') + ->addGroupBy('by_concerned_persons_count_aggregator'); + } + + public function applyOn(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder): void + { + // No form needed + } + + public function getNormalizationVersion(): int + { + return 1; + } + + public function normalizeFormData(array $formData): array + { + return []; + } + + public function denormalizeFormData(array $formData, int $fromVersion): array + { + return []; + } + + public function getFormDefaultData(): array + { + return []; + } + + public function getLabels($key, array $values, $data): callable + { + return function ($value): string { + if ('_header' === $value) { + return 'export.aggregator.Concerned persons count'; + } + + if (null === $value) { + return 'export.aggregator.No concerned persons count specified'; + } + + return (string) $value; + }; + } + + public function getQueryKeys($data): array + { + return ['by_concerned_persons_count_aggregator']; + } + + public function getTitle(): string + { + return 'export.aggregator.Group by concerned persons count'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumConcernedPersonsCountAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumConcernedPersonsCountAsideActivity.php new file mode 100644 index 000000000..ab22302c2 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumConcernedPersonsCountAsideActivity.php @@ -0,0 +1,116 @@ +getTitle(); + + return static fn ($value) => $labels[$value]; + } + + public function getQueryKeys($data): array + { + return ['export_sum_concerned_persons_count']; + } + + public function getResult($query, $data, \Chill\MainBundle\Export\ExportGenerationContext $context): array + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string + { + return 'export.Sum concerned persons count for aside activities'; + } + + public function getType(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data, \Chill\MainBundle\Export\ExportGenerationContext $context): \Doctrine\ORM\QueryBuilder + { + $qb = $this->repository->createQueryBuilder('aside'); + + $qb->select('SUM(COALESCE(aside.concernedPersonsCount, 0)) as export_sum_concerned_persons_count'); + + return $qb; + } + + public function requiredRole(): string + { + return AsideActivityVoter::STATS; + } + + public function supportsModifiers(): array + { + return [ + Declarations::ASIDE_ACTIVITY_TYPE, + ]; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php index d6fcb821c..ea04fdc42 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Form/AsideActivityFormType.php @@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; @@ -29,11 +30,13 @@ use Symfony\Component\OptionsResolver\OptionsResolver; final class AsideActivityFormType extends AbstractType { private readonly array $timeChoices; + private readonly bool $showConcernedPersonsCount; public function __construct( ParameterBagInterface $parameterBag, ) { $this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration'); + $this->showConcernedPersonsCount = $parameterBag->get('chill_aside_activity.show_concerned_persons_count'); } public function buildForm(FormBuilderInterface $builder, array $options) @@ -76,6 +79,16 @@ final class AsideActivityFormType extends AbstractType ->add('location', PickUserLocationType::class) ; + if ($this->showConcernedPersonsCount) { + $builder->add('concernedPersonsCount', IntegerType::class, [ + 'label' => 'Concerned persons count', + 'required' => false, + 'attr' => [ + 'min' => 0, + ], + ]); + } + foreach (['duration'] as $fieldName) { $builder->get($fieldName) ->addModelTransformer($durationTimeTransformer); diff --git a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig index 0a8648749..0d06e5ba9 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig +++ b/src/Bundle/ChillAsideActivityBundle/src/Resources/views/asideActivity/index.html.twig @@ -42,6 +42,11 @@ {%- if entity.location.name is defined -%}