From 97846a5877eb4f53fbf942fe475f2c617a863a71 Mon Sep 17 00:00:00 2001 From: Julie Lenaerts Date: Tue, 14 May 2024 11:01:45 +0200 Subject: [PATCH] add basic fields csperson to list person export --- .../Export/AddCSPersonToPersonListHelper.php | 183 +++++ .../src/Export/ListCSPerson.php | 628 ------------------ .../src/Resources/config/services/export.yml | 4 +- 3 files changed, 185 insertions(+), 630 deletions(-) create mode 100644 src/Bundle/ChillJobBundle/src/Export/AddCSPersonToPersonListHelper.php delete mode 100644 src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php diff --git a/src/Bundle/ChillJobBundle/src/Export/AddCSPersonToPersonListHelper.php b/src/Bundle/ChillJobBundle/src/Export/AddCSPersonToPersonListHelper.php new file mode 100644 index 000000000..34f10a1f9 --- /dev/null +++ b/src/Bundle/ChillJobBundle/src/Export/AddCSPersonToPersonListHelper.php @@ -0,0 +1,183 @@ +leftJoin(CSPerson::class, 'cs_person', Query\Expr\Join::WITH, 'cs_person.person = person'); + + foreach (self::CSPERSON_FIELDS as $f) { + switch ($f) { + case 'findernieremploidate': + $qb->addSelect('cs_person.dateFinDernierEmploi AS findernieremploidate'); + + break; + + case 'poleemploiid': + $qb->addSelect('cs_person.poleEmploiId AS poleemploiid'); + + break; + + case 'cafid': + $qb->addSelect('cs_person.cafId AS cafid'); + + break; + + case 'cafinscriptiondate': + $qb->addSelect('cs_person.cafInscriptionDate AS cafinscriptiondate'); + + break; + + case 'contratiejdate': + $qb->addSelect('cs_person.dateContratIEJ AS contratiejdate'); + + break; + + case 'cerinscriptiondate': + $qb->addSelect('cs_person.cERInscriptionDate AS cerinscriptiondate'); + + break; + + case 'ppaeinscriptiondate': + $qb->addSelect('cs_person.pPAEInscriptionDate AS ppaeinscriptiondate'); + + break; + + case 'ppaesignataire': + $qb->addSelect('cs_person.pPAESignataire AS ppaesignataire'); + + break; + + case 'cersignataire': + $qb->addSelect('cs_person.cERSignataire AS cersignataire'); + + break; + + case 'neetcommissiondate': + $qb->addSelect('cs_person.nEETCommissionDate AS neetcommissiondate'); + + break; + + case 'fsemademarchecode': + $qb->addSelect('cs_person.fSEMaDemarcheCode AS fsemademarchecode'); + + break; + + default: + $qb->addSelect(sprintf('person.%s as %s', $f, $f)); + + } + } + } + + public function getLabels(string $key, array $values, array $data): ?callable + { +// dump('im here'); + switch ($key) { + case 'cerinscriptiondate': + case 'ppaeinscriptiondate': + case 'neetcommissiondate': + case 'findernieremploidate': + case 'cafinscriptiondate': + case 'contratiejdate': + return function ($value) use ($key) { + if ('_header' === $value) { + return $this->translator->trans($key); + } + + if (null === $value) { + return ''; + } + // warning: won't work with DateTimeImmutable as we reset time a few lines later + $date = \DateTime::createFromFormat('Y-m-d', $value); + $hasTime = false; + + if (false === $date) { + $date = \DateTime::createFromFormat('Y-m-d H:i:s', $value); + $hasTime = true; + } + + // check that the creation could occur. + if (false === $date) { + throw new \Exception(sprintf('The value %s could not be converted to %s', $value, \DateTime::class)); + } + + if (!$hasTime) { + $date->setTime(0, 0, 0); + } + + return $date; + }; + + default: +/* if (!\in_array($key, $this->getAllKeys(), true)) { + throw new \RuntimeException("this key is not supported by this helper: {$key}"); + }*/ + + // for fields which are associated with person + return function ($value) use ($key) { + if ('_header' === $value) { + return $this->translator->trans($key); + } + + return $value; + }; + } + } +} diff --git a/src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php b/src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php deleted file mode 100644 index a671cf8f2..000000000 --- a/src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php +++ /dev/null @@ -1,628 +0,0 @@ - CSPerson::RESSOURCES, - 'moyen_transport__label' => CSPerson::MOBILITE_MOYEN_TRANSPORT, - 'type_contrat__label' => CSPerson::TYPE_CONTRAT, - 'permis_conduire__label' => CSPerson::PERMIS_CONDUIRE, - 'accompagnement__label' => CSPerson::ACCOMPAGNEMENTS, - 'situation_professionnelle__label' => CSPerson::SITUATION_PROFESSIONNELLE, - 'neet_eligibility__label' => CSPerson::NEET_ELIGIBILITY, - ]; - - protected array $personIds = []; - protected EntityManagerInterface $em; - protected TranslatableStringHelper $translatableStringHelper; - protected CustomFieldProvider $customFieldProvider; - - public function __construct( - protected TranslatorInterface $translator, - EntityManagerInterface $em, - ListPersonHelper $listPersonHelper, - TranslatableStringHelper $translatableStringHelper, - CustomFieldProvider $customFieldProvider, - ParameterBagInterface $parameterBag - ) { - parent::__construct($customFieldProvider, $listPersonHelper, $em, $translatableStringHelper, $parameterBag); - } - - /** - * Rebuild fields array, combining parent ListPerson and ListCSPerson, - * adding query type as value. - * - * @return array - */ - protected function allFields() - { - $fields = [ - 'id' => 'integer', - 'firstName' => 'string', - 'lastName' => 'string', - 'gender' => 'string', - 'birthdate' => 'date', - 'placeOfBirth' => 'string', - 'countryOfBirth' => 'json', - 'nationality' => 'json', - 'email' => 'string', - 'phonenumber' => 'string', - 'mobilenumber' => 'string', - 'contactInfo' => 'string', - 'memo' => 'string', - 'address_valid_from' => 'date', - 'address_street_address_1' => 'string', - 'address_street_address_2' => 'string', - 'address_postcode_code' => 'string', - 'address_postcode_label' => 'string', - 'address_country_name' => 'string', - 'address_country_code' => 'string', - 'address_isnoaddress' => 'boolean', - ]; - - $CSfields = [ - 'recentopeningdate' => 'date', - 'recentclosingdate' => 'date', - 'closingmotive' => 'json', - 'situation_familiale' => 'json', - 'enfantacharge' => 'integer', - 'accompagnement__label' => 'json', - 'findernieremploidate' => 'date', - 'prescripteur__name' => 'string', - 'prescripteur__email' => 'string', - 'prescripteur__phone' => 'string', - 'poleemploiid' => 'string', - 'cafid' => 'string', - 'cafinscriptiondate' => 'date', - 'contratiejdate' => 'date', - 'cerinscriptiondate' => 'date', - 'ppaeinscriptiondate' => 'date', - 'ppaesignataire' => 'string', - 'cersignataire' => 'string', - 'neet_eligibility__label' => 'string', - 'neetcommissiondate' => 'date', - 'fsemademarchecode' => 'string', - 'permis_conduire__label' => 'json', - 'situation_professionnelle__label' => 'string', - 'datefindernieremploi' => 'date', - 'type_contrat__label' => 'json', - 'ressource__label' => 'json', - 'moyen_transport__label' => 'json', - ]; - - return array_merge($fields, $CSfields); - } - - /** - * Return array FIELDS keys only. - * - * @return array - */ - private function getFields() - { - return array_keys($this->allFields()); - } - - /** - * give the list of keys the current export added to the queryBuilder in - * self::initiateQuery. - * - * Example: if your query builder will contains `SELECT count(id) AS count_id ...`, - * this function will return `array('count_id')`. - * - * @param mixed[] $data the data from the export's form (added by self::buildForm) - * - * @return array - */ - public function getQueryKeys($data) - { - $csperson = self::CSPERSON; - - $fields = []; - foreach ($data['fields'] as $key) { - switch ($key) { - case 'ressource__label': - case 'moyen_transport__label': - foreach ($csperson[$key] as $item) { - $this->translationCompatKey($item, $key); - $fields[] = $item; - } - break; - - case 'prescripteur__name': - case 'prescripteur__email': - case 'prescripteur__phone': - $key = str_replace('__', '.', (string) $key); - - // no break - case 'situation_professionnelle__label': - case 'neet_eligibility__label': - case 'accompagnement__label': - case 'permis_conduire__label': - case 'type_contrat__label': - default: - $fields[] = $key; - } - } - - return $fields; - } - - /** - * Some fields values are arrays that have to be splitted in columns. - * This function split theses fields. - * - * @param array $rows - * - * @return array|\Closure - */ - private function splitArrayToColumns($rows) - { - $csperson = self::CSPERSON; - - $results = []; - foreach ($rows as $row) { - $res = []; - foreach ($row as $key => $value) { - switch ($key) { - case 'ressource__label': - case 'moyen_transport__label': - foreach ($csperson[$key] as $item) { - $this->translationCompatKey($item, $key); - if ((null === $value) || (0 === count($value))) { - $res[$item] = ''; - } else { - foreach ($value as $v) { - $this->translationCompatKey($v, $key); - - if ($item === $v) { - $res[$item] = 'x'; - break; - } - $res[$item] = ''; - } - } - } - break; - - case 'situation_professionnelle__label': - $f = false; - if ('en_activite' === $value) { - $f = true; - } - $res[$key] = $value; - break; - - case 'type_contrat__label': - if ('' !== $value) { - $res[$key] = ($f) ? $value : null; - } else { - $res[$key] = null; - } - break; - - case 'prescripteur__name': - case 'prescripteur__email': - case 'prescripteur__phone': - $key = str_replace('__', '.', (string) $key); - - // no break - case 'neet_eligibility__label': - case 'accompagnement__label': - case 'permis_conduire__label': - default: - $res[$key] = $value; - } - } - $results[] = $res; - } - - return $results; - } - - /** - * Make item compatible with YAML messages ids - * for fields that are splitted in columns (with field key to replace). - * - * AVANT - * key: projet_prof__volume_horaire__label - * item: temps_plein - * APRES - * item: projet_prof.volume_horaire.temps_plein - * - * @param string $item (&) passed by reference - * @param string $key - */ - private function translationCompatKey(&$item, $key) - { - $key = str_replace('label', $item, $key); - $key = str_replace('__', '.', $key); - $item = $key; - } - - public function buildForm(FormBuilderInterface $builder) - { - parent::buildForm($builder); // ajouter un '?' dans la query - - $choices = array_combine($this->getFields(), $this->getFields()); - - $builder->add('fields', ChoiceType::class, [ - 'multiple' => true, - 'expanded' => true, - 'choices' => $choices, - 'data' => $choices, - // les checkbox cochés !! -// 'choices_as_values' => true, - 'label' => 'Fields to include in export', - 'choice_label' => fn ($key) => str_replace('__', '.', (string) $key), - 'choice_attr' => function ($val) { - if (str_starts_with($val, 'address_')) { - return ['data-display-target' => 'address_date']; - } - - return []; - }, - 'constraints' => [new Callback(['callback' => function ($selected, ExecutionContextInterface $context) { - if (0 === count($selected)) { - $context->buildViolation('You must select at least one element') - ->atPath('fields') - ->addViolation(); - } - }])], - ]); - } - - /** - * @return \Doctrine\ORM\NativeQuery|\Doctrine\ORM\QueryBuilder - * - * @throws \Doctrine\DBAL\Exception\InvalidArgumentException - */ - public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) - { - $centers = array_map(fn ($el) => $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'); - } - - return $this->entityManager->createQueryBuilder() - ->from('ChillPersonBundle:Person', 'person') - ->join('person.center', 'center') - ->andWhere('center IN (:authorized_centers)') - ->setParameter('authorized_centers', $centers) - ; - } - - /** - * @param \Doctrine\ORM\NativeQuery|\Doctrine\ORM\QueryBuilder $qb - * @param mixed[] $data - */ - public function getResult($qb, $data) - { - $qb->select('person.id'); - - $ids = $qb->getQuery()->getResult(Query::HYDRATE_SCALAR); - $this->personIds = array_map(fn ($e) => $e['id'], $ids); - - $personIdsParameters = '?'.\str_repeat(', ?', count($this->personIds) - 1); - $query = \str_replace('%person_ids%', $personIdsParameters, self::QUERY); - - $rsm = new Query\ResultSetMapping(); - - foreach ($this->allFields() as $name => $type) { - if (null !== $data['fields'][$name]) { - $rsm->addScalarResult(strtolower($name), $name, $type); - } - } - - $nq = $this->entityManager->createNativeQuery($query, $rsm); - - $idx = 0; - for ($i = 1; $i <= 8; ++$i) { - ++$idx; - $nq->setParameter($idx, $data['address_date'], 'date'); - } - for ($i = 1; $i <= count($this->personIds); ++$i) { - ++$idx; - $nq->setParameter($idx, $this->personIds[$i - 1]); - } - - return $this->splitArrayToColumns( - $nq->getResult() - ); - } - - /** - * @param string $key The column key, as added in the query - * @param mixed[] $values The values from the result. if there are duplicates, those might be given twice. Example: array('FR', 'BE', 'CZ', 'FR', 'BE', 'FR') - * @param mixed $data The data from the export's form (as defined in `buildForm` - */ - public function getLabels($key, array $values, $data) - { - $csperson = self::CSPERSON; - - return match ($key) { - 'countryOfBirth', 'situation_familiale', 'closingmotive', 'nationality' => function ($value) use ($key) { - if ('_header' === $value) { - return $key; - } - - return $value['fr']; - }, - 'accompagnement__label', 'permis_conduire__label', 'type_contrat__label' => function ($value) use ($key) { - if ('_header' === $value) { - return $this->translator->trans( - str_replace('__', '.', $key) - ); - } - if ('' === $value) { - return ''; - } - $arr = []; - foreach ($value as $v) { - $this->translationCompatKey($v, $key); - $arr[] = $this->translator->trans($v); - } - - return implode(', ', $arr); - }, - 'situation_professionnelle__label', 'neet_eligibility__label' => function ($value) use ($key) { - if ('_header' === $value) { - return $this->translator->trans( - str_replace('__', '.', $key) - ); - } - if ('' === $value) { - return ''; - } - $this->translationCompatKey($value, $key); - - return $this->translator->trans($value); - }, - 'birthdate', 'address_valid_from', 'recentopeningdate', 'recentclosingdate', 'findernieremploidate', 'cafinscriptiondate', 'contratiejdate', 'cerinscriptiondate', 'ppaeinscriptiondate', 'neetcommissiondate', 'datefindernieremploi' => function ($value) use ($key) { - if ('_header' === $value) { - return $key; - } - if ('' === $value) { - return ''; - } - - return $value->format('d-m-Y'); - }, - 'gender' => function ($value) { - if ('_header' === $value) { - return 'gender'; - } - - return $this->translator->trans($value); - }, - 'address_country_name' => function ($value) use ($key) { - if ('_header' === $value) { - return \strtolower($key); - } - if (null === $value) { - return ''; - } - - return $this->translatableStringHelper->localize(json_decode($value, true)); - }, - 'address_isnoaddress' => parent::getLabels($key, $values, $data), - default => function ($value) use ($key) { - if ('_header' === $value) { - return $key; - } - if ('' === $value) { - return ''; - } - - return $value; - }, - }; - } - - /** - * Native Query SQL. - */ - public const QUERY = <<<'SQL' - -WITH accompagning AS ( - - SELECT * - FROM ( - - SELECT - p.id, - ac.openingdate, - - rank() OVER ( - PARTITION BY p.id - ORDER BY ac.openingdate DESC - ) openingrank, - - ac.closingdate, - - rank() OVER ( - PARTITION BY p.id - ORDER BY ac.closingdate DESC - ) closingrank, - - ( CASE - WHEN ac.closingdate IS NULL - THEN NULL - ELSE cm.name - END ) as closingmotive - - FROM public.chill_person_person AS p - - LEFT OUTER JOIN public.chill_person_accompanying_period AS ac - ON p.id = ac.person_id - - LEFT OUTER JOIN public.chill_person_closingmotive AS cm - ON ac.closingmotive_id = cm.id - - ) AS sq - - WHERE sq.openingrank = 1 - OR sq.closingrank = 1 -) -SELECT --- identifiant - p.id as id, --- ** - p.firstname as firstName, --- ** - p.lastname as lastName, --- genre - p.gender as gender, --- date de naissance - p.birthdate as birthdate, --- ** - p.place_of_birth as placeOfBirth, --- ** - cnb.name as countryOfBirth, --- nationalité - cnn.name as nationality, --- Courriel - p.email as email, --- numéro de téléphone - p.phonenumber as phonenumber, --- numéro de téléphone portable - p.mobilenumber as mobilenumber, --- ** - p.contactInfo as contactInfo, --- memo - p.memo as memo, - --- Date de début de validité de l'adresse - get_last_address_validfrom(p.id, ?::date) as address_valid_from, --- Adresse SDF - get_last_address_isnoaddress(p.id, ?::date) as address_isnoaddress, --- Adresse ligne 1 - get_last_address_streetaddress1(p.id, ?::date) as address_street_address_1, --- Adresse ligne 2 - get_last_address_streetaddress2(p.id, ?::date) as address_street_address_2, --- Code postal - get_last_address_postcode_code(p.id, ?::date) as address_postcode_code, --- Commune - get_last_address_postcode_label(p.id, ?::date) as address_postcode_label, --- Code pays - get_last_address_country_code(p.id, ?::date) as address_country_code, --- Pays - get_last_address_country_name(p.id, ?::date) as address_country_name, - --- date d’ouverture du dossier la plus récente - ac.openingdate as recentopeningdate, --- date de fermeture du dossier la plus récente - ac.closingdate as recentclosingdate, --- motif de cloture - ac.closingmotive as closingmotive, - --- Situation familiale - ms.name as situation_familiale, --- Enfants à charge - cs.enfantacharge as enfantacharge, --- Date de fin du dernier emploi - cs.datefindernieremploi as findernieremploidate, --- Accompagnement - cs.accompagnement as accompagnement__label, --- Prescripteur - tpp.name as prescripteur__name, --- Email prescripteur - tpp.email as prescripteur__email, --- Téléphone prescripteur - tpp.telephone as prescripteur__phone, --- Identifiant pôle emploi - cs.poleemploiid as poleemploiid, --- Numéro allocataire CAF - cs.cafid as cafid, --- Date de l’inscription CAF - cs.cafinscriptiondate as cafinscriptiondate, --- Date de l’avenant du contrat - cs.datecontratiej as contratiejdate, --- Date de l’inscription CER - cs.cerinscriptiondate as cerinscriptiondate, --- Date de l’inscription PPAE - cs.ppaeinscriptiondate as ppaeinscriptiondate, --- Signataire PPAE - cs.ppaesignataire as ppaesignataire, --- Signataire CER - cs.cersignataire as cersignataire, --- Éligibilité NEET - cs.neeteligibilite as neet_eligibility__label, --- Date de commission NEET - cs.neetcommissiondate as neetcommissiondate, --- Code démarche FSE - cs.fsemademarchecode as fsemademarchecode, --- Permis de conduire - cs.permisconduire as permis_conduire__label, --- Situation professionnelle - cs.situationprofessionnelle as situation_professionnelle__label, --- Type de contrat - cs.typecontrat as type_contrat__label, --- Salaire(s), ARE, ASS, RSA, AAH, Autre - cs.ressources as ressource__label, --- Transport en commun, Scooter, Vélo, Voiture, Autre - cs.mobilitemoyentransport as moyen_transport__label - -FROM public.chill_person_person AS p - - LEFT JOIN chill_job.cs_person AS cs - ON p.id = cs.person_id - LEFT JOIN chill_3party.third_party AS tpp - ON cs.prescripteur_id = tpp.id - LEFT JOIN public.chill_person_marital_status AS ms - ON p.maritalstatus_id = ms.id - - LEFT JOIN public.country AS cnb - ON p.countryofbirth_id = cnb.id - LEFT JOIN public.country AS cnn - ON p.nationality_id = cnn.id - - LEFT JOIN accompagning AS ac - ON p.id = ac.id - -WHERE - p.id IN (%person_ids%) - -ORDER BY p.id ASC - -SQL; - - public function validateForm(mixed $data, ExecutionContextInterface $context) - { - // TODO: Implement validateForm() method. - } -} diff --git a/src/Bundle/ChillJobBundle/src/Resources/config/services/export.yml b/src/Bundle/ChillJobBundle/src/Resources/config/services/export.yml index 08bacf6ae..3d9c67261 100644 --- a/src/Bundle/ChillJobBundle/src/Resources/config/services/export.yml +++ b/src/Bundle/ChillJobBundle/src/Resources/config/services/export.yml @@ -3,9 +3,9 @@ services: autowire: true autoconfigure: true - Chill\JobBundle\Export\ListCSPerson: + Chill\JobBundle\Export\AddCSPersonToPersonListHelper: tags: - - { name: chill.export, alias: list_CSPerson } + - { name: chill_person.list_person_customizer } Chill\JobBundle\Export\ListCV: tags: