Commit 8da9a18e authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Admission : nouveau format de fichier unique CSV des futurs...

Admission : nouveau format de fichier unique CSV des futurs doctorants/apprenants (importable par Pégase).
parent e07e47fd
Loading
Loading
Loading
Loading
+1 −0
Changes for CHANGELOG.md: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ Journal des modifications

13.1.0
------
- Admission : nouveau format de fichier unique CSV des futurs doctorants/apprenants (importable par Pégase).
- Association d'individu à un membre de jury : si un acteur existe déjà avec le même individu et le même rôle pas besoin d'en créer un nouveau.
- [FIX] Plantage lors de la suppression d'un dossier d'admission : toutes les données liées n'étaient pas supprimées correctement au préalable.
- [FIX] Plantage lors de la suppression d'une association d'individu à un membre de jury en l'absence de directeur de thèse.
+3 −3
Changes for composer.lock: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -13185,11 +13185,11 @@
        },
        {
            "name": "unicaen/search",
            "version": "1.1.1",
            "version": "1.1.2",
            "source": {
                "type": "git",
                "url": "https://git.unicaen.fr/lib/unicaen/search.git",
                "reference": "abfc8a3feadd0fa128645d616225be9381626cd7"
                "reference": "035be22cecb2e82ed457ba634a710bccb62d2001"
            },
            "require": {
                "doctrine/doctrine-orm-module": "^5.3 || ^6.0",
@@ -13216,7 +13216,7 @@
                ]
            },
            "description": "Module Unicaen proposant la création de pages de recherche en BDD et de filtres normalisés",
            "time": "2026-03-01T08:56:04+00:00"
            "time": "2026-07-16T09:07:14+00:00"
        },
        {
            "name": "unicaen/shell",
+7 −25
Changes for module/Admission/src/Admission/Controller/AdmissionController.php: 7 added lines, 25 removed lines.
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ use Notification\Service\NotifierServiceAwareTrait;
use RuntimeException;
use Structure\Service\Etablissement\EtablissementServiceAwareTrait;
use UnicaenApp\Service\EntityManagerAwareTrait;
use UnicaenApp\View\Model\CsvModel;
use UnicaenMultipageForm\Form\Fieldset\MultipageFormNavFieldset;
use UnicaenMultipageForm\Manager\Manager as MultipageFormManager;
use UnicaenMultipageForm\Manager\Result;
@@ -997,7 +998,7 @@ class AdmissionController extends AdmissionAbstractController
        return $navigationElement;
    }

    public function genererExportCsvAction(): HttpResponse|JsonModel
    public function genererExportCsvAction(): HttpResponse|CsvModel
    {
        $queryParams = $this->params()->fromQuery();

@@ -1016,7 +1017,9 @@ class AdmissionController extends AdmissionAbstractController
        }

        $this->admissionRechercheService->init();
        if($queryParams) $this->admissionRechercheService->processQueryParams($queryParams);
        if ($queryParams) {
            $this->admissionRechercheService->processQueryParams($queryParams);
        }
        $qb = $this->admissionRechercheService->getQueryBuilder();
        $qb
            ->andWhere($qb->expr()->orX('admission.etat = :etat'))
@@ -1026,31 +1029,10 @@ class AdmissionController extends AdmissionAbstractController
            ->andWhere('d.id IS NULL');
        $listing = $qb->getQuery()->getResult();

        //Génération des CSV
        $admisCSV = $this->admissionExporter->exportAdmisCSV($listing);
        $admissionsCSV = $this->admissionExporter->exportAdmissionsCSV($listing);

        //Création du fichier ZIP
        $zipFilename = tempnam(sys_get_temp_dir(), 'export_') . '.zip';
        $filenameZIP = (new DateTime())->format('Ymd') . '_export_module_admissions.zip';

        try{
            $this->admissionExporter->exportToZip([$admisCSV, $admissionsCSV], $zipFilename);
        }catch (Exception $e){
            throw new RuntimeException("Un problème est survenu lors de la génération du ZIP",0,$e);
        }

        $response = $this->getResponse();
        $response->getHeaders()->addHeaders([
            'Content-Type' => 'application/zip',
            'Content-Disposition' => 'attachment; filename="'.$filenameZIP.'"',
            'Content-Length' => filesize($zipFilename)
        ]);
        $response->setContent(file_get_contents($zipFilename));

        unlink($zipFilename);
        $admisCSV->setFilename(sprintf('sygal_admis_%s.csv', date_create()->format('Ymd_His')));

        return $response;
        return $admisCSV;
    }

    /** TEMPLATES RENDERER *******************************************************************************/
+118 −91
Changes for module/Admission/src/Admission/Service/Exporter/Admission/AdmissionExporter.php: 118 added lines, 91 removed lines.
Original line number Diff line number Diff line
@@ -6,82 +6,105 @@ use Admission\Entity\Db\Admission;
use Admission\Entity\Db\Etudiant;
use Admission\Entity\Db\Transmission;
use Admission\Service\Transmission\TransmissionServiceAwareTrait;
use DateTime;
use RuntimeException;
use UnicaenApp\View\Model\CsvModel;
use ZipArchive;

class AdmissionExporter{

    use TransmissionServiceAwareTrait;
    public function exportToZip(array $csvs, string $zipFilename): ZipArchive
    {
        // Création de l'archive ZIP
        $zip = new ZipArchive();

        foreach ($csvs as $csv) {
            if ($zip->open($zipFilename, ZipArchive::CREATE) !== TRUE) throw new RuntimeException('Impossible de créer le fichier ZIP');

            // Ajout du fichier CSV à l'archive
            if(!$csv instanceof CsvModel)  throw new RuntimeException("Le fichier donné n'est pas au format attendu : CSV");

            $tempCSV = $this->generateCsvContent($csv);
            if(!$tempCSV) throw new RuntimeException("Le contenu du CSV n'a pas pu être récupéré");

            $zip->addFromString($csv->getFilename(), $tempCSV);

            $zip->close();
        }
        return $zip;
    }

    private function generateCsvContent(CsvModel $csvModel): bool|string
class AdmissionExporter
{
        $output = fopen('php://memory', 'r+');
        $delimiter = $csvModel->getDelimiter();
        $enclosure = $csvModel->getEnclosure();

        if ($headers = $csvModel->getHeader()) {
            fputcsv($output, $headers, $delimiter, $enclosure);
        }

        foreach ($csvModel->getData() as $record) {
            fputcsv($output, $record, $delimiter, $enclosure);
        }

        rewind($output);
        $content = stream_get_contents($output);
        fclose($output);
    use TransmissionServiceAwareTrait;

        return $content;
    }
    private const origine_admission1 = 'ED';
    private const code_regime_inscription1 = 'REG006';

    public function exportAdmisCSV($admissions): CsvModel
    /**
     * @param Admission[] $admissions
     */
    public function exportAdmisCSV(array $admissions): CsvModel
    {
        //export
        $headers = ['numero_candidat', 'sexe', 'nom_famille', 'nom_usuel', 'prenom', 'prenom2', 'prenom3',	'date_naissance', 'code_commune_naissance',
            'libellé_commune_naissance', 'code_pays_naissance',	'code_nationalite',	'ine', 'adresse_code_pays',	'adresse_ligne1_etage',
            'adresse_ligne2_batiment',	'adresse_ligne3_voie',	'adresse_ligne4_complement', 'adresse_code_postal',	'adresse_code_commune',
            'adresse_cp_ville_etranger', 'numero_telephone1', 'numero_telephone2', 'courriel'
        $headers = [
            'sexe',
            'nom_naissance',
            'nom_usage',
            'prenom',
            'prenom2',
            'prenom3',
            'date_naissance',
            'code_commune_naissance',
            'libelle_commune_naissance_etranger',
            'code_pays_naissance',
            'code_nationalite',
            'ine',
            'adresse_code_pays',
            'adresse_ligne1_etage',
            'adresse_ligne2_batiment',
            'adresse_ligne3_voie',
            'adresse_ligne4_complement',
            'adresse_ligne5_etranger',
            'adresse_code_postal',
            'adresse_code_commune',
            'numero_telephone1',
            'numero_telephone2',
            'mail',
            //
            'origine_admission1',
            'code_voeu1',
            'code_periode1',
            'annee_concours1',
            'code_regime_inscription1',
            'code_profil_specifique1',
            'code_cursus_amenage_sise1',
            'origine_admission2',
            'annee_concours2',
            'code_voeu2',
            'code_periode2',
            'code_regime_inscription2',
            'code_profil_specifique2',
            'code_cursus_amenage_sise2',
            'origine_admission3',
            'annee_concours3',
            'code_voeu3',
            'code_periode3',
            'code_regime_inscription3',
            'code_profil_specifique3',
            'code_cursus_amenage_sise3',
            'origine_admission4',
            'annee_concours4',
            'code_voeu4',
            'code_periode4',
            'code_regime_inscription4',
            'code_profil_specifique4',
            'code_cursus_amenage_sise4',
            'origine_admission5',
            'annee_concours5',
            'code_voeu5',
            'code_periode5',
            'code_regime_inscription5',
            'code_profil_specifique5',
            'code_cursus_amenage_sise5',
        ];

        $records = [];
        /** @var Admission $admission */

        foreach ($admissions as $admission) {
            $entry = [];
            /** @var Transmission $transmission */
            $transmission = $this->transmissionService->getRepository()->findOneBy(["admission" => $admission]);

            /** @var Etudiant $etudiant */
            $etudiant = $admission->getEtudiant()->first();
            if ($sexe = $admission->getIndividu()->getCivilite()) {
                $sexe = rtrim($sexe, '.') === "M" ? "M" : "F";
            }

            $entry = [];

            $entry['sexe'] = $sexe;
            $entry['nom_famille'] = $etudiant->getNomFamille();
            $entry['nom_usuel'] = $etudiant->getNomUsuel();
            $entry['nom_naissance'] = $etudiant->getNomFamille();
            $entry['nom_usage'] = $etudiant->getNomUsuel();
            $entry['prenom'] = $etudiant->getPrenom();
            $entry['prenom2'] = $etudiant->getPrenom2();
            $entry['prenom3'] = $etudiant->getPrenom3();
            $entry['date_naissance'] = $etudiant->getDateNaissanceFormat();
            $entry['code_commune_naissance'] = $etudiant->getCodeCommuneNaissance();
            $entry['libellé_commune_naissance'] = $etudiant->getLibelleCommuneNaissance();
            $entry['libelle_commune_naissance_etranger'] = null;
            $entry['code_pays_naissance'] = $etudiant->getPaysNaissance() ? $etudiant->getPaysNaissance()->getCodePaysApogee() : null;
            $entry['code_nationalite'] = $etudiant->getNationalite() ? $etudiant->getNationalite()->getCodePaysApogee() : null;
            $entry['ine'] = $etudiant->getIne();
@@ -90,53 +113,57 @@ class AdmissionExporter{
            $entry['adresse_ligne2_batiment'] = $etudiant->getAdresseLigne2Batiment();
            $entry['adresse_ligne3_voie'] = $etudiant->getAdresseLigne3voie();
            $entry['adresse_ligne4_complement'] = $etudiant->getAdresseLigne4Complement();
            $entry['adresse_ligne5_etranger'] = null;
            $entry['adresse_code_postal'] = $etudiant->getAdresseCodePostal();
            $entry['adresse_code_commune'] = $etudiant->getAdresseCodeCommune();
            $entry['adresse_cp_ville_etranger'] = $etudiant->getAdresseCpVilleEtrangere();
            $entry['numero_telephone1'] = (string)$etudiant->getNumeroTelephone1();
            $entry['numero_telephone2'] = (string)$etudiant->getNumeroTelephone2();
            $entry['courriel'] = $etudiant->getCourriel();
            $records[] = $entry;
        }
        $filename = (new DateTime())->format('Ymd') . '_admis.csv';
        $CSV = new CsvModel();
        $CSV->setDelimiter(';');
        $CSV->setEnclosure('"');
        $CSV->setHeader($headers);
        $CSV->setData($records);
        $CSV->setFilename($filename);
            $entry['mail'] = $etudiant->getCourriel();
            //
            $entry['origine_admission1'] = self::origine_admission1;
            $entry['code_voeu1'] = $transmission?->getCodeVoeu();
            $entry['code_periode1'] = $transmission?->getCodePeriode();
            $entry['annee_concours1'] = null;
            $entry['code_regime_inscription1'] = self::code_regime_inscription1;
            $entry['code_profil_specifique1'] = null;
            $entry['code_cursus_amenage_sise1'] = null;
            $entry['origine_admission2'] = null;
            $entry['annee_concours2'] = null;
            $entry['code_voeu2'] = null;
            $entry['code_periode2'] = null;
            $entry['code_regime_inscription2'] = null;
            $entry['code_profil_specifique2'] = null;
            $entry['code_cursus_amenage_sise2'] = null;
            $entry['origine_admission3'] = null;
            $entry['annee_concours3'] = null;
            $entry['code_voeu3'] = null;
            $entry['code_periode3'] = null;
            $entry['code_regime_inscription3'] = null;
            $entry['code_profil_specifique3'] = null;
            $entry['code_cursus_amenage_sise3'] = null;
            $entry['origine_admission4'] = null;
            $entry['annee_concours4'] = null;
            $entry['code_voeu4'] = null;
            $entry['code_periode4'] = null;
            $entry['code_regime_inscription4'] = null;
            $entry['code_profil_specifique4'] = null;
            $entry['code_cursus_amenage_sise4'] = null;
            $entry['origine_admission5'] = null;
            $entry['annee_concours5'] = null;
            $entry['code_voeu5'] = null;
            $entry['code_periode5'] = null;
            $entry['code_regime_inscription5'] = null;
            $entry['code_profil_specifique5'] = null;
            $entry['code_cursus_amenage_sise5'] = null;

        return $CSV;
    }

    public function exportAdmissionsCSV($admissions): CsvModel
    {
        //export
        $headers = ['numero_candidat', 'origine_admission', 'voie_admission', 'annee_concours', 'code_voeu', 'code_periode', 'code_sise', 'code_formation_psup', 'code_etablissement_affectation'];
        $records = [];
        /** @var Admission $admission */
        foreach ($admissions as $admission) {
            /** @var Transmission $transmission */
            $transmission = $this->transmissionService->getRepository()->findOneBy(["admission" => $admission]);

            $entry = [];
            $entry['origine_admission'] = "CO";
            $entry['voie_admission'] = "D";
            $entry['annee_concours'] = null;
            $entry['code_voeu'] = $transmission?->getCodeVoeu();
            $entry['code_periode'] = $transmission?->getCodePeriode();
            $entry['code_sise'] = null;
            $entry['code_formation_psup'] = null;
            $entry['code_etablissement_affectation'] = null;
            $records[] = $entry;
        }
        $filename = (new DateTime())->format('Ymd') . '_admissions.csv';

        $CSV = new CsvModel();
        $CSV->setDelimiter(';');
        $CSV->setEnclosure('"');
        $CSV->setHeader($headers);
        $CSV->setData($records);
        $CSV->setFilename($filename);

        return $CSV;
    }