From 4a1615afd520cdc363ab4558dbe704c6c143e85b Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 10:02:07 +0200 Subject: [PATCH 1/9] export, fix merge translations --- .../translations/messages.fr.yml | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 34cc1c8af..e70c11139 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -349,7 +349,7 @@ Create an average of accompanying courses duration according to various filters: Closingdate to apply: Date de fin à prendre en compte lorsque le parcours n'est pas clotûré Exports of social work actions: Exports des actions d'accompagnement -Count social work actions: Nombre d'actions d'accompagnement +Count social work actions: Nombre d'actions Count social work actions by various parameters: Compte le nombre d'actions d'accompagnement en fonction de différents filtres. @@ -361,7 +361,7 @@ Exports of households: Exports des ménages Count households: Nombre de ménages Count household by various parameters.: Compte le nombre de ménages impliqués dans un parcours selon différents filtres. -## filters +## persons filters Filter by person gender: Filtrer par genre de la personne Accepted genders: Genres acceptés 'Filtering by genders: only %genders%': 'Filtré par genre: seulement %genders%' @@ -424,6 +424,7 @@ Having an accompanying period closed after this date: Ayant une période d'accom "Having an accompanying period closed before this date": "Ayant une période d'accompagnement fermée avant cette date" "Filtered by accompanying period: persons having an accompanying period closed between the %date_from% and %date_to%": "Filtrer par période d'accompagnement: ayant une période fermée entre le %date_from% et le %date_to%" +## accompanying course filters/aggr Filter by user scope: Filtrer les parcours par service du référent "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" Group by user scope: Grouper les parcours par service du référent @@ -433,7 +434,6 @@ Filter by user job: Filtrer les parcours par métier du référent Group by user job: Grouper les parcours par métier du référent Filter by social issue: Filtrer les parcours par problématiques sociales -Filter by scope: Filtrer par service Accepted socialissues: Problématiques sociales "Filtered by socialissues: only %socialissues%": "Filtré par problématique sociale: uniquement %socialissues%" Group by social issue: Grouper les parcours par problématiques sociales @@ -458,10 +458,6 @@ Evaluation: Évaluation "Filtered by evaluations: only %evals%": "Filtré par évaluation: uniquement %evals%" Group by evaluation: Grouper les parcours par évaluation -Group social work actions by action type: Grouper par type d'action -Group social work actions by goal: Grouper par objectif -Group social work actions by result: Grouper par résultat - Filter accompanying course by activity type: Filtrer les parcours par type d'activité Accepted activitytypes: Types d'activités "Filtered by activity types: only %activitytypes%": "Filtré par type d'activité: seulement %activitytypes%" @@ -531,10 +527,13 @@ Date from: Date de début Date to: Date de fin "Filtered by opening dates: between %datefrom% and %dateto%": "Filtrer les parcours ouverts entre deux dates: entre le %datefrom% et le %dateto%" +## social actions filters/aggr Filter by treating agent scope: Filtrer les actions par service de l'agent traitant "Filtered by treating agent scope: only %scopes%": "Filtré par service de l'agent traitant: uniquement %scopes%" Group by treating agent scope: Grouper les actions par service de l'agent traitant +Filter by scope: Filtrer par service + Filter by treating agent job: Filtrer les actions par métier de l'agent traitant "Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" Group by treating agent job: Grouper les actions par métier de l'agent traitant @@ -544,6 +543,11 @@ Accepted agents: Agent traitant "Filtered by treating agent: only %agents%": "Filtré par agent traitant: uniquement %agents%" Group by treating agent: Grouper les actions par agent traitant +Group social work actions by action type: Grouper les actions par type +Group social work actions by goal: Grouper les actions par objectif +Group social work actions by result: Grouper les actions par résultat + +## evaluations filters/aggr Filter by evaluation type: Filtrer les évaluations par type Accepted evaluationtype: Évaluations "Filtered by evaluation type: only %evals%": "Filtré par type d'évaluation: uniquement %evals%" @@ -556,6 +560,7 @@ is specified: La date d'échéance est spécifiée is not specified: La date d'échéance n'est pas spécifiée "Filtered by maxdate: only %choice%": "Filtré par date d'échéance: uniquement si %choice%" +## household filters/aggr Filter by composition: Filtrer les ménages par composition familiale Accepted composition: Composition familiale "Filtered by composition: only %compositions% on %ondate%": "Filtré par composition familiale: uniquement %compositions%, en date du %ondate%" @@ -563,7 +568,7 @@ Group by composition: Grouper les ménages par composition familiale Group by number of children: Grouper les ménages par nombre d'enfants -## aggregators +## persons aggregators Group people by nationality: Grouper les personnes par nationalités Group by level: Grouper par niveau Group by continents: Grouper par continent From 9af620ece5be98bddc67ac75ac10d25d2d68b968 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 10:17:44 +0200 Subject: [PATCH 2/9] fix translations --- .../ChillCalendarBundle/translations/messages.fr.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index b0add946d..7068168b5 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -41,13 +41,14 @@ crud: # exports Exports of calendar: Exports des rendez-vous -Count appointments: Nombre des rendez-vous +Count appointments: Nombre de rendez-vous +Count appointments by various parameters.: Compte le nombre de rendez-vous en fonction de différents paramètres. -Average appointment duration: Moyenne des durées des rendez-vous -Get the average of appointment duration according to various filters: Calculer la moyenne des durées des rendez-vous +Average appointment duration: Moyenne de la durée des rendez-vous +Get the average of appointment duration according to various filters: Calcule la moyenne des durées des rendez-vous en fonction de différents paramètres. -Sum of appointment durations: Somme des durées des rendez-vous -Get the sum of appointment durations according to various filters: Calculer la somme des durées des rendez-vous +Sum of appointment durations: Somme de la durée des rendez-vous +Get the sum of appointment durations according to various filters: Calcule la somme des durées des rendez-vous en fonction de différents paramètres. 'Filtered by agent: only %agents%': "Filtré par agents: uniquement %agents%" Filter by agent: Filtrer par agents From 248d56e59833c72b9a1e178dc8b67d1cd96ab148 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 11:49:27 +0200 Subject: [PATCH 3/9] exports: add activity linked_to_acp new filters --- .../ACPFilters/BySocialActionFilter.php | 81 +++++++++++++++++ .../Filter/ACPFilters/BySocialIssueFilter.php | 81 +++++++++++++++++ .../Export/Filter/ACPFilters/ByUserFilter.php | 80 +++++++++++++++++ .../Filter/ACPFilters/EmergencyFilter.php | 86 ++++++++++++++++++ .../Filter/ACPFilters/LocationTypeFilter.php | 85 ++++++++++++++++++ .../Filter/ACPFilters/SentReceivedFilter.php | 82 +++++++++++++++++ .../Export/Filter/ACPFilters/UserFilter.php | 82 +++++++++++++++++ .../Filter/ACPFilters/UserScopeFilter.php | 89 +++++++++++++++++++ .../config/services/export.yaml | 40 +++++++++ .../translations/messages.fr.yml | 26 ++++++ 10 files changed, 732 insertions(+) create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php new file mode 100644 index 000000000..ea125adb2 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php @@ -0,0 +1,81 @@ +actionRender = $actionRender; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_socialactions', EntityType::class, [ + 'class' => SocialAction::class, + 'choice_label' => function (SocialAction $sa) { + return $this->actionRender->renderString($sa, []); + }, + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by linked socialaction'; + } + + public function describeAction($data, $format = 'string'): array + { + $actions = []; + + foreach ($data['accepted_socialactions'] as $sa) { + $actions[] = $this->actionRender->renderString($sa, []); + } + + return ['Filtered activity by linked socialaction: only %actions%', [ + '%actions%' => implode(", ou", $actions) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->in('activity.socialActions', ':socialactions'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('socialactions', $data['accepted_socialactions']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php new file mode 100644 index 000000000..247b0ea32 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php @@ -0,0 +1,81 @@ +issueRender = $issueRender; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_socialissues', EntityType::class, [ + 'class' => SocialIssue::class, + 'choice_label' => function(SocialIssue $si) { + return $this->issueRender->renderString($si, []); + }, + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by linked socialissue'; + } + + public function describeAction($data, $format = 'string'): array + { + $issues = []; + + foreach ($data['accepted_socialissues'] as $si) { + $issues[] = $this->issueRender->renderString($si, []); + } + + return ['Filtered activity by linked socialissue: only %issues%', [ + '%issues%' => implode(", ou", $issues) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->in('activity.socialIssues', ':socialissues'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('socialissues', $data['accepted_socialissues']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php new file mode 100644 index 000000000..9fef06f72 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php @@ -0,0 +1,80 @@ +userRender = $userRender; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_users', EntityType::class, [ + 'class' => User::class, + 'choice_label' => function (User $u) { + return $this->userRender->renderString($u, []); + }, + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by linked users'; + } + + public function describeAction($data, $format = 'string'): array + { + $users = []; + + foreach ($data['accepted_users'] as $u) { + $users[] = $this->userRender->renderString($u, []); + } + + return ['Filtered activity by linked users: only %users%', [ + '%users%' => implode(", ou", $users) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->in('activity.users', ':users'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('users', $data['accepted_users']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php new file mode 100644 index 000000000..d7a823891 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php @@ -0,0 +1,86 @@ + true, + 'activity is not emergency' => false, + ]; + + private CONST DEFAULT_CHOICE = false; + + private TranslatorInterface $translator; + + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_emergency', ChoiceType::class, [ + 'choices' => self::CHOICES, + 'multiple' => false, + 'expanded' => true, + 'empty_data' => self::DEFAULT_CHOICE, + 'data' => self::DEFAULT_CHOICE, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by emergency'; + } + + public function describeAction($data, $format = 'string'): array + { + foreach (self::CHOICES as $k => $v) { + if ($v === $data['accepted_emergency']) { + $choice = $k; + } + } + + return ['Filtered activity by emergency: only %emergency%', [ + '%emergency%' => $this->translator->trans($choice) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->eq('activity.emergency', ':emergency'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('emergency', $data['accepted_emergency']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php new file mode 100644 index 000000000..22e1f3c30 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php @@ -0,0 +1,85 @@ +translatableStringHelper = $translatableStringHelper; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_locationtype', EntityType::class, [ + 'class' => LocationType::class, + 'choice_label' => function(LocationType $type) { + return $this->translatableStringHelper->localize($type->getTitle()); + }, + 'multiple' => true, + 'expanded' => true, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by locationtype'; + } + + public function describeAction($data, $format = 'string'): array + { + $types = []; + + foreach ($data['accepted_locationtype'] as $type) { + $types[] = $this->translatableStringHelper->localize( + $type->getTitle() + ); + } + + return ['Filtered activity by locationtype: only %types%', [ + '%types%' => implode(", ou", $types) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + if (!in_array('location', $qb->getAllAliases())) { + $qb->join('activity.location', 'location'); + } + + $where = $qb->getDQLPart('where'); + $clause = $qb->expr()->in('location.locationType', ':locationtype'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('locationtype', $data['accepted_locationtype']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php new file mode 100644 index 000000000..409c974ac --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php @@ -0,0 +1,82 @@ + Activity::SENTRECEIVED_SENT, + 'is received' => Activity::SENTRECEIVED_RECEIVED, + ]; + + private CONST DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT; + + private TranslatorInterface $translator; + + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_sentreceived', ChoiceType::class, [ + 'choices' => self::CHOICES, + 'multiple' => false, + 'expanded' => true, + 'empty_data' => self::DEFAULT_CHOICE, + 'data' => self::DEFAULT_CHOICE, + ]); + } + + public function getTitle(): string + { + return 'Filter activity by sentreceived'; + } + + public function describeAction($data, $format = 'string'): array + { + $sentreceived = array_flip(self::CHOICES)[$data['accepted_sentreceived']]; + + return ['Filtered activity by sentreceived: only %sentreceived%', [ + '%sentreceived%' => $this->translator->trans($sentreceived) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->eq('activity.sentReceived', ':sentreceived'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('sentreceived', $data['accepted_sentreceived']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php new file mode 100644 index 000000000..02aff8cad --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php @@ -0,0 +1,82 @@ +userRender = $userRender; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_users', EntityType::class, [ + 'class' => User::class, + 'choice_label' => function (User $u) { + return $this->userRender->renderString($u, []); + }, + 'multiple' => true, + 'expanded' => true, + 'label' => 'Creators' + ]); + } + + public function getTitle(): string + { + return 'Filter activity by user'; + } + + public function describeAction($data, $format = 'string'): array + { + $users = []; + + foreach ($data['accepted_users'] as $u) { + $users[] = $this->userRender->renderString($u, []); + } + + return ['Filtered activity by user: only %users%', [ + '%users%' => implode(", ou", $users) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->in('activity.user', ':users'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('users', $data['accepted_users']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php new file mode 100644 index 000000000..abc26d418 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php @@ -0,0 +1,89 @@ +translatableStringHelper = $translatableStringHelper; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('accepted_userscope', EntityType::class, [ + 'class' => Scope::class, + 'choice_label' => function (Scope $s) { + return $this->translatableStringHelper->localize( + $s->getName() + ); + }, + 'multiple' => true, + 'expanded' => true + ]); + } + + public function getTitle(): string + { + return 'Filter activity by userscope'; + } + + public function describeAction($data, $format = 'string'): array + { + $scopes = []; + + foreach ($data['accepted_userscope'] as $s) { + $scopes[] = $this->translatableStringHelper->localize( + $s->getName() + ); + } + + return ['Filtered activity by userscope: only %scopes%', [ + '%scopes%' => implode(", ou", $scopes) + ]]; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + if (!in_array('user', $qb->getAllAliases())) { + $qb->join('activity.user', 'user'); + } + + $where = $qb->getDQLPart('where'); + + $clause = $qb->expr()->in('user.mainScope', ':userscope'); + + if ($where instanceof Andx) { + $where->add($clause); + } else { + $where = $qb->expr()->andX($clause); + } + + $qb->add('where', $where); + $qb->setParameter('userscope', $data['accepted_userscope']); + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml index c6b0e9718..393e452e6 100644 --- a/src/Bundle/ChillActivityBundle/config/services/export.yaml +++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml @@ -67,6 +67,46 @@ services: name: chill.export_filter alias: 'activity_person_having_ac_bw_date_filter' + chill.activity.export.locationtype_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter + tags: + - { name: chill.export_filter, alias: 'activity_locationtype_filter' } + + chill.activity.export.byuser_filter: # TMS (M2M) + class: Chill\ActivityBundle\Export\Filter\ACPFilters\ByUserFilter + tags: + - { name: chill.export_filter, alias: 'activity_byuser_filter' } + + chill.activity.export.emergency_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\EmergencyFilter + tags: + - { name: chill.export_filter, alias: 'activity_emergency_filter' } + + chill.activity.export.sentreceived_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\SentReceivedFilter + tags: + - { name: chill.export_filter, alias: 'activity_sentreceived_filter' } + + chill.activity.export.bysocialaction_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter + tags: + - { name: chill.export_filter, alias: 'activity_bysocialaction_filter' } + + chill.activity.export.bysocialissue_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter + tags: + - { name: chill.export_filter, alias: 'activity_bysocialissue_filter' } + + chill.activity.export.user_filter: # Creator (M2O) + class: Chill\ActivityBundle\Export\Filter\ACPFilters\UserFilter + tags: + - { name: chill.export_filter, alias: 'activity_user_filter' } + + chill.activity.export.userscope_filter: + class: Chill\ActivityBundle\Export\Filter\ACPFilters\UserScopeFilter + tags: + - { name: chill.export_filter, alias: 'activity_userscope_filter' } + ## Aggregators chill.activity.export.reason_aggregator: class: Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index f6bfafc41..b66c606d5 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -249,6 +249,32 @@ Activity reasons for those activities: Sujets de ces activités Filter by activity type: Filtrer les activités par type +Filter activity by locationtype: Filtrer les activités par type de localisation +'Filtered activity by locationtype: only %types%': "Filtré par type de localisation: uniquement %types%" +Accepted locationtype: Types de localisation +Filter activity by linked users: Filtrer les activités par TMS +'Filtered activity by linked users: only %users%': "Filtré par TMS: uniquement %users%" +Accepted users: TMS(s) +Filter activity by emergency: Filtrer les activités par urgence +'Filtered activity by emergency: only %emergency%': "Filtré par urgence: uniquement %emergency%" +activity is emergency: l'activité est urgente +activity is not emergency: l'activité n'est pas urgente +Filter activity by sentreceived: Filtrer les activités par envoyé/reçu +'Filtered activity by sentreceived: only %sentreceived%': "Filtré par envoyé/reçu: uniquement %sentreceived%" +Accepted sentreceived: '' +is sent: envoyé +is received: reçu +Filter activity by linked socialaction: Filtrer les activités par action liée +'Filtered activity by linked socialaction: only %actions%': "Filtré par action liée: uniquement %actions%" +Filter activity by linked socialissue: Filtrer les activités par problématique liée +'Filtered activity by linked socialissue: only %issues%': "Filtré par problématique liée: uniquement %issues%" +Filter activity by user: Filtrer les activités par créateur +'Filtered activity by user: only %users%': "Filtré par créateur: uniquement %users%" +Creators: Créateurs +Filter activity by userscope: Filtrer les activités par service du créateur +'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" +Accepted userscope: Services + #aggregators Activity type: Type d'activité Activity user: Utilisateur lié à l'activity From 95ea3bf30e8b05b1a7100bb84a01d00fd64042aa Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 13:29:22 +0200 Subject: [PATCH 4/9] refactor builder form in a filter --- .../Filter/AccompanyingCourseFilters/EmergencyFilter.php | 8 ++++---- src/Bundle/ChillPersonBundle/translations/messages.fr.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php index fc1f3d002..ed874be2b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php @@ -13,8 +13,8 @@ use Symfony\Contracts\Translation\TranslatorInterface; class EmergencyFilter implements FilterInterface { private const CHOICES = [ - 'is not emergency' => false, 'is emergency' => true, + 'is not emergency' => false, ]; private CONST DEFAULT_CHOICE = false; @@ -28,7 +28,7 @@ class EmergencyFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_emergencies', ChoiceType::class, [ + $builder->add('accepted_emergency', ChoiceType::class, [ 'choices' => self::CHOICES, 'multiple' => false, 'expanded' => true, @@ -45,7 +45,7 @@ class EmergencyFilter implements FilterInterface public function describeAction($data, $format = 'string'): array { foreach (self::CHOICES as $k => $v) { - if ($v === $data['accepted_emergencies']) { + if ($v === $data['accepted_emergency']) { $choice = $k; } } @@ -74,7 +74,7 @@ class EmergencyFilter implements FilterInterface } $qb->add('where', $where); - $qb->setParameter('emergency', $data['accepted_emergencies']); + $qb->setParameter('emergency', $data['accepted_emergency']); } public function applyOn(): string diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index e70c11139..9bb2c7e3f 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -495,7 +495,7 @@ Confidentiality: Confidentialité Group by confidential: Grouper les parcours par confidentialité Filter by emergency: Filtrer les parcours par urgence -Accepted emergencies: '' +Accepted emergency: '' is emergency: le parcours est urgent is not emergency: le parcours n'est pas urgent "Filtered by emergency: only %emergency%": "Filtré par urgence: uniquement si %emergency%" From f8f17a6a0669cef3850aabb71591af98f039b871 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 13:37:20 +0200 Subject: [PATCH 5/9] exports: move activity old filters in PersonFilters folder --- .../{ => PersonFilters}/ActivityReasonFilter.php | 2 +- .../PersonHavingActivityBetweenDateFilter.php | 2 +- .../ChillActivityBundle/config/services/export.yaml | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) rename src/Bundle/ChillActivityBundle/Export/Filter/{ => PersonFilters}/ActivityReasonFilter.php (98%) rename src/Bundle/ChillActivityBundle/Export/Filter/{ => PersonFilters}/PersonHavingActivityBetweenDateFilter.php (99%) diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php similarity index 98% rename from src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php rename to src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php index eef032818..c0845573a 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/ActivityReasonFilter.php @@ -9,7 +9,7 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Export\Filter; +namespace Chill\ActivityBundle\Export\Filter\PersonFilters; use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Export\Declarations; diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php similarity index 99% rename from src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php rename to src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php index 2c47d1c91..c8c21f385 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/PersonFilters/PersonHavingActivityBetweenDateFilter.php @@ -9,7 +9,7 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Export\Filter; +namespace Chill\ActivityBundle\Export\Filter\PersonFilters; use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Repository\ActivityReasonRepository; diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml index 393e452e6..4db7b7406 100644 --- a/src/Bundle/ChillActivityBundle/config/services/export.yaml +++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml @@ -45,11 +45,6 @@ services: - { name: chill.export, alias: 'avg_activity_visit_duration_linked_to_acp' } ## Filters - chill.activity.export.reason_filter: - class: Chill\ActivityBundle\Export\Filter\ActivityReasonFilter - tags: - - { name: chill.export_filter, alias: 'activity_reason_filter' } - chill.activity.export.type_filter: class: Chill\ActivityBundle\Export\Filter\ActivityTypeFilter tags: @@ -60,8 +55,13 @@ services: tags: - { name: chill.export_filter, alias: 'activity_date_filter' } + chill.activity.export.reason_filter: + class: Chill\ActivityBundle\Export\Filter\PersonFilters\ActivityReasonFilter + tags: + - { name: chill.export_filter, alias: 'activity_reason_filter' } + chill.activity.export.person_having_an_activity_between_date_filter: - class: Chill\ActivityBundle\Export\Filter\PersonHavingActivityBetweenDateFilter + class: Chill\ActivityBundle\Export\Filter\PersonFilters\PersonHavingActivityBetweenDateFilter tags: - #0 register as a filter name: chill.export_filter From c4944cce17ced568dd8255e142934dba7ffce5df Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 17:11:02 +0200 Subject: [PATCH 6/9] exports: move activity old aggregators in PersonAggregators folder --- .../Export/Aggregator/ActivityUserAggregator.php | 2 +- .../{ => PersonAggregators}/ActivityReasonAggregator.php | 2 +- src/Bundle/ChillActivityBundle/config/services/export.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/Bundle/ChillActivityBundle/Export/Aggregator/{ => PersonAggregators}/ActivityReasonAggregator.php (98%) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php index be4149bf9..3cdeee0f9 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php @@ -48,7 +48,7 @@ class ActivityUserAggregator implements AggregatorInterface public function applyOn(): string { - return Declarations::ACTIVITY_PERSON; + return Declarations::ACTIVITY; } public function buildForm(FormBuilderInterface $builder) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php similarity index 98% rename from src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php rename to src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php index 5c77159e3..8db93265d 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/PersonAggregators/ActivityReasonAggregator.php @@ -9,7 +9,7 @@ declare(strict_types=1); -namespace Chill\ActivityBundle\Export\Aggregator; +namespace Chill\ActivityBundle\Export\Aggregator\PersonAggregators; use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository; diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml index 4db7b7406..517e85767 100644 --- a/src/Bundle/ChillActivityBundle/config/services/export.yaml +++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml @@ -109,7 +109,7 @@ services: ## Aggregators chill.activity.export.reason_aggregator: - class: Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator + class: Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator tags: - { name: chill.export_aggregator, alias: activity_reason_aggregator } From dea7982ca882a8ea2106f922212e6fedb31b715a Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 22 Aug 2022 18:48:34 +0200 Subject: [PATCH 7/9] exports: add activity linked_to_acp new aggregators (wip) --- .../BySocialActionAggregator.php | 79 +++++++++++++++ .../BySocialIssueAggregator.php | 80 +++++++++++++++ .../ACPAggregators/ByThirdpartyAggregator.php | 79 +++++++++++++++ .../ACPAggregators/ByUserAggregator.php | 79 +++++++++++++++ .../ACPAggregators/DateAggregator.php | 99 +++++++++++++++++++ .../ACPAggregators/LocationTypeAggregator.php | 82 +++++++++++++++ .../ACPAggregators/UserScopeAggregator.php | 86 ++++++++++++++++ .../config/services/export.yaml | 35 +++++++ .../translations/messages.fr.yml | 8 ++ 9 files changed, 627 insertions(+) create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/UserScopeAggregator.php diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php new file mode 100644 index 000000000..a5cbc16f1 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php @@ -0,0 +1,79 @@ +actionRender = $actionRender; + $this->actionRepository = $actionRepository; + } + + public function getLabels($key, array $values, $data) + { + return function($value) { + if ('_header' === $value) { + return 'Social action'; + } + + $sa = $this->actionRepository->find($value); + + return $this->actionRender->renderString($sa, []); + }; + } + + public function getQueryKeys($data): array + { + return ['socialaction_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by linked socialaction'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('IDENTITY(activity.socialActions) AS socialaction_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('socialaction_aggregator'); + } else { + $qb->groupBy('socialaction_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php new file mode 100644 index 000000000..193f93f5c --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php @@ -0,0 +1,80 @@ +issueRepository = $issueRepository; + $this->issueRender = $issueRender; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + + if ($value === '_header') { + return 'Social issues'; + } + + $i = $this->issueRepository->find($value); + + return $this->issueRender->renderString($i, []); + }; + } + + public function getQueryKeys($data): array + { + return ['socialissue_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by linked socialissue'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('IDENTITY(activity.socialIssues) AS socialissue_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('socialissue_aggregator'); + } else { + $qb->groupBy('socialissue_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php new file mode 100644 index 000000000..583e3589a --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php @@ -0,0 +1,79 @@ +thirdPartyRepository = $thirdPartyRepository; + $this->thirdPartyRender = $thirdPartyRender; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ($value === '_header') { + return 'Thirdparty'; + } + + $tp = $this->thirdPartyRepository->find($value); + + return $this->thirdPartyRender->renderString($tp, []); + }; + } + + public function getQueryKeys($data): array + { + return ['thirdparty_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by linked thirdparties'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('IDENTITY(activity.thirdParties) AS thirdparty_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('thirdparty_aggregator'); + } else { + $qb->groupBy('thirdparty_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php new file mode 100644 index 000000000..9cd6601c1 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php @@ -0,0 +1,79 @@ +userRepository = $userRepository; + $this->userRender = $userRender; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ($value === '_header') { + return 'Accepted users'; + } + + $u = $this->userRepository->find($value); + + return $this->userRender->renderString($u, []); + }; + } + + public function getQueryKeys($data): array + { + return ['users_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by linked users'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('IDENTITY(activity.users) AS users_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('users_aggregator'); + } else { + $qb->groupBy('users_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php new file mode 100644 index 000000000..ef866f4f6 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php @@ -0,0 +1,99 @@ + 'month', + 'by week' => 'week', // sur base du numéro de la semaine + 'by year' => 'year', + ]; + + private CONST DEFAULT_CHOICE = 'year'; + + private TranslatorInterface $translator; + + public function __construct( + TranslatorInterface $translator + ) { + $this->translator = $translator; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + switch ($value) { + case '_header': + return 'By date'; + + case 'month': + return $this->translator->trans('by month'); + + case 'week': + return $this->translator->trans('by week'); + + case 'year': + return $this->translator->trans('by year'); + + default: + throw new LogicException(sprintf('The value %s is not valid', $value)); + } + }; + } + + public function getQueryKeys($data): array + { + return ['date_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('by_date', ChoiceType::class, [ + 'choices' => self::CHOICES, + 'multiple' => false, + 'expanded' => true, + 'empty_data' => self::DEFAULT_CHOICE, + 'data' => self::DEFAULT_CHOICE, + ]); + } + + public function getTitle(): string + { + return 'Group activity by date'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('activity.date AS date_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('date_aggregator'); + } else { + $qb->groupBy('date_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php new file mode 100644 index 000000000..088ac0e4a --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php @@ -0,0 +1,82 @@ +locationTypeRepository = $locationTypeRepository; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ($value === '_header') { + return 'Accepted locationtype'; + } + + $lt = $this->locationTypeRepository->find($value); + + return $this->translatableStringHelper->localize( + $lt->getTitle() + ); + }; + } + + public function getQueryKeys($data): array + { + return ['locationtype_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by locationtype'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $qb->addSelect('IDENTITY(activity.location) AS locationtype_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('locationtype_aggregator'); + } else { + $qb->groupBy('locationtype_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/UserScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/UserScopeAggregator.php new file mode 100644 index 000000000..4d6cef24a --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/UserScopeAggregator.php @@ -0,0 +1,86 @@ +scopeRepository = $scopeRepository; + $this->translatableStringHelper = $translatableStringHelper; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ($value === '_header') { + return 'Scope'; + } + + $s = $this->scopeRepository->find($value); + + return $this->translatableStringHelper->localize( + $s->getName() + ); + }; + } + + public function getQueryKeys($data): array + { + return ['userscope_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + // no form + } + + public function getTitle(): string + { + return 'Group activity by userscope'; + } + + public function addRole() + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + if (!in_array('user', $qb->getAllAliases())) { + $qb->join('activity.user', 'user'); + } + + $qb->addSelect('IDENTITY(user.mainScope) AS userscope_aggregator'); + + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('userscope_aggregator'); + } else { + $qb->groupBy('userscope_aggregator'); + } + } + + public function applyOn(): string + { + return Declarations::ACTIVITY_ACP; + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml index 517e85767..c88046c5f 100644 --- a/src/Bundle/ChillActivityBundle/config/services/export.yaml +++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml @@ -122,3 +122,38 @@ services: class: Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator tags: - { name: chill.export_aggregator, alias: activity_user_aggregator } + + chill.activity.export.locationtype_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\LocationTypeAggregator + tags: + - { name: chill.export_aggregator, alias: activity_locationtype_aggregator } + + chill.activity.export.date_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\DateAggregator + tags: + - { name: chill.export_aggregator, alias: activity_date_aggregator } + + chill.activity.export.byuser_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByUserAggregator + tags: + - { name: chill.export_aggregator, alias: activity_byuser_aggregator } + + chill.activity.export.bythirdparty_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByThirdpartyAggregator + tags: + - { name: chill.export_aggregator, alias: activity_bythirdparty_aggregator } + + chill.activity.export.bysocialaction_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialActionAggregator + tags: + - { name: chill.export_aggregator, alias: activity_bysocialaction_aggregator } + + chill.activity.export.bysocialissue_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialIssueAggregator + tags: + - { name: chill.export_aggregator, alias: activity_bysocialissue_aggregator } + + chill.activity.export.userscope_aggregator: + class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\UserScopeAggregator + tags: + - { name: chill.export_aggregator, alias: activity_userscope_aggregator } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index b66c606d5..0bef84ba0 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -286,6 +286,14 @@ Aggregate by activity user: Grouper les activités par utilisateur Aggregate by activity type: Grouper les activités par type Aggregate by activity reason: Grouper les activités par sujet +Group activity by locationtype: Grouper les activités par type de localisation +Group activity by date: Grouper les activités par date +Group activity by linked users: Grouper les activités par TMS impliqué +Group activity by linked thirdparties: Grouper les activités par tiers impliqué +Group activity by linked socialaction: Grouper les activités par action liée +Group activity by linked socialissue: Grouper les activités par problématique liée +Group activity by userscope: Grouper les activités par service du créateur + Last activities: Les dernières activités See activity in accompanying course context: Voir l'activité dans le contexte du parcours d'accompagnement From 52902e905a294f15221c6d6f808089b8ab78d9d1 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 24 Aug 2022 11:22:54 +0200 Subject: [PATCH 8/9] exports: test all activity filters/aggregators and fix errors --- .../ACPAggregators/BySocialActionAggregator.php | 6 +++++- .../ACPAggregators/BySocialIssueAggregator.php | 6 +++++- .../ACPAggregators/ByThirdpartyAggregator.php | 8 ++++++-- .../Aggregator/ACPAggregators/ByUserAggregator.php | 6 +++++- .../Aggregator/ACPAggregators/DateAggregator.php | 3 ++- .../ACPAggregators/LocationTypeAggregator.php | 6 +++++- .../Export/Aggregator/ActivityUserAggregator.php | 13 ++++++++++--- .../Filter/ACPFilters/BySocialActionFilter.php | 8 ++++++-- .../Filter/ACPFilters/BySocialIssueFilter.php | 8 ++++++-- .../Export/Filter/ACPFilters/ByUserFilter.php | 8 ++++++-- .../Export/Filter/ACPFilters/LocationTypeFilter.php | 2 +- .../Export/Filter/ACPFilters/UserFilter.php | 2 +- .../Export/Filter/ACPFilters/UserScopeFilter.php | 2 +- .../translations/messages.fr.yml | 9 +++++++-- 14 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php index a5cbc16f1..269924a8a 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php @@ -61,7 +61,11 @@ class BySocialActionAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('IDENTITY(activity.socialActions) AS socialaction_aggregator'); + if(!in_array('socialaction', $qb->getAllAliases())) { + $qb->join('activity.socialActions', 'socialaction'); + } + + $qb->addSelect('socialaction.id AS socialaction_aggregator'); $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php index 193f93f5c..0e4b9ab8e 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php @@ -62,7 +62,11 @@ class BySocialIssueAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('IDENTITY(activity.socialIssues) AS socialissue_aggregator'); + if (!in_array('socialissue', $qb->getAllAliases())) { + $qb->join('activity.socialIssues', 'socialissue'); + } + + $qb->addSelect('socialissue.id AS socialissue_aggregator'); $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php index 583e3589a..5a9e633ef 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php @@ -30,7 +30,7 @@ class ByThirdpartyAggregator implements AggregatorInterface { return function ($value): string { if ($value === '_header') { - return 'Thirdparty'; + return 'Accepted thirdparty'; } $tp = $this->thirdPartyRepository->find($value); @@ -61,7 +61,11 @@ class ByThirdpartyAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('IDENTITY(activity.thirdParties) AS thirdparty_aggregator'); + if (!in_array('thirdparty', $qb->getAllAliases())) { + $qb->join('activity.thirdParties', 'thirdparty'); + } + + $qb->addSelect('thirdparty.id AS thirdparty_aggregator'); $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php index 9cd6601c1..95c9998b8 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php @@ -61,7 +61,11 @@ class ByUserAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('IDENTITY(activity.users) AS users_aggregator'); + if (!in_array('user', $qb->getAllAliases())) { + $qb->join('activity.users', 'user'); + } + + $qb->addSelect('user.id AS users_aggregator'); $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php index ef866f4f6..11e508b88 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php @@ -16,7 +16,7 @@ class DateAggregator implements AggregatorInterface { private const CHOICES = [ 'by month' => 'month', - 'by week' => 'week', // sur base du numéro de la semaine + 'by week' => 'week', // numéro de la semaine 'by year' => 'year', ]; @@ -60,6 +60,7 @@ class DateAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('by_date', ChoiceType::class, [ + 'label' => 'Frequency', 'choices' => self::CHOICES, 'multiple' => false, 'expanded' => true, diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php index 088ac0e4a..aa5052aaa 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php @@ -63,7 +63,11 @@ class LocationTypeAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('IDENTITY(activity.location) AS locationtype_aggregator'); + if (!in_array('location', $qb->getAllAliases())) { + $qb->join('activity.location', 'location'); + } + + $qb->addSelect('IDENTITY(location.locationType) AS locationtype_aggregator'); $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php index 3cdeee0f9..675098c60 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php @@ -15,6 +15,7 @@ use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Repository\UserRepository; +use Chill\MainBundle\Templating\Entity\UserRender; use Closure; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -26,10 +27,14 @@ class ActivityUserAggregator implements AggregatorInterface private UserRepository $userRepository; + private UserRender $userRender; + public function __construct( - UserRepository $userRepository + UserRepository $userRepository, + UserRender $userRender ) { $this->userRepository = $userRepository; + $this->userRender = $userRender; } public function addRole() @@ -63,10 +68,12 @@ class ActivityUserAggregator implements AggregatorInterface return function ($value) { if ('_header' === $value) { - return 'activity user'; + return 'Activity user'; } - return $this->userRepository->find($value)->getUsername(); + $u = $this->userRepository->find($value); + + return $this->userRender->renderString($u, []); }; } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php index ea125adb2..58d77c73e 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php @@ -48,7 +48,7 @@ class BySocialActionFilter implements FilterInterface } return ['Filtered activity by linked socialaction: only %actions%', [ - '%actions%' => implode(", ou", $actions) + '%actions%' => implode(", ou ", $actions) ]]; } @@ -61,7 +61,11 @@ class BySocialActionFilter implements FilterInterface { $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('activity.socialActions', ':socialactions'); + if (!in_array('socialaction', $qb->getAllAliases())) { + $qb->join('activity.socialActions', 'socialaction'); + } + + $clause = $qb->expr()->in('socialaction.id', ':socialactions'); if ($where instanceof Andx) { $where->add($clause); diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php index 247b0ea32..052b780ff 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php @@ -48,7 +48,7 @@ class BySocialIssueFilter implements FilterInterface } return ['Filtered activity by linked socialissue: only %issues%', [ - '%issues%' => implode(", ou", $issues) + '%issues%' => implode(", ou ", $issues) ]]; } @@ -61,7 +61,11 @@ class BySocialIssueFilter implements FilterInterface { $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('activity.socialIssues', ':socialissues'); + if (!in_array('socialissue', $qb->getAllAliases())) { + $qb->join('activity.socialIssues', 'socialissue'); + } + + $clause = $qb->expr()->in('socialissue.id', ':socialissues'); if ($where instanceof Andx) { $where->add($clause); diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php index 9fef06f72..b128b03aa 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php @@ -48,7 +48,7 @@ class ByUserFilter implements FilterInterface } return ['Filtered activity by linked users: only %users%', [ - '%users%' => implode(", ou", $users) + '%users%' => implode(", ou ", $users) ]]; } @@ -61,7 +61,11 @@ class ByUserFilter implements FilterInterface { $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('activity.users', ':users'); + if (!in_array('user', $qb->getAllAliases())) { + $qb->join('activity.users', 'user'); + } + + $clause = $qb->expr()->in('user.id', ':users'); if ($where instanceof Andx) { $where->add($clause); diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php index 22e1f3c30..cf29f20f2 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php @@ -50,7 +50,7 @@ class LocationTypeFilter implements FilterInterface } return ['Filtered activity by locationtype: only %types%', [ - '%types%' => implode(", ou", $types) + '%types%' => implode(", ou ", $types) ]]; } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php index 02aff8cad..d1455ea89 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserFilter.php @@ -49,7 +49,7 @@ class UserFilter implements FilterInterface } return ['Filtered activity by user: only %users%', [ - '%users%' => implode(", ou", $users) + '%users%' => implode(", ou ", $users) ]]; } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php index abc26d418..987704ab8 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php @@ -52,7 +52,7 @@ class UserScopeFilter implements FilterInterface } return ['Filtered activity by userscope: only %scopes%', [ - '%scopes%' => implode(", ou", $scopes) + '%scopes%' => implode(", ou ", $scopes) ]]; } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 0bef84ba0..4041b97dc 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -256,7 +256,7 @@ Filter activity by linked users: Filtrer les activités par TMS 'Filtered activity by linked users: only %users%': "Filtré par TMS: uniquement %users%" Accepted users: TMS(s) Filter activity by emergency: Filtrer les activités par urgence -'Filtered activity by emergency: only %emergency%': "Filtré par urgence: uniquement %emergency%" +'Filtered activity by emergency: only %emergency%': "Filtré par urgence: uniquement si %emergency%" activity is emergency: l'activité est urgente activity is not emergency: l'activité n'est pas urgente Filter activity by sentreceived: Filtrer les activités par envoyé/reçu @@ -277,7 +277,7 @@ Accepted userscope: Services #aggregators Activity type: Type d'activité -Activity user: Utilisateur lié à l'activity +Activity user: Utilisateur lié à l'activité By reason: Par sujet By category of reason: Par catégorie de sujet Reason's level: Niveau du sujet @@ -288,8 +288,13 @@ Aggregate by activity reason: Grouper les activités par sujet Group activity by locationtype: Grouper les activités par type de localisation Group activity by date: Grouper les activités par date +Frequency: Fréquence +by month: par mois +by week: par semaine +by year: par année Group activity by linked users: Grouper les activités par TMS impliqué Group activity by linked thirdparties: Grouper les activités par tiers impliqué +Accepted thirdparty: Tiers impliqué Group activity by linked socialaction: Grouper les activités par action liée Group activity by linked socialissue: Grouper les activités par problématique liée Group activity by userscope: Grouper les activités par service du créateur From 7173e4be4a998eeec46f5fcb26436b1904b9cb5e Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 24 Aug 2022 15:44:18 +0200 Subject: [PATCH 9/9] exports: fix activity DateAggregator; add customs DQL Date/Time functions --- .../ACPAggregators/DateAggregator.php | 62 +++++++++++++++---- .../translations/messages.fr.yml | 8 ++- .../ChillMainExtension.php | 6 ++ .../ChillMainBundle/Doctrine/DQL/Extract.php | 47 ++++++++++++++ .../ChillMainBundle/Doctrine/DQL/ToChar.php | 38 ++++++++++++ 5 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php create mode 100644 src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php index 11e508b88..6dda268e2 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php @@ -8,6 +8,7 @@ use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Export\AggregatorInterface; use Closure; use Doctrine\ORM\QueryBuilder; +use RuntimeException; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -16,7 +17,7 @@ class DateAggregator implements AggregatorInterface { private const CHOICES = [ 'by month' => 'month', - 'by week' => 'week', // numéro de la semaine + 'by week' => 'week', 'by year' => 'year', ]; @@ -32,22 +33,32 @@ class DateAggregator implements AggregatorInterface public function getLabels($key, array $values, $data) { - return function ($value): string { - switch ($value) { - case '_header': - return 'By date'; - + return function ($value) use ($data): string { + switch ($data['frequency']) { case 'month': - return $this->translator->trans('by month'); + if ($value === '_header') { + return 'by month'; + } + $month = \DateTime::createFromFormat('!m', $value); + return + sprintf("%02d", $value) .'/'. + $month->format('F') // TODO translation ?!? + ; case 'week': - return $this->translator->trans('by week'); + if ($value === '_header') { + return 'by week'; + } + return $this->translator->trans('for week') .' '. $value ; case 'year': - return $this->translator->trans('by year'); + if ($value === '_header') { + return 'by year'; + } + return $this->translator->trans('in year') .' '. $value ; default: - throw new LogicException(sprintf('The value %s is not valid', $value)); + throw new RuntimeException(sprintf('The value %s is not valid', $value)); } }; } @@ -59,8 +70,7 @@ class DateAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('by_date', ChoiceType::class, [ - 'label' => 'Frequency', + $builder->add('frequency', ChoiceType::class, [ 'choices' => self::CHOICES, 'multiple' => false, 'expanded' => true, @@ -81,7 +91,33 @@ class DateAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('activity.date AS date_aggregator'); + switch ($data['frequency']) { + case 'month': + $qb + //->addSelect("TO_CHAR(activity.date,'Mon') AS MON") + ->addSelect('EXTRACT(month FROM activity.date) AS date_aggregator') + //->orderBy('date_aggregator') + ; + break; + + case 'week': + $qb + ->addSelect("TO_CHAR(activity.date, 'IW') AS date_aggregator") + //->orderBy('date_aggregator') + ; + break; + + case 'year': + $qb + //->addSelect("TO_CHAR(activity.date, 'YYYY') AS date_aggregator") + ->addSelect('EXTRACT(year FROM activity.date) AS date_aggregator') + //->orderBy('date_aggregator', 'ASC') + ; + break; + + default: + throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency'])); + } $groupBy = $qb->getDQLPart('groupBy'); diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 4041b97dc..9f8ed3d7c 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -289,9 +289,11 @@ Aggregate by activity reason: Grouper les activités par sujet Group activity by locationtype: Grouper les activités par type de localisation Group activity by date: Grouper les activités par date Frequency: Fréquence -by month: par mois -by week: par semaine -by year: par année +by month: Par mois +by week: Par semaine +for week: Semaine +by year: Par année +in year: En Group activity by linked users: Grouper les activités par TMS impliqué Group activity by linked thirdparties: Grouper les activités par tiers impliqué Accepted thirdparty: Tiers impliqué diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index df0affa86..30bda0ab6 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -22,6 +22,7 @@ use Chill\MainBundle\Controller\UserController; use Chill\MainBundle\Controller\UserJobApiController; use Chill\MainBundle\Controller\UserJobController; use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface; +use Chill\MainBundle\Doctrine\DQL\Extract; use Chill\MainBundle\Doctrine\DQL\GetJsonFieldByKey; use Chill\MainBundle\Doctrine\DQL\JsonAggregate; use Chill\MainBundle\Doctrine\DQL\JsonbArrayLength; @@ -31,6 +32,7 @@ use Chill\MainBundle\Doctrine\DQL\Replace; use Chill\MainBundle\Doctrine\DQL\Similarity; use Chill\MainBundle\Doctrine\DQL\STContains; use Chill\MainBundle\Doctrine\DQL\StrictWordSimilarityOPS; +use Chill\MainBundle\Doctrine\DQL\ToChar; use Chill\MainBundle\Doctrine\DQL\Unaccent; use Chill\MainBundle\Doctrine\ORM\Hydration\FlatHierarchyEntityHydrator; use Chill\MainBundle\Doctrine\Type\NativeDateIntervalType; @@ -238,6 +240,10 @@ class ChillMainExtension extends Extension implements 'ST_CONTAINS' => STContains::class, 'JSONB_ARRAY_LENGTH' => JsonbArrayLength::class, ], + 'datetime_functions' => [ + 'EXTRACT' => Extract::class, + 'TO_CHAR' => ToChar::class, + ], ], 'hydrators' => [ 'chill_flat_hierarchy_list' => FlatHierarchyEntityHydrator::class, diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php new file mode 100644 index 000000000..44d20724b --- /dev/null +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php @@ -0,0 +1,47 @@ +field, + $this->value->dispatch($sqlWalker) + ); + } + + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $parser->match(Lexer::T_IDENTIFIER); + $this->field = $parser->getLexer()->token['value']; + + $parser->match(Lexer::T_FROM); + + $this->value = $parser->ScalarExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + +} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php new file mode 100644 index 000000000..c634555dc --- /dev/null +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php @@ -0,0 +1,38 @@ +walkArithmeticPrimary($this->datetime), + $sqlWalker->walkArithmeticPrimary($this->fmt) + ); + } + + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->datetime = $parser->ArithmeticExpression(); + $parser->match(Lexer::T_COMMA); + $this->fmt = $parser->StringExpression(); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + +} \ No newline at end of file