diff --git a/.changes/unreleased/Feature-20231115-114550.yaml b/.changes/unreleased/Feature-20231115-114550.yaml new file mode 100644 index 000000000..6678b19f6 --- /dev/null +++ b/.changes/unreleased/Feature-20231115-114550.yaml @@ -0,0 +1,5 @@ +kind: Feature +body: 'Export: add a export which count persons on accompanying period work' +time: 2023-11-15T11:45:50.540277614+01:00 +custom: + Issue: "206" diff --git a/.changes/unreleased/Feature-20231115-121431.yaml b/.changes/unreleased/Feature-20231115-121431.yaml new file mode 100644 index 000000000..6f7e5a33f --- /dev/null +++ b/.changes/unreleased/Feature-20231115-121431.yaml @@ -0,0 +1,5 @@ +kind: Feature +body: 'Export: add an export which count persons on activity' +time: 2023-11-15T12:14:31.515840946+01:00 +custom: + Issue: "206" diff --git a/.changes/unreleased/Feature-20231115-132233.yaml b/.changes/unreleased/Feature-20231115-132233.yaml new file mode 100644 index 000000000..5d3accbd4 --- /dev/null +++ b/.changes/unreleased/Feature-20231115-132233.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: 'Export: add clauses on the social work start date and end date within the filter + "Filter accompanying period by accompanying period work"' +time: 2023-11-15T13:22:33.19215851+01:00 +custom: + Issue: "203" diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountPersonsOnActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountPersonsOnActivity.php new file mode 100644 index 000000000..c49b9d4ad --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountPersonsOnActivity.php @@ -0,0 +1,138 @@ +repository = $em->getRepository(Activity::class); + $this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; + } + + public function buildForm(FormBuilderInterface $builder) {} + + public function getFormDefaultData(): array + { + return []; + } + + public function getAllowedFormattersTypes(): array + { + return [FormatterInterface::TYPE_TABULAR]; + } + + public function getDescription(): string + { + return 'export.export.count_person_on_activity.description'; + } + + public function getGroup(): string + { + return 'Exports of activities linked to an accompanying period'; + } + + public function getLabels($key, array $values, $data) + { + if ('export_count_activity' !== $key) { + throw new \LogicException("the key {$key} is not used by this export"); + } + + return static fn ($value) => '_header' === $value ? 'export.export.count_person_on_activity.header' : $value; + } + + public function getQueryKeys($data): array + { + return ['export_count_activity']; + } + + public function getResult($query, $data) + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string + { + return 'export.export.count_person_on_activity.title'; + } + + public function getType(): string + { + return Declarations::ACTIVITY; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) + { + $centers = array_map(static fn ($el) => $el['center'], $acl); + + $qb = $this->repository + ->createQueryBuilder('activity') + ->join('activity.persons', 'person') + ->join('activity.accompanyingPeriod', 'acp'); + + if ($this->filterStatsByCenters) { + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part + JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person) + WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers); + } + + AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb); + + $qb->select('COUNT(DISTINCT person.id) as export_count_activity'); + + return $qb; + } + + public function requiredRole(): string + { + return ActivityStatsVoter::STATS; + } + + public function supportsModifiers(): array + { + return [ + Declarations::ACTIVITY, + Declarations::ACTIVITY_ACP, + PersonDeclarations::ACP_TYPE, + PersonDeclarations::PERSON_TYPE, + ]; + } +} diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountPersonsOnActivityTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountPersonsOnActivityTest.php new file mode 100644 index 000000000..25d6643fb --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Export/LinkedToACP/CountPersonsOnActivityTest.php @@ -0,0 +1,54 @@ +get(EntityManagerInterface::class); + + yield new CountPersonsOnActivity($em, $this->getParameters(true)); + yield new CountPersonsOnActivity($em, $this->getParameters(false)); + } + + public function getFormData() + { + return [[]]; + } + + public function getModifiersCombination() + { + return [[ + Declarations::ACTIVITY, + Declarations::ACTIVITY_ACP, + PersonDeclarations::ACP_TYPE, + PersonDeclarations::PERSON_TYPE, + ]]; + } +} diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml index dcc6bec17..52294be40 100644 --- a/src/Bundle/ChillActivityBundle/config/services/export.yaml +++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml @@ -16,6 +16,10 @@ services: tags: - { name: chill.export, alias: 'list_activity_linked_to_person' } + Chill\ActivityBundle\Export\Export\LinkedToACP\CountPersonsOnActivity: + tags: + - { name: chill.export, alias: 'count_person_on_activity' } + chill.activity.export.count_activity_linked_to_acp: class: Chill\ActivityBundle\Export\Export\LinkedToACP\CountActivity tags: diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 52c5366a7..036f75ce3 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -332,6 +332,11 @@ docgen: myWorksOnly: Prendre en compte uniquement les actions d'accompagnement dont je suis référent export: + export: + count_person_on_activity: + title: Nombre d'usagers concernés par les échanges + description: Compte le nombre d'usagers concernés par les échanges. Si un usager est présent dans plusieurs échanges, il n'est comptabilisé qu'une seule fois. + header: Nombre d'usagers concernés par des échanges list: activity: users name: Nom des utilisateurs diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php index 7628d6aa3..6a139de7b 100644 --- a/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php +++ b/src/Bundle/ChillMainBundle/Form/DataMapper/RollingDateDataMapper.php @@ -37,9 +37,13 @@ class RollingDateDataMapper implements DataMapperInterface { $forms = iterator_to_array($forms); - $viewData = new RollingDate( - $forms['roll']->getData() ?? RollingDate::T_TODAY, - $forms['fixedDate']->getData() - ); + if (null === $forms['roll']->getData()) { + $viewData = null; + } else { + $viewData = new RollingDate( + $forms['roll']->getData(), + $forms['fixedDate']->getData() + ); + } } } diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickRollingDateType.php b/src/Bundle/ChillMainBundle/Form/Type/PickRollingDateType.php index 8ceb08578..ca10530e8 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickRollingDateType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickRollingDateType.php @@ -54,7 +54,7 @@ class PickRollingDateType extends AbstractType { $resolver->setDefaults([ 'class' => RollingDate::class, - 'empty_data' => new RollingDate(RollingDate::T_TODAY), + 'empty_data' => null, 'constraints' => [ new Callback($this->validate(...)), ], @@ -66,6 +66,10 @@ class PickRollingDateType extends AbstractType public function validate($data, ExecutionContextInterface $context, $payload): void { + if (null === $data) { + return; + } + /** @var RollingDate $data */ if (RollingDate::T_FIXED_DATE === $data->getRoll() && null === $data->getFixedDate()) { $context diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWork.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWork.php new file mode 100644 index 000000000..13dd0d512 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWork.php @@ -0,0 +1,139 @@ +filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; + } + + public function buildForm(FormBuilderInterface $builder): void + { + // No form necessary? + } + + public function getFormDefaultData(): array + { + return []; + } + + public function getAllowedFormattersTypes(): array + { + return [FormatterInterface::TYPE_TABULAR]; + } + + public function getDescription(): string + { + return 'export.export.count_person_on_acpw_associate_person_on_work.description'; + } + + public function getGroup(): string + { + return 'Exports of social work actions'; + } + + public function getLabels($key, array $values, $data) + { + if ('export_result' !== $key) { + throw new \LogicException("the key {$key} is not used by this export"); + } + + $labels = array_combine($values, $values); + $labels['_header'] = 'export.export.count_person_on_acpw_associate_person_on_work.header'; + + return static fn ($value) => $labels[$value]; + } + + public function getQueryKeys($data): array + { + return ['export_result']; + } + + public function getResult($query, $data) + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string + { + return 'export.export.count_person_on_acpw_associate_person_on_work.title'; + } + + public function getType(): string + { + return Declarations::SOCIAL_WORK_ACTION_TYPE; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []): QueryBuilder + { + $centers = array_map(static fn ($el) => $el['center'], $acl); + + $qb = $this->em->createQueryBuilder(); + + $qb + ->from(AccompanyingPeriod\AccompanyingPeriodWork::class, 'acpw') + ->join('acpw.accompanyingPeriod', 'acp') + ->join('acpw.persons', 'person'); + + if ($this->filterStatsByCenters) { + $qb + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM '.PersonCenterHistory::class.' acl_count_person_history WHERE acl_count_person_history.person = person + AND acl_count_person_history.center IN (:authorized_centers) + ' + ) + ) + ->setParameter('authorized_centers', $centers); + } + + $qb->select('COUNT(DISTINCT person.id) as export_result'); + + AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb); + + return $qb; + } + + public function requiredRole(): string + { + return AccompanyingPeriodVoter::STATS; + } + + public function supportsModifiers(): array + { + return [ + Declarations::SOCIAL_WORK_ACTION_TYPE, + Declarations::ACP_TYPE, + Declarations::PERSON_TYPE, + ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php index cba86c257..dc5ffa042 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/SocialActionFilter.php @@ -12,6 +12,8 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\SocialWork\SocialAction; use Chill\PersonBundle\Export\Declarations; @@ -19,10 +21,17 @@ use Chill\PersonBundle\Form\Type\PickSocialActionType; use Chill\PersonBundle\Templating\Entity\SocialActionRender; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final readonly class SocialActionFilter implements FilterInterface { - public function __construct(private SocialActionRender $actionRender) {} + private const PREFIX = 'acp_by_social_action_filter'; + + public function __construct( + private SocialActionRender $actionRender, + private RollingDateConverterInterface $rollingDateConverter, + private TranslatorInterface $translator + ) {} public function addRole(): ?string { @@ -31,17 +40,40 @@ final readonly class SocialActionFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->andWhere( - $qb->expr()->exists( - sprintf( - 'SELECT 1 FROM %s acp_by_social_action_filter WHERE acp_by_social_action_filter.socialAction ' - .'IN (:acp_by_social_action_filter_actions) AND acp_by_social_action_filter.accompanyingPeriod = acp', - AccompanyingPeriod\AccompanyingPeriodWork::class - ) - ) - ); + $p = self::PREFIX; - $qb->setParameter('acp_by_social_action_filter_actions', SocialAction::getDescendantsWithThisForActions($data['accepted_socialactions'])); + $dql = + sprintf( + 'SELECT 1 FROM %s acp_by_social_action_filter WHERE acp_by_social_action_filter.accompanyingPeriod = acp ', + AccompanyingPeriod\AccompanyingPeriodWork::class + ); + + if (0 < count($data['accepted_socialactions'])) { + $dql .= 'AND acp_by_social_action_filter.socialAction IN (:acp_by_social_action_filter_actions)'; + $qb->setParameter("{$p}_actions", SocialAction::getDescendantsWithThisForActions($data['accepted_socialactions'])); + } + + if (null !== ($data['start_date_after'] ?? null)) { + $dql .= " AND acp_by_social_action_filter.startDate > :{$p}_start_date_after"; + $qb->setParameter("{$p}_start_date_after", $this->rollingDateConverter->convert($data['start_date_after'])); + } + + if (null !== ($data['start_date_before'] ?? null)) { + $dql .= " AND acp_by_social_action_filter.startDate <= :{$p}_start_date_before"; + $qb->setParameter("{$p}_start_date_before", $this->rollingDateConverter->convert($data['start_date_before'])); + } + + if (null !== ($data['end_date_after'] ?? null)) { + $dql .= " AND acp_by_social_action_filter.endDate > :{$p}_end_date_after OR acp_by_social_action_filter.endDate IS NULL"; + $qb->setParameter("{$p}_end_date_after", $this->rollingDateConverter->convert($data['end_date_after'])); + } + + if (null !== ($data['end_date_before'] ?? null)) { + $dql .= " AND acp_by_social_action_filter.endDate <= :{$p}_end_date_before OR acp_by_social_action_filter.endDate IS NULL"; + $qb->setParameter("{$p}_end_date_before", $this->rollingDateConverter->convert($data['end_date_before'])); + } + + $qb->andWhere($qb->expr()->exists($dql)); } public function applyOn(): string @@ -51,14 +83,44 @@ final readonly class SocialActionFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_socialactions', PickSocialActionType::class, [ - 'multiple' => true, - ]); + $builder + ->add('accepted_socialactions', PickSocialActionType::class, [ + 'multiple' => true, + 'label' => 'export.filter.course.by_social_action.Accepted socialactions', + 'help' => 'export.filter.course.by_social_action.accepted socialations help', + ]) + ->add('start_date_after', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_social_action.start date after', + 'help' => 'export.filter.course.by_social_action.start date after help', + 'required' => false, + ]) + ->add('start_date_before', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_social_action.start date before', + 'help' => 'export.filter.course.by_social_action.start date before help', + 'required' => false, + ]) + ->add('end_date_after', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_social_action.end date after', + 'help' => 'export.filter.course.by_social_action.end date after help', + 'required' => false, + ]) + ->add('end_date_before', PickRollingDateType::class, [ + 'label' => 'export.filter.course.by_social_action.end date before', + 'help' => 'export.filter.course.by_social_action.end date before help', + 'required' => false, + ]) + ; } public function getFormDefaultData(): array { - return []; + return [ + 'accepted_social_actions' => [], + 'start_date_after' => null, + 'start_date_before' => null, + 'end_date_after' => null, + 'end_date_before' => null, + ]; } public function describeAction($data, $format = 'string'): array @@ -73,13 +135,17 @@ final readonly class SocialActionFilter implements FilterInterface ]); } - return ['Filtered by socialactions: only %socialactions%', [ + return ['export.filter.course.by_social_action.Filtered by socialactions: only %socialactions%', [ '%socialactions%' => implode(', ', $actions), + '%start_date_after%' => null === ($data['start_date_after'] ?? null) ? '('.$this->translator->trans('export.filter.course.by_social_action.date ignored').')' : $this->rollingDateConverter->convert($data['start_date_after'])->format('d-m-Y'), + '%start_date_before%' => null === ($data['start_date_before'] ?? null) ? '('.$this->translator->trans('export.filter.course.by_social_action.date ignored').')' : $this->rollingDateConverter->convert($data['start_date_before'])->format('d-m-Y'), + '%end_date_after%' => null === ($data['end_date_after'] ?? null) ? '('.$this->translator->trans('export.filter.course.by_social_action.date ignored').')' : $this->rollingDateConverter->convert($data['end_date_after'])->format('d-m-Y'), + '%end_date_before%' => null === ($data['end_date_before'] ?? null) ? '('.$this->translator->trans('export.filter.course.by_social_action.date ignored').')' : $this->rollingDateConverter->convert($data['end_date_before'])->format('d-m-Y'), ]]; } public function getTitle(): string { - return 'Filter by socialaction'; + return 'export.filter.course.by_social_action.title'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWorkTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWorkTest.php new file mode 100644 index 000000000..04d2debe5 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWorkTest.php @@ -0,0 +1,50 @@ +get(EntityManagerInterface::class); + + yield new CountAccompanyingPeriodWorkAssociatePersonOnWork($em, $this->getParameters(true)); + yield new CountAccompanyingPeriodWorkAssociatePersonOnWork($em, $this->getParameters(false)); + } + + public function getFormData() + { + return [[]]; + } + + public function getModifiersCombination() + { + return [ + [Declarations::SOCIAL_WORK_ACTION_TYPE, Declarations::PERSON_TYPE, Declarations::ACP_TYPE], + ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php index 66768d966..65078dad2 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/AccompanyingCourseFilters/SocialActionFilterTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Export\Filter\AccompanyingCourseFilters; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\SocialWork\SocialAction; @@ -50,7 +51,36 @@ final class SocialActionFilterTest extends AbstractFilterTest ->setMaxResults(1) ->getResult(); - yield ['accepted_socialactions' => $array]; + return [ + [ + 'accepted_socialactions' => $array, + 'start_date_after' => null, + 'start_date_before' => null, + 'end_date_after' => null, + 'end_date_before' => null, + ], + [ + 'accepted_socialactions' => $array, + 'start_date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), + 'start_date_before' => new RollingDate(RollingDate::T_TODAY), + 'end_date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), + 'end_date_before' => new RollingDate(RollingDate::T_TODAY), + ], + [ + 'accepted_socialactions' => [], + 'start_date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), + 'start_date_before' => new RollingDate(RollingDate::T_TODAY), + 'end_date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), + 'end_date_before' => new RollingDate(RollingDate::T_TODAY), + ], + [ + 'accepted_socialactions' => [], + 'start_date_after' => null, + 'start_date_before' => null, + 'end_date_after' => null, + 'end_date_before' => null, + ], + ]; } public function getQueryBuilders(): array diff --git a/src/Bundle/ChillPersonBundle/config/services/exports_social_actions.yaml b/src/Bundle/ChillPersonBundle/config/services/exports_social_actions.yaml index 3e6f12fe1..bda76f4a7 100644 --- a/src/Bundle/ChillPersonBundle/config/services/exports_social_actions.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/exports_social_actions.yaml @@ -22,6 +22,10 @@ services: tags: - { name: chill.export, alias: list_social_work_actions_associate_person_work } + Chill\PersonBundle\Export\Export\CountPersonOnAccompanyingPeriodWorkAssociatePersonOnWork: + tags: + - { name: chill.export, alias: count_person_on_acwp_associate_person_work } + Chill\PersonBundle\Export\Export\AvgDurationAPWorkPersonAssociatedOnAccompanyingPeriod: tags: - { name: chill.export, alias: avg_duration_social_work_actions_person_associated_on_period } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 71b428920..d55ccdfaf 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -483,9 +483,6 @@ Select a geographical layer: Choisir une couche géographique Group people by geographical unit based on his address: Grouper les usagers par zone géographique (sur base de l'adresse) Filter by person's geographical unit (based on address): Filtrer les usagers par zone géographique (sur base de l'adresse) -Filter by socialaction: Filtrer les parcours par action d'accompagnement -Accepted socialactions: Actions d'accompagnement -"Filtered by socialactions: only %socialactions%": "Filtré par action d'accompagnement: uniquement %socialactions%" Group by social action: Grouper les parcours par action d'accompagnement Filter by type of action, goals and results: "Filtrer les actions par type, objectif et résultat" @@ -1003,13 +1000,17 @@ export: count_accompanying_period_work_associate_person: title: Nombre d'actions, filtres et regroupements sur les usagers du parcours - description: Compte le nombre d'actions d'accompagnement avec des filtres et regroupements possibles sur les usagers, les parcours et les actions. Les filtres et regroupements agissent sur les usagers concernés par le parcours de l'action. + description: Compte le nombre d'actions d'accompagnement avec des filtres et regroupements possibles sur les usagers, les parcours et les actions. Les filtres et regroupements relatifs aux usagers agissent sur les usagers concernés par le parcours de l'action. header: Nombre d'actions count_accompanying_period_work_associate_work: title: Nombre d'actions, filtres et regroupements sur les usagers de l'action - description: Compte le nombre d'actions d'accompagnement avec des filtres et regroupements possibles sur les usagers, les parcours et les actions. Les filtres et regroupements agissent sur les usagers concernés par l'action. + description: Compte le nombre d'actions d'accompagnement avec des filtres et regroupements possibles sur les usagers, les parcours et les actions. Les filtres et regroupements relatifs aux usagers agissent sur les usagers concernés par l'action. header: Nombre d'actions + count_person_on_acpw_associate_person_on_work: + title: Nombre d'usagers concernés par une action d'accompagnement, filtres et regroupements sur les usagers de l'action + description: Compte le nombre d'usager concernés par une action d'accompagnement, avec des filtres et regroupements possibles sur les usagers, les parcours et les actions. Les filtres et regroupements relatifs aux usagers agissent sur les usagers concernés par l'action. Si un usager est concerné par plusieurs actions, il n'est comptabilisé qu'une fois. + header: Nombre d'usagers concernés par une action avg_duration_acpw_associate_on_period: title: Durée moyenne des actions d'accompagnements, filtres et regroupement sur les usagers du parcours @@ -1180,6 +1181,20 @@ export: by_user_job: Filter by user job: Filtrer les parcours par métier du référent "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" + by_social_action: + title: Filtrer les parcours par action d'accompagnement + Accepted socialactions: Actions d'accompagnement + accepted socialations help: Si laissé vide, tous les types d'action seront pris en compte + "Filtered by socialactions: only %socialactions%": "Filtré par action d'accompagnement: uniquement %socialactions%, date d'ouverture après le %start_date_after%, et avant le %start_date_before%, date de fermeture après le %end_date_after% et avant le %end_date_before%" + start date after: Date de début de l'action après le + start date after help: Sera ignoré si laissé vide + start date before: Date de début de l'action avant le + start date before help: Sera ignoré si laissé vide + end date after: Date de fin de l'action après le + end date after help: Sera ignoré si laissé vide. Les actions sans date de fin seront toujours prises en compte. + end date before: Date de fin de l'action avant le + end date before help: Sera ignoré si laissé vide. Les actions sans date de fin seront toujours prises en compte. + date ignored: clause de date ignorée work: start_between_dates: