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..269924a8a --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialActionAggregator.php @@ -0,0 +1,83 @@ +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) + { + if(!in_array('socialaction', $qb->getAllAliases())) { + $qb->join('activity.socialActions', 'socialaction'); + } + + $qb->addSelect('socialaction.id 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..0e4b9ab8e --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/BySocialIssueAggregator.php @@ -0,0 +1,84 @@ +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) + { + if (!in_array('socialissue', $qb->getAllAliases())) { + $qb->join('activity.socialIssues', 'socialissue'); + } + + $qb->addSelect('socialissue.id 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..5a9e633ef --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByThirdpartyAggregator.php @@ -0,0 +1,83 @@ +thirdPartyRepository = $thirdPartyRepository; + $this->thirdPartyRender = $thirdPartyRender; + } + + public function getLabels($key, array $values, $data) + { + return function ($value): string { + if ($value === '_header') { + return 'Accepted 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) + { + if (!in_array('thirdparty', $qb->getAllAliases())) { + $qb->join('activity.thirdParties', 'thirdparty'); + } + + $qb->addSelect('thirdparty.id 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..95c9998b8 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/ByUserAggregator.php @@ -0,0 +1,83 @@ +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) + { + if (!in_array('user', $qb->getAllAliases())) { + $qb->join('activity.users', 'user'); + } + + $qb->addSelect('user.id 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..6dda268e2 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php @@ -0,0 +1,136 @@ + 'month', + 'by week' => 'week', + '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) use ($data): string { + switch ($data['frequency']) { + case 'month': + if ($value === '_header') { + return 'by month'; + } + $month = \DateTime::createFromFormat('!m', $value); + return + sprintf("%02d", $value) .'/'. + $month->format('F') // TODO translation ?!? + ; + + case 'week': + if ($value === '_header') { + return 'by week'; + } + return $this->translator->trans('for week') .' '. $value ; + + case 'year': + if ($value === '_header') { + return 'by year'; + } + return $this->translator->trans('in year') .' '. $value ; + + default: + throw new RuntimeException(sprintf('The value %s is not valid', $value)); + } + }; + } + + public function getQueryKeys($data): array + { + return ['date_aggregator']; + } + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('frequency', 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) + { + 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'); + + 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..aa5052aaa --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/LocationTypeAggregator.php @@ -0,0 +1,86 @@ +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) + { + if (!in_array('location', $qb->getAllAliases())) { + $qb->join('activity.location', 'location'); + } + + $qb->addSelect('IDENTITY(location.locationType) 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/Export/Aggregator/ActivityUserAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php index be4149bf9..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() @@ -48,7 +53,7 @@ class ActivityUserAggregator implements AggregatorInterface public function applyOn(): string { - return Declarations::ACTIVITY_PERSON; + return Declarations::ACTIVITY; } public function buildForm(FormBuilderInterface $builder) @@ -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/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/Export/Filter/ACPFilters/BySocialActionFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php new file mode 100644 index 000000000..58d77c73e --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialActionFilter.php @@ -0,0 +1,85 @@ +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'); + + 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); + } 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..052b780ff --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/BySocialIssueFilter.php @@ -0,0 +1,85 @@ +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'); + + 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); + } 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..b128b03aa --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ByUserFilter.php @@ -0,0 +1,84 @@ +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'); + + 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); + } 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..cf29f20f2 --- /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..d1455ea89 --- /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..987704ab8 --- /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/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 c6b0e9718..c88046c5f 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,16 +55,61 @@ 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 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 + class: Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator tags: - { name: chill.export_aggregator, alias: activity_reason_aggregator } @@ -82,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 f6bfafc41..9f8ed3d7c 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -249,9 +249,35 @@ 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 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 +'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 +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 @@ -260,6 +286,21 @@ 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 +Frequency: Fréquence +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é +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 diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index 320be80f5..48f17be76 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 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 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 34cc1c8af..9bb2c7e3f 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%" @@ -499,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%" @@ -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