diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php index 6c91c9336..32418e3c3 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByActivityTypeAggregator.php @@ -53,19 +53,15 @@ class ByActivityTypeAggregator implements AggregatorInterface public function getLabels($key, array $values, $data) { - $this->asideActivityCategoryRepository->findBy(['id' => $values]); - return function ($value): string { if ('_header' === $value) { return 'export.aggregator.Aside activity type'; } - if (null === $value) { + if (null === $value || null === $t = $this->asideActivityCategoryRepository->find($value)) { return ''; } - $t = $this->asideActivityCategoryRepository->find($value); - return $this->translatableStringHelper->localize($t->getTitle()); }; } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php new file mode 100644 index 000000000..d2fe7c2f2 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -0,0 +1,89 @@ +userJobRepository = $userJobRepository; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + if (!in_array('aside_user', $qb->getAllAliases(), true)) { + $qb->leftJoin('aside.agent', 'aside_user'); + } + + $qb + ->addSelect('IDENTITY(aside_user.userJob) AS aside_activity_user_job_aggregator') + ->addGroupBy('aside_activity_user_job_aggregator'); + } + + public function applyOn() + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + // nothing to add in the form + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ('_header' === $value) { + return 'Users \'s job'; + } + + if (null === $value || '' === $value) { + return ''; + } + + $j = $this->userJobRepository->find($value); + + return $this->translatableStringHelper->localize( + $j->getLabel() + ); + }; + } + + public function getQueryKeys($data): array + { + return ['aside_activity_user_job_aggregator']; + } + + public function getTitle() + { + return 'export.aggregator.Aggregate by user job'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php new file mode 100644 index 000000000..6c06ee756 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -0,0 +1,89 @@ +scopeRepository = $scopeRepository; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + if (!in_array('aside_user', $qb->getAllAliases(), true)) { + $qb->leftJoin('aside.agent', 'aside_user'); + } + + $qb + ->addSelect('IDENTITY(aside_user.mainScope) AS aside_activity_user_scope_aggregator') + ->addGroupBy('aside_activity_user_scope_aggregator'); + } + + public function applyOn() + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + // nothing to add in the form + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ('_header' === $value) { + return 'Users \'s scope'; + } + + if (null === $value || '' === $value) { + return ''; + } + + $s = $this->scopeRepository->find($value); + + return $this->translatableStringHelper->localize( + $s->getName() + ); + }; + } + + public function getQueryKeys($data): array + { + return ['aside_activity_user_scope_aggregator']; + } + + public function getTitle() + { + return 'export.aggregator.Aggregate by user scope'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php new file mode 100644 index 000000000..f3db629cb --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/AvgAsideActivityDuration.php @@ -0,0 +1,102 @@ +repository = $repository; + } + + public function buildForm(FormBuilderInterface $builder) + { + } + + public function getAllowedFormattersTypes(): array + { + return [FormatterInterface::TYPE_TABULAR]; + } + + public function getDescription(): string + { + return 'export.Average aside activities duration'; + } + + public function getGroup(): string + { + return 'export.Exports of aside activities'; + } + + public function getLabels($key, array $values, $data) + { + if ('export_avg_aside_activity_duration' !== $key) { + throw new LogicException("the key {$key} is not used by this export"); + } + + return static fn ($value) => '_header' === $value ? 'Average duration aside activities' : $value; + } + + public function getQueryKeys($data): array + { + return ['export_avg_aside_activity_duration']; + } + + public function getResult($query, $data) + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string + { + return 'export.Average aside activities duration'; + } + + public function getType(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) + { + $qb = $this->repository->createQueryBuilder('aside'); + + $qb + ->select('AVG(aside.duration) as export_avg_aside_activity_duration') + ->andWhere($qb->expr()->isNotNull('aside.duration')); + + 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/Export/Export/CountAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php index c3e99f129..87aad1659 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/CountAsideActivity.php @@ -11,12 +11,12 @@ declare(strict_types=1); namespace Chill\AsideActivityBundle\Export\Export; +use Chill\AsideActivityBundle\Export\Declarations; use Chill\AsideActivityBundle\Repository\AsideActivityRepository; use Chill\AsideActivityBundle\Security\AsideActivityVoter; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\FormatterInterface; use Chill\MainBundle\Export\GroupedExportInterface; -use ChillAsideActivityBundle\Export\Declarations; use Doctrine\ORM\Query; use LogicException; use Symfony\Component\Form\FormBuilderInterface; @@ -100,6 +100,8 @@ class CountAsideActivity implements ExportInterface, GroupedExportInterface public function supportsModifiers(): array { - return []; + return [ + Declarations::ASIDE_ACTIVITY_TYPE, + ]; } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php new file mode 100644 index 000000000..bf370f71b --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php @@ -0,0 +1,236 @@ +em = $em; + $this->dateTimeHelper = $dateTimeHelper; + $this->userHelper = $userHelper; + $this->scopeRepository = $scopeRepository; + $this->centerRepository = $centerRepository; + $this->asideActivityCategoryRepository = $asideActivityCategoryRepository; + $this->categoryRender = $categoryRender; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function buildForm(FormBuilderInterface $builder) + { + } + + public function getAllowedFormattersTypes() + { + return [FormatterInterface::TYPE_LIST]; + } + + public function getDescription() + { + return 'export.aside_activity.List of aside activities'; + } + + public function getTitle() + { + return 'export.aside_activity.List of aside activities'; + } + + public function getGroup(): string + { + return 'export.Exports of aside activities'; + } + + public function getLabels($key, array $values, $data) + { + switch ($key) { + case 'id': + case 'note': + return function ($value) use ($key) { + if ('_header' === $value) { + return 'export.aside_activity.' . $key; + } + + return $value ?? ''; + }; + case 'duration': + return function ($value) use ($key) { + if ('_header' === $value) { + return 'export.aside_activity.' . $key; + } + + if (null === $value) { + return ''; + } + + if ($value instanceof \DateTimeInterface) { + return $value->format('H:i:s'); + } + + return $value; + }; + + case 'createdAt': + case 'updatedAt': + case 'date': + return $this->dateTimeHelper->getLabel('export.aside_activity.'.$key); + + case 'agent_id': + case 'creator_id': + return $this->userHelper->getLabel($key, $values, 'export.aside_activity.' . $key); + + case 'aside_activity_type': + return function ($value) { + if ('_header' === $value) { + return 'export.aside_activity.aside_activity_type'; + } + + if (null === $value || '' === $value || null === $c = $this->asideActivityCategoryRepository->find($value)) { + return ''; + } + + return $this->categoryRender->renderString($c, []); + }; + + case 'main_scope': + return function ($value) { + if ('_header' === $value) { + return 'export.aside_activity.main_scope'; + } + + if (null === $value || '' === $value || null === $c = $this->scopeRepository->find($value)) { + return ''; + } + + return $this->translatableStringHelper->localize($c->getName()); + }; + + case 'main_center': + return function ($value) { + if ('_header' === $value) { + return 'export.aside_activity.main_center'; + } + + /** @var Center $c */ + if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) { + return ''; + } + + return $c->getName(); + }; + + default: + throw new \LogicException('this key is not supported : ' . $key); + } + } + + public function getQueryKeys($data) + { + return [ + 'id', + 'createdAt', + 'updatedAt', + 'agent_id', + 'creator_id', + 'main_scope', + 'main_center', + 'aside_activity_type', + 'date', + 'duration', + 'note' + ]; + } + + /** + * @param QueryBuilder $query + * @param array $data + */ + public function getResult($query, $data): array + { + return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY); + } + + public function getType(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) + { + $qb = $this->em->createQueryBuilder() + ->from(AsideActivity::class, 'aside') + ->leftJoin('aside.agent', 'agent') + ; + + $qb + ->addSelect('aside.id AS id') + ->addSelect('aside.createdAt AS createdAt') + ->addSelect('aside.updatedAt AS updatedAt') + ->addSelect('IDENTITY(aside.agent) AS agent_id') + ->addSelect('IDENTITY(aside.createdBy) AS creator_id') + ->addSelect('IDENTITY(agent.mainScope) AS main_scope') + ->addSelect('IDENTITY(agent.mainCenter) AS main_center') + ->addSelect('IDENTITY(aside.type) AS aside_activity_type') + ->addSelect('aside.date') + ->addSelect('aside.duration') + ->addSelect('aside.note') + ; + + return $qb; + } + + public function requiredRole(): string + { + return AsideActivityVoter::STATS; + } + + public function supportsModifiers() + { + return [Declarations::ASIDE_ACTIVITY_TYPE]; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php new file mode 100644 index 000000000..af17a2591 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/SumAsideActivityDuration.php @@ -0,0 +1,102 @@ +repository = $repository; + } + + public function buildForm(FormBuilderInterface $builder) + { + } + + public function getAllowedFormattersTypes(): array + { + return [FormatterInterface::TYPE_TABULAR]; + } + + public function getDescription(): string + { + return 'export.Sum aside activities duration'; + } + + public function getGroup(): string + { + return 'export.Exports of aside activities'; + } + + public function getLabels($key, array $values, $data) + { + if ('export_sum_aside_activity_duration' !== $key) { + throw new LogicException("the key {$key} is not used by this export"); + } + + return static fn ($value) => '_header' === $value ? 'Sum duration aside activities' : $value; + } + + public function getQueryKeys($data): array + { + return ['export_sum_aside_activity_duration']; + } + + public function getResult($query, $data) + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string + { + return 'export.Sum aside activities duration'; + } + + public function getType(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) + { + $qb = $this->repository + ->createQueryBuilder('aside'); + + $qb->select('SUM(aside.duration) as export_sum_aside_activity_duration') + ->andWhere($qb->expr()->isNotNull('aside.duration')); + + 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/Export/Filter/ByActivityTypeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php index 85b327795..3ad8e0e93 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByActivityTypeFilter.php @@ -80,8 +80,8 @@ class ByActivityTypeFilter implements FilterInterface public function describeAction($data, $format = 'string'): array { $types = array_map( - fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getName()), - $this->asideActivityTypeRepository->findBy(['id' => $data['types']->toArray()]) + fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getTitle()), + $data['types']->toArray() ); return ['export.filter.Filtered by aside activity type: only %type%', [ diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php index 099c87fc0..2d49b3d57 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByDateFilter.php @@ -46,25 +46,18 @@ class ByDateFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - $where = $qb->getDQLPart('where'); $clause = $qb->expr()->between( 'aside.date', ':date_from', ':date_to' ); - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } + $qb->andWhere($clause); - $qb->add('where', $where); $qb->setParameter( 'date_from', $this->rollingDateConverter->convert($data['date_from']) - ); - $qb->setParameter( + )->setParameter( 'date_to', $this->rollingDateConverter->convert($data['date_to']) ); diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php new file mode 100644 index 000000000..c2a3b4c54 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserFilter.php @@ -0,0 +1,75 @@ +userRender = $userRender; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $clause = $qb->expr()->in('aside.agent', ':users'); + + $qb + ->andWhere($clause) + ->setParameter('users', $data['accepted_users']); + } + + public function applyOn(): string + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_users', PickUserDynamicType::class, [ + 'multiple' => true, + 'label' => 'Creators', + ]); + } + + public function describeAction($data, $format = 'string'): array + { + $users = []; + + foreach ($data['accepted_users'] as $u) { + $users[] = $this->userRender->renderString($u, []); + } + + return ['export.filter.Filtered aside activity by user: only %users%', [ + '%users%' => implode(', ', $users), + ]]; + } + + public function getTitle(): string + { + return 'export.filter.Filter aside activity by user'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php new file mode 100644 index 000000000..86194b123 --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php @@ -0,0 +1,81 @@ +translatableStringHelper = $translatableStringHelper; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_job_filter_act + JOIN aside_activity_user_job_filter_act.agent aside_activity_user_job_filter_user WHERE aside_activity_user_job_filter_user.userJob IN (:aside_activity_user_job_filter_jobs) AND aside_activity_user_job_filter_act = aside' + ) + ) + ->setParameter('aside_activity_user_job_filter_jobs', $data['jobs']); + } + + public function applyOn() + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('jobs', EntityType::class, [ + 'class' => UserJob::class, + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function describeAction($data, $format = 'string') + { + return ['export.filter.Filtered aside activities by user jobs: only %jobs%', [ + '%jobs%' => implode( + ', ', + array_map( + fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), + $data['jobs']->toArray() + ) + ), + ]]; + } + + public function getTitle() + { + return 'export.filter.Filter by user jobs'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php new file mode 100644 index 000000000..4342e11eb --- /dev/null +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php @@ -0,0 +1,88 @@ +scopeRepository = $scopeRepository; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_scope_filter_act + JOIN aside_activity_user_scope_filter_act.agent aside_activity_user_scope_filter_user WHERE aside_activity_user_scope_filter_user.mainScope IN (:aside_activity_user_scope_filter_scopes) AND aside_activity_user_scope_filter_act = aside ' + ) + ) + ->setParameter('aside_activity_user_scope_filter_scopes', $data['scopes']); + } + + public function applyOn() + { + return Declarations::ASIDE_ACTIVITY_TYPE; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choices' => $this->scopeRepository->findAllActive(), + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function describeAction($data, $format = 'string') + { + return ['export.filter.Filtered aside activities by user scope: only %scopes%', [ + '%scopes%' => implode( + ', ', + array_map( + fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + $data['scopes']->toArray() + ) + ), + ]]; + } + + public function getTitle() + { + return 'export.filter.Filter by user scope'; + } +} diff --git a/src/Bundle/ChillAsideActivityBundle/src/config/services.yaml b/src/Bundle/ChillAsideActivityBundle/src/config/services.yaml index 2a7c30d7c..34bb6da33 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/config/services.yaml +++ b/src/Bundle/ChillAsideActivityBundle/src/config/services.yaml @@ -20,33 +20,3 @@ services: resource: "../Controller" autowire: true autoconfigure: true - - - ## Exports - - # indicators - Chill\AsideActivityBundle\Export\Export\CountAsideActivity: - autowire: true - autoconfigure: true - tags: - - { name: chill.export, alias: count_asideactivity } - - # filters - Chill\AsideActivityBundle\Export\Filter\ByDateFilter: - autowire: true - autoconfigure: true - tags: - - { name: chill.export_filter, alias: asideactivity_bydate_filter } - - Chill\AsideActivityBundle\Export\Filter\ByActivityTypeFilter: - autowire: true - autoconfigure: true - tags: - - { name: chill.export_filter, alias: asideactivity_activitytype_filter } - - # aggregators - Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator: - autowire: true - autoconfigure: true - tags: - - { name: chill.export_aggregator, alias: asideactivity_activitytype_aggregator } diff --git a/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml b/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml index 1b6b05e1c..a29413e15 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml +++ b/src/Bundle/ChillAsideActivityBundle/src/config/services/export.yaml @@ -3,11 +3,23 @@ services: autowire: true autoconfigure: true + Chill\AsideActivityBundle\Export\Export\ListAsideActivity: + tags: + - { name: chill.export, alias: 'list_aside_activity' } + ## Indicators Chill\AsideActivityBundle\Export\Export\CountAsideActivity: tags: - { name: chill.export, alias: 'count_aside_activity' } + Chill\AsideActivityBundle\Export\Export\SumAsideActivityDuration: + tags: + - { name: chill.export, alias: 'sum_aside_activity_duration' } + + Chill\AsideActivityBundle\Export\Export\AvgAsideActivityDuration: + tags: + - { name: chill.export, alias: 'avg_aside_activity_duration' } + ## Filters chill.aside_activity.export.date_filter: class: Chill\AsideActivityBundle\Export\Filter\ByDateFilter @@ -19,9 +31,34 @@ services: tags: - { name: chill.export_filter, alias: 'aside_activity_type_filter' } + chill.aside_activity.export.user_job_filter: + class: Chill\AsideActivityBundle\Export\Filter\ByUserJobFilter + tags: + - { name: chill.export_filter, alias: 'aside_activity_user_job_filter' } + + chill.aside_activity.export.user_scope_filter: + class: Chill\AsideActivityBundle\Export\Filter\ByUserScopeFilter + tags: + - { name: chill.export_filter, alias: 'aside_activity_user_scope_filter' } + + chill.aside_activity.export.user_filter: + class: Chill\AsideActivityBundle\Export\Filter\ByUserFilter + tags: + - { name: chill.export_filter, alias: 'aside_activity_user_filter' } + ## Aggregators chill.aside_activity.export.type_aggregator: class: Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator tags: - - { name: chill.export_aggregator, alias: activity_type_aggregator } \ No newline at end of file + - { name: chill.export_aggregator, alias: activity_type_aggregator } + + chill.aside_activity.export.user_job_aggregator: + class: Chill\AsideActivityBundle\Export\Aggregator\ByUserJobAggregator + tags: + - { name: chill.export_aggregator, alias: aside_activity_user_job_aggregator } + + chill.aside_activity.export.user_scope_aggregator: + class: Chill\AsideActivityBundle\Export\Aggregator\ByUserScopeAggregator + tags: + - { name: chill.export_aggregator, alias: aside_activity_user_scope_aggregator } diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml index 2b4b6788a..0c807479f 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml +++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml @@ -29,16 +29,16 @@ location: Lieu # Crud crud: - aside_activity: - title_view: Détail de l'activité annexe - title_new: Nouvelle activité annexe - title_edit: Édition d'une activité annexe - title_delete: Supprimer une activité annexe - button_delete: Supprimer - confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe? - aside_activity_category: - title_new: Nouvelle catégorie d'activité annexe - title_edit: Édition d'une catégorie de type d'activité + aside_activity: + title_view: Détail de l'activité annexe + title_new: Nouvelle activité annexe + title_edit: Édition d'une activité annexe + title_delete: Supprimer une activité annexe + button_delete: Supprimer + confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe? + aside_activity_category: + title_new: Nouvelle catégorie d'activité annexe + title_edit: Édition d'une catégorie de type d'activité #forms Create a new aside activity type: Nouvelle categorie d'activité annexe @@ -169,19 +169,43 @@ Aside activity configuration: Configuration des activités annexes # exports export: - Exports of aside activities: Exports des activités annexes - Count aside activities: Nombre d'activités annexes - Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères - filter: - Filter by aside activity date: Filtrer les activités annexes par date - Filter by aside activity type: Filtrer les activités annexes par type d'activité - 'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%" - This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date" - Aside activities after this date: Actvitités annexes après cette date - Aside activities before this date: Actvitités annexes avant cette date - aggregator: - Group by aside activity type: Grouper les activités annexes par type d'activité - Aside activity type: Type d'activité annexe + aside_activity: + List of aside activities: Liste des activités annexes + createdAt: Création + updatedAt: Dernière mise à jour + agent_id: Utilisateur + creator_id: Créateur + main_scope: Service principal de l'utilisateur + main_center: Centre principal de l'utilisteur + aside_activity_type: Catégorie d'activité annexe + date: Date + duration: Durée + note: Note + + Exports of aside activities: Exports des activités annexes + Count aside activities: Nombre d'activités annexes + Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères + Average aside activities duration: Durée moyenne des activités annexes + Sum aside activities duration: Durée des activités annexes + filter: + Filter by aside activity date: Filtrer les activités annexes par date + Filter by aside activity type: Filtrer les activités annexes par type d'activité + 'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%" + Filtered by aside activities between %dateFrom% and %dateTo%: Filtré par date d'activité annexe, entre %dateFrom% et %dateTo% + This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date" + Aside activities after this date: Actvitités annexes après cette date + Aside activities before this date: Actvitités annexes avant cette date + 'Filtered aside activity by user: only %users%': "Filtré par utilisateur: uniquement %users%" + Filter aside activity by user: Filtrer par utilisateur + 'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%" + Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs + 'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%" + Filter by user scope: Filtrer les activités annexes par service d'utilisateur + aggregator: + Group by aside activity type: Grouper les activités annexes par type d'activité + Aside activity type: Type d'activité annexe + Aggregate by user job: Grouper les activités annexes par métier des utilisateurs + Aggregate by user scope: Grouper les activités annexes par service des utilisateurs # ROLES CHILL_ASIDE_ACTIVITY_STATS: Statistiques pour les activités annexes diff --git a/src/Bundle/ChillMainBundle/Export/ExportInterface.php b/src/Bundle/ChillMainBundle/Export/ExportInterface.php index be43ad47a..79b59d241 100644 --- a/src/Bundle/ChillMainBundle/Export/ExportInterface.php +++ b/src/Bundle/ChillMainBundle/Export/ExportInterface.php @@ -83,9 +83,9 @@ interface ExportInterface extends ExportElementInterface * * @param string $key The column key, as added in the query * @param mixed[] $values The values from the result. if there are duplicates, those might be given twice. Example: array('FR', 'BE', 'CZ', 'FR', 'BE', 'FR') - * @param mixed $data The data from the export's form (as defined in `buildForm` + * @param mixed $data The data from the export's form (as defined in `buildForm`) * - * @return Closure where the first argument is the value, and the function should return the label to show in the formatted file. Example : `function($countryCode) use ($countries) { return $countries[$countryCode]->getName(); }` + * @return pure-callable(null|string|int|float|'_header' $value):string|int|\DateTimeInterface where the first argument is the value, and the function should return the label to show in the formatted file. Example : `function($countryCode) use ($countries) { return $countries[$countryCode]->getName(); }` */ public function getLabels($key, array $values, $data); diff --git a/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php index 86a2458b2..648632e15 100644 --- a/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php +++ b/src/Bundle/ChillMainBundle/Export/Helper/DateTimeHelper.php @@ -35,6 +35,10 @@ class DateTimeHelper return ''; } + if ($value instanceof \DateTimeInterface) { + return $value; + } + // warning: won't work with DateTimeImmutable as we reset time a few lines later $date = DateTime::createFromFormat('Y-m-d', $value); $hasTime = false;