From d75ec92417d0f82b12aae3e8a33f9244326638ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 26 Oct 2022 14:59:06 +0200 Subject: [PATCH] Feature: [export] add a list of people having an accompanying period --- .../ListPersonWithAccompanyingPeriod.php | 218 ++++++++++++++++++ .../config/services/exports_person.yaml | 9 +- .../translations/messages.fr.yml | 5 +- 3 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriod.php diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriod.php new file mode 100644 index 000000000..ce97ce662 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPersonWithAccompanyingPeriod.php @@ -0,0 +1,218 @@ +addressHelper = $addressHelper; + $this->listPersonHelper = $listPersonHelper; + $this->entityManager = $em; + } + + public function buildForm(FormBuilderInterface $builder) + { + $choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS); + + // Add a checkbox to select fields + $builder->add('fields', ChoiceType::class, [ + 'multiple' => true, + 'expanded' => true, + 'choices' => $choices, + 'label' => 'Fields to include in export', + 'choice_attr' => static function (string $val): array { + // add a 'data-display-target' for address fields + if (substr($val, 0, 7) === 'address' || 'center' === $val || 'household' === $val) { + return ['data-display-target' => 'address_date']; + } + + return []; + }, + 'constraints' => [new Callback([ + 'callback' => static function ($selected, ExecutionContextInterface $context) { + if (count($selected) === 0) { + $context->buildViolation('You must select at least one element') + ->atPath('fields') + ->addViolation(); + } + }, + ])], + 'data' => array_values($choices), + ]); + + // add a date field for addresses + $builder->add('address_date', ChillDateType::class, [ + 'label' => 'Data valid at this date', + 'help' => 'Data regarding center, addresses, and so on will be computed at this date', + 'data' => new DateTimeImmutable(), + 'input' => 'datetime_immutable', + ]); + } + + public function getAllowedFormattersTypes() + { + return [FormatterInterface::TYPE_LIST]; + } + + public function getDescription() + { + return 'export.list.person_with_acp.Create a list of people having an accompaying periods, according to various filters.'; + } + + public function getGroup(): string + { + return 'Exports of persons'; + } + + public function getLabels($key, array $values, $data) + { + return $this->listPersonHelper->getLabels($key, $values, $data); + } + + public function getQueryKeys($data) + { + $fields = []; + + foreach (ListPersonHelper::FIELDS as $key) { + if (!in_array($key, $data['fields'], true)) { + continue; + } + + if (substr($key, 0, strlen('address_fields')) === 'address_fields') { + $fields = array_merge($fields, $this->addressHelper->getKeys(ListPersonHelper::HELPER_ATTRIBUTES, 'address_fields')); + + continue; + } + + if ('lifecycleUpdate' === $key) { + $fields = array_merge($fields, ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']); + + continue; + } + + $fields[] = $key; + } + + return $fields; + } + + public function getResult($query, $data) + { + return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR); + } + + public function getTitle() + { + return 'export.list.person_with_acp.List peoples having an accompanying period'; + } + + public function getType() + { + return Declarations::PERSON_TYPE; + } + + /** + * @param array{fields: string[], address_date: DateTimeImmutable} $data + */ + public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) + { + $centers = array_map(static function ($el) { + return $el['center']; + }, $acl); + + // throw an error if any fields are present + if (!array_key_exists('fields', $data)) { + throw new \Doctrine\DBAL\Exception\InvalidArgumentException('any fields ' + . 'have been checked'); + } + + $qb = $this->entityManager->createQueryBuilder(); + + $qb->from(Person::class, 'person') + ->join('person.accompanyingPeriodParticipations', 'acppart') + ->join('acppart.accompanyingPeriod', 'acp') + ->andWhere( + $qb->expr()->exists( + 'SELECT 1 FROM ' . PersonCenterHistory::class . ' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)' + ) + )->setParameter('authorized_centers', $centers); + + $fields = $data['fields']; + + $this->listPersonHelper->addSelect($qb, $fields, $data['address_date']); + + return $qb; + } + + public function requiredRole(): string + { + return PersonVoter::LISTS; + } + + public function supportsModifiers() + { + return [Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN, Declarations::ACP_TYPE]; + } + + public function validateForm($data, ExecutionContextInterface $context) + { + // get the field starting with address_ + $addressFields = array_filter( + ListPersonHelper::FIELDS, + static fn (string $el): bool => substr($el, 0, 8) === 'address_' + ); + + // check if there is one field starting with address in data + if (count(array_intersect($data['fields'], $addressFields)) > 0) { + // if a field address is checked, the date must not be empty + if (!$data['address_date'] instanceof DateTimeImmutable) { + $context + ->buildViolation('You must set this date if an address is checked') + ->atPath('address_date') + ->addViolation(); + } + } + } +} diff --git a/src/Bundle/ChillPersonBundle/config/services/exports_person.yaml b/src/Bundle/ChillPersonBundle/config/services/exports_person.yaml index ffffaf175..b9030ec62 100644 --- a/src/Bundle/ChillPersonBundle/config/services/exports_person.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/exports_person.yaml @@ -15,13 +15,18 @@ services: tags: - { name: chill.export, alias: count_person_with_accompanying_course } - chill.person.export.list_person: - class: Chill\PersonBundle\Export\Export\ListPerson + Chill\PersonBundle\Export\Export\ListPerson: autowire: true autoconfigure: true tags: - { name: chill.export, alias: list_person } + Chill\PersonBundle\Export\Export\ListPersonWithAccompanyingPeriod: + autowire: true + autoconfigure: true + tags: + - { name: chill.export, alias: list_person_with_acp } + chill.person.export.list_person.duplicate: class: Chill\PersonBundle\Export\Export\ListPersonDuplicate arguments: diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 0b71d9698..5f43608ce 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1019,8 +1019,9 @@ export: Computation date for referrer: Date à laquelle le référent était actif by_referrer: Computation date for referrer: Date à laquelle le référent était actif - lists: - + list: + person_with_acp.List peoples having an accompanying period: Liste des personnes ayant un parcours d'accompagnement + Create a list of people having an accompaying periods, according to various filters.: Génère une liste des personnes ayant un parcours d'accompagnement, selon différents critères liés au parcours ou à l'usager social_action: and children: et dérivés