Loading data/ddl/view/V_EXPORT_PAIEMENT_WINPAIE.sql +2 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,9 @@ FROM (SELECT i.annee_id t2.periode_paiement_id periode_id, i.id intervenant_id, CASE WHEN i.numero_insee IS NULL THEN '''' || TRIM(d.numero_insee) WHEN i.numero_insee IS NULL THEN '''' || TRIM(d.numero_insee) || TRIM(numero_pec) ELSE '''' || TRIM(i.numero_insee) '''' || TRIM(i.numero_insee) || TRIM(numero_pec) END insee, i.nom_usuel || ',' || i.prenom nom, t2.code_origine code_origine, Loading front/Paiement/ImportNumeroPec.vue 0 → 100644 +129 −0 Original line number Diff line number Diff line <template> <div class=" card text-dark bg-light"> <div class="card-header text-uppercase fw-bold"> Importation des numéros de prise en charge </div> <div class="card-body"> <form id="formImport" action="" enctype="multipart/form-data" method="post"> <p class="fs-9 text"> Vous pouvez utiliser le modèle directement extrait de winpaie ou télécharger le modèle d'import générique en <a href="/modeles/import-numero-pec.xlsx">cliquant ici.</a> </p> <div class="mb-3"> <label class="form-label" for="importFile">Choisissez le fichier à importer :</label> <input class="form-control" name="importFile" type="file" @change="handleFileUpload"> </div> <div class="mb-3"> <label class="form-label" for="modele">Choisissez le modèle d'import :</label> <select id="modeleImport" class="form-select" name="modeleImport"> <option value="winpaie">Winpaie</option> <option value="generic">Generique</option> </select> </div> <div class="mb-3"> <button id="btn-import-inprogress" class="btn btn-primary d-none" disabled type="button"> <span id="spinner" aria-hidden="true" class="spinner-border spinner-border-sm" role="status"></span> Veuillez patienter... </button> <button id="btn-import" class="btn btn-primary" disabled type="button" @click="importFile"> Importer les numéros de prise en charge </button> <!-- <input id="btn-import" class="btn btn-primary" disabled type="submit" value="Importer les numéros de prise en charge">--> </div> </form> </div> </div> <div v-if="this.fileErrors || this.intervenantMissing" id="fileErrors" class="card text-dark bg-light"> <div class="card-header text-uppercase fw-bold"> Rapport de chargement du fichier </div> <div class="card-body"> <div v-if="this.fileErrors.length != 0"> <p>Listes des intervenants du fichier dont le numéro INSEE n'est pas valide : </p> <ul> <li v-for="error in this.fileErrors"> {{}} </li> </ul> </div> <div v-if="this.intervenantMissing.length != 0"> <p>Listes des intervenants présents dans le fichier mais non trouvés dans OSE : </p> <ul> <li v-for="intervenant in this.intervenantMissing"> {{ intervenant }} </li> </ul> </div> </div> </div> </template> <script> import UnicaenVue from "unicaen-vue/js/Client/unicaenVue"; export default { props: { canImportPec: {type: Boolean, required: false}, }, data() { return { selectedFile: null, importUrl: unicaenVue.url('paiement/import-numero-pec'), fileErrors: null, intervenantMissing: null, } }, mounted() { }, methods: { handleFileUpload(event) { this.selectedFile = event.target.files[0]; document.getElementById('btn-import').disabled = false; }, importFile(event) { event.preventDefault(); //On desactive le bouton de soumission let btnImport = document.getElementById('btn-import') let btnImportInProgress = document.getElementById('btn-import-inprogress') btnImportInProgress.classList.remove('d-none'); btnImport.classList.add('d-none'); btnImport.disabled = true; let form = document.getElementById('formImport'); let formData = new FormData(form); unicaenVue.axios.post(this.importUrl, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) .then(response => { let datas = response.data; this.fileErrors = datas.file; this.intervenantMissing = datas.intervenant; btnImport.disabled = false; btnImportInProgress.classList.add('d-none'); btnImport.classList.remove('d-none'); }) .catch(error => { console.error('Error uploading'); }) } } } </script> No newline at end of file module/Paiement/config/paiement.config.php +3 −1 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ return [ 'route' => '/import-numero-pec', 'controller' => Controller\PaiementController::class, 'action' => 'importNumeroPec', 'privileges' => Privileges::MISE_EN_PAIEMENT_EXPORT_PAIE, ], 'pilotage' => [ 'route' => '/pilotage', Loading Loading @@ -256,7 +257,7 @@ return [ ], [ 'controller' => Controller\PaiementController::class, 'action' => ['extractionPaie', 'imputationSiham'], 'action' => ['extractionPaie', 'imputationSiham', 'importNumeroPec'], 'privileges' => [Privileges::MISE_EN_PAIEMENT_EXPORT_PAIE], ], [ Loading @@ -279,6 +280,7 @@ return [ Service\MiseEnPaiementService::class => Service\MiseEnPaiementServiceFactory::class, Service\MiseEnPaiementIntervenantStructureService::class => Service\MiseEnPaiementIntervenantStructureServiceFactory::class, Service\MotifNonPaiementService::class => Service\MotifNonPaiementServiceFactory::class, Service\NumeroPriseEnChargeService::class => Service\NumeroPriseEnChargeServiceFactory::class, Assertion\PaiementAssertion::class => \UnicaenPrivilege\Assertion\AssertionFactory::class, PaiementProcess::class => PaiementProcessFactory::class, ], Loading module/Paiement/src/Controller/PaiementController.php +12 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ use Paiement\Form\Paiement\MiseEnPaiementFormAwareTrait; use Paiement\Form\Paiement\MiseEnPaiementRechercheFormAwareTrait; use Paiement\Service\DotationServiceAwareTrait; use Paiement\Service\MiseEnPaiementServiceAwareTrait; use Paiement\Service\NumeroPriseEnChargeServiceAwareTrait; use Paiement\Service\ServiceAPayerServiceAwareTrait; use Paiement\Service\TypeRessourceServiceAwareTrait; use Referentiel\Entity\Db\ServiceReferentiel; Loading @@ -50,6 +51,7 @@ class PaiementController extends AbstractController use DotationServiceAwareTrait; use WorkflowServiceAwareTrait; use EtatSortieServiceAwareTrait; use NumeroPriseEnChargeServiceAwareTrait; /** * Initialisation des filtres Doctrine pour les historique. Loading Loading @@ -679,7 +681,16 @@ class PaiementController extends AbstractController $this->initFilters(); $title = 'Import des numéros de prise en charge'; return true; if ($this->getRequest()->isPost()) { $files = $this->getRequest()->getFiles()->toArray(); $datas = $this->getRequest()->getPost(); $importFile = $files['importFile']; $serviceNumeroPriseEnCharge = $this->getServiceNumeroPriseEnCharge(); return $serviceNumeroPriseEnCharge->treatImportFile($importFile, $datas['modeleImport']); } return compact('title'); } Loading module/Paiement/src/Service/NumeroPriseEnChargeService.php 0 → 100755 +157 −0 Original line number Diff line number Diff line <?php namespace Paiement\Service; use Application\Entity\Db\Intervenant; use Application\Service\AbstractService; use Unicaen\OpenDocument\Calc\Sheet; use Unicaen\OpenDocument\Document; use UnicaenVue\View\Model\AxiosModel; /** * Description of NumeroPriseEnChargeService * * @author LE COURTES Antony <antony.lecourtes at unicaen.fr> */ class NumeroPriseEnChargeService extends AbstractService { /** * @param array $file * * @return AxiosModel Liste des erreurs rencontrées sous forme json */ public function treatImportFile (array $file, string $model = 'winpaie'): AxiosModel { $errors = []; $nameFile = $file['tmp_name']; $document = new Document(); $document->loadFromFile($nameFile); $sheet = $document->getCalc()->getSheet(0); switch ($model) { case 'winpaie': $datas = $this->winpaieTreatment($sheet); break; default: $datas = $this->genericTreatment($sheet); break; } $errors['file'] = $datas['errors']; //On met à jour les numéros de prise en charge des intervenants $em = $this->getEntityManager(); $em->beginTransaction(); foreach ($datas['result'] as $key => $value) { $intervenant = $em->getRepository(Intervenant::class)->findOneBy(['numeroInsee' => $value['insee'], 'annee' => $this->getServiceContext()->getAnnee()]); if ($intervenant) { $intervenant->setNumeroPec($value['pec']); $intervenant->setSyncPec(0); $em->persist($intervenant); } else { $errors['intervenant'][] = $value['nom'] . " - " . $value['insee']; } } $em->flush(); $em->commit(); return new AxiosModel($errors); } public function winpaieTreatment (Sheet $sheet): array { $lines = []; $errors = []; $colonneNames = [ 'insee' => 1, 'nom' => 2, 'nom de naissance' => 3, 'code poste' => 4, 'libelle poste' => 5, 'code grade' => 6, 'libelle grade' => 7, ]; $maxRow = $sheet->getMaxRow(); for ($rowNum = 2; $rowNum <= $maxRow; $rowNum++) { $cell = $sheet->getCellByCoords($colonneNames['insee'], $rowNum); $colValue = $cell->getContent(); // Expression régulière pour capturer les caractères après le 16ème caractère $regexInsee = '/^(.{16})(.*)$/'; $regexInseeProvisoire = '/^(.{15})(.*)$/'; // Utilisation de preg_match pour appliquer l'expression régulière if (preg_match($regexInsee, $colValue, $matches)) { $insee = str_replace("'", "", $matches[1]); $pec = $matches[2]; //Si je n'ai pas réussi à récupérer le numéro PEC s'est que le numéro insee doit etre provisoire sur 15 carctères if ($pec == '') { if (preg_match($regexInseeProvisoire, $colValue, $matches)) { $insee = str_replace(["'", " "], ["", ""], $matches[1]); $pec = $matches[2]; } else { $inseeFile = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $nomFile = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $errors[] = $nomFile . " - " . $inseeFile; } } $lines[] = [ 'insee' => $insee, 'pec' => $pec, 'nom' => $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(), ]; } else { //On stocke les erreurs dans datas pour afficher les lignes qui n'ont pas pu être traitées. $inseeFile = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $nomFile = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $errors[] = $nomFile . " - " . $inseeFile; } } $datas['result'] = $lines; $datas['errors'] = $errors; return $datas; } public function genericTreatment (Sheet $sheet): array { $lines = []; $errors = []; $colonneNames = [ 'insee' => 1, 'numero pec' => 2, 'nom' => 3, ]; $maxRow = $sheet->getMaxRow(); for ($rowNum = 2; $rowNum <= $maxRow; $rowNum++) { $insee = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $pec = $sheet->getCellByCoords($colonneNames['numero pec'], $rowNum)->getContent(); $nom = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $lines[] = [ 'insee' => $insee, 'pec' => $pec, 'nom' => $nom, ]; } $datas['result'] = $lines; $datas['errors'] = $errors; return $datas; } } No newline at end of file Loading
data/ddl/view/V_EXPORT_PAIEMENT_WINPAIE.sql +2 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,9 @@ FROM (SELECT i.annee_id t2.periode_paiement_id periode_id, i.id intervenant_id, CASE WHEN i.numero_insee IS NULL THEN '''' || TRIM(d.numero_insee) WHEN i.numero_insee IS NULL THEN '''' || TRIM(d.numero_insee) || TRIM(numero_pec) ELSE '''' || TRIM(i.numero_insee) '''' || TRIM(i.numero_insee) || TRIM(numero_pec) END insee, i.nom_usuel || ',' || i.prenom nom, t2.code_origine code_origine, Loading
front/Paiement/ImportNumeroPec.vue 0 → 100644 +129 −0 Original line number Diff line number Diff line <template> <div class=" card text-dark bg-light"> <div class="card-header text-uppercase fw-bold"> Importation des numéros de prise en charge </div> <div class="card-body"> <form id="formImport" action="" enctype="multipart/form-data" method="post"> <p class="fs-9 text"> Vous pouvez utiliser le modèle directement extrait de winpaie ou télécharger le modèle d'import générique en <a href="/modeles/import-numero-pec.xlsx">cliquant ici.</a> </p> <div class="mb-3"> <label class="form-label" for="importFile">Choisissez le fichier à importer :</label> <input class="form-control" name="importFile" type="file" @change="handleFileUpload"> </div> <div class="mb-3"> <label class="form-label" for="modele">Choisissez le modèle d'import :</label> <select id="modeleImport" class="form-select" name="modeleImport"> <option value="winpaie">Winpaie</option> <option value="generic">Generique</option> </select> </div> <div class="mb-3"> <button id="btn-import-inprogress" class="btn btn-primary d-none" disabled type="button"> <span id="spinner" aria-hidden="true" class="spinner-border spinner-border-sm" role="status"></span> Veuillez patienter... </button> <button id="btn-import" class="btn btn-primary" disabled type="button" @click="importFile"> Importer les numéros de prise en charge </button> <!-- <input id="btn-import" class="btn btn-primary" disabled type="submit" value="Importer les numéros de prise en charge">--> </div> </form> </div> </div> <div v-if="this.fileErrors || this.intervenantMissing" id="fileErrors" class="card text-dark bg-light"> <div class="card-header text-uppercase fw-bold"> Rapport de chargement du fichier </div> <div class="card-body"> <div v-if="this.fileErrors.length != 0"> <p>Listes des intervenants du fichier dont le numéro INSEE n'est pas valide : </p> <ul> <li v-for="error in this.fileErrors"> {{}} </li> </ul> </div> <div v-if="this.intervenantMissing.length != 0"> <p>Listes des intervenants présents dans le fichier mais non trouvés dans OSE : </p> <ul> <li v-for="intervenant in this.intervenantMissing"> {{ intervenant }} </li> </ul> </div> </div> </div> </template> <script> import UnicaenVue from "unicaen-vue/js/Client/unicaenVue"; export default { props: { canImportPec: {type: Boolean, required: false}, }, data() { return { selectedFile: null, importUrl: unicaenVue.url('paiement/import-numero-pec'), fileErrors: null, intervenantMissing: null, } }, mounted() { }, methods: { handleFileUpload(event) { this.selectedFile = event.target.files[0]; document.getElementById('btn-import').disabled = false; }, importFile(event) { event.preventDefault(); //On desactive le bouton de soumission let btnImport = document.getElementById('btn-import') let btnImportInProgress = document.getElementById('btn-import-inprogress') btnImportInProgress.classList.remove('d-none'); btnImport.classList.add('d-none'); btnImport.disabled = true; let form = document.getElementById('formImport'); let formData = new FormData(form); unicaenVue.axios.post(this.importUrl, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) .then(response => { let datas = response.data; this.fileErrors = datas.file; this.intervenantMissing = datas.intervenant; btnImport.disabled = false; btnImportInProgress.classList.add('d-none'); btnImport.classList.remove('d-none'); }) .catch(error => { console.error('Error uploading'); }) } } } </script> No newline at end of file
module/Paiement/config/paiement.config.php +3 −1 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ return [ 'route' => '/import-numero-pec', 'controller' => Controller\PaiementController::class, 'action' => 'importNumeroPec', 'privileges' => Privileges::MISE_EN_PAIEMENT_EXPORT_PAIE, ], 'pilotage' => [ 'route' => '/pilotage', Loading Loading @@ -256,7 +257,7 @@ return [ ], [ 'controller' => Controller\PaiementController::class, 'action' => ['extractionPaie', 'imputationSiham'], 'action' => ['extractionPaie', 'imputationSiham', 'importNumeroPec'], 'privileges' => [Privileges::MISE_EN_PAIEMENT_EXPORT_PAIE], ], [ Loading @@ -279,6 +280,7 @@ return [ Service\MiseEnPaiementService::class => Service\MiseEnPaiementServiceFactory::class, Service\MiseEnPaiementIntervenantStructureService::class => Service\MiseEnPaiementIntervenantStructureServiceFactory::class, Service\MotifNonPaiementService::class => Service\MotifNonPaiementServiceFactory::class, Service\NumeroPriseEnChargeService::class => Service\NumeroPriseEnChargeServiceFactory::class, Assertion\PaiementAssertion::class => \UnicaenPrivilege\Assertion\AssertionFactory::class, PaiementProcess::class => PaiementProcessFactory::class, ], Loading
module/Paiement/src/Controller/PaiementController.php +12 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ use Paiement\Form\Paiement\MiseEnPaiementFormAwareTrait; use Paiement\Form\Paiement\MiseEnPaiementRechercheFormAwareTrait; use Paiement\Service\DotationServiceAwareTrait; use Paiement\Service\MiseEnPaiementServiceAwareTrait; use Paiement\Service\NumeroPriseEnChargeServiceAwareTrait; use Paiement\Service\ServiceAPayerServiceAwareTrait; use Paiement\Service\TypeRessourceServiceAwareTrait; use Referentiel\Entity\Db\ServiceReferentiel; Loading @@ -50,6 +51,7 @@ class PaiementController extends AbstractController use DotationServiceAwareTrait; use WorkflowServiceAwareTrait; use EtatSortieServiceAwareTrait; use NumeroPriseEnChargeServiceAwareTrait; /** * Initialisation des filtres Doctrine pour les historique. Loading Loading @@ -679,7 +681,16 @@ class PaiementController extends AbstractController $this->initFilters(); $title = 'Import des numéros de prise en charge'; return true; if ($this->getRequest()->isPost()) { $files = $this->getRequest()->getFiles()->toArray(); $datas = $this->getRequest()->getPost(); $importFile = $files['importFile']; $serviceNumeroPriseEnCharge = $this->getServiceNumeroPriseEnCharge(); return $serviceNumeroPriseEnCharge->treatImportFile($importFile, $datas['modeleImport']); } return compact('title'); } Loading
module/Paiement/src/Service/NumeroPriseEnChargeService.php 0 → 100755 +157 −0 Original line number Diff line number Diff line <?php namespace Paiement\Service; use Application\Entity\Db\Intervenant; use Application\Service\AbstractService; use Unicaen\OpenDocument\Calc\Sheet; use Unicaen\OpenDocument\Document; use UnicaenVue\View\Model\AxiosModel; /** * Description of NumeroPriseEnChargeService * * @author LE COURTES Antony <antony.lecourtes at unicaen.fr> */ class NumeroPriseEnChargeService extends AbstractService { /** * @param array $file * * @return AxiosModel Liste des erreurs rencontrées sous forme json */ public function treatImportFile (array $file, string $model = 'winpaie'): AxiosModel { $errors = []; $nameFile = $file['tmp_name']; $document = new Document(); $document->loadFromFile($nameFile); $sheet = $document->getCalc()->getSheet(0); switch ($model) { case 'winpaie': $datas = $this->winpaieTreatment($sheet); break; default: $datas = $this->genericTreatment($sheet); break; } $errors['file'] = $datas['errors']; //On met à jour les numéros de prise en charge des intervenants $em = $this->getEntityManager(); $em->beginTransaction(); foreach ($datas['result'] as $key => $value) { $intervenant = $em->getRepository(Intervenant::class)->findOneBy(['numeroInsee' => $value['insee'], 'annee' => $this->getServiceContext()->getAnnee()]); if ($intervenant) { $intervenant->setNumeroPec($value['pec']); $intervenant->setSyncPec(0); $em->persist($intervenant); } else { $errors['intervenant'][] = $value['nom'] . " - " . $value['insee']; } } $em->flush(); $em->commit(); return new AxiosModel($errors); } public function winpaieTreatment (Sheet $sheet): array { $lines = []; $errors = []; $colonneNames = [ 'insee' => 1, 'nom' => 2, 'nom de naissance' => 3, 'code poste' => 4, 'libelle poste' => 5, 'code grade' => 6, 'libelle grade' => 7, ]; $maxRow = $sheet->getMaxRow(); for ($rowNum = 2; $rowNum <= $maxRow; $rowNum++) { $cell = $sheet->getCellByCoords($colonneNames['insee'], $rowNum); $colValue = $cell->getContent(); // Expression régulière pour capturer les caractères après le 16ème caractère $regexInsee = '/^(.{16})(.*)$/'; $regexInseeProvisoire = '/^(.{15})(.*)$/'; // Utilisation de preg_match pour appliquer l'expression régulière if (preg_match($regexInsee, $colValue, $matches)) { $insee = str_replace("'", "", $matches[1]); $pec = $matches[2]; //Si je n'ai pas réussi à récupérer le numéro PEC s'est que le numéro insee doit etre provisoire sur 15 carctères if ($pec == '') { if (preg_match($regexInseeProvisoire, $colValue, $matches)) { $insee = str_replace(["'", " "], ["", ""], $matches[1]); $pec = $matches[2]; } else { $inseeFile = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $nomFile = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $errors[] = $nomFile . " - " . $inseeFile; } } $lines[] = [ 'insee' => $insee, 'pec' => $pec, 'nom' => $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(), ]; } else { //On stocke les erreurs dans datas pour afficher les lignes qui n'ont pas pu être traitées. $inseeFile = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $nomFile = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $errors[] = $nomFile . " - " . $inseeFile; } } $datas['result'] = $lines; $datas['errors'] = $errors; return $datas; } public function genericTreatment (Sheet $sheet): array { $lines = []; $errors = []; $colonneNames = [ 'insee' => 1, 'numero pec' => 2, 'nom' => 3, ]; $maxRow = $sheet->getMaxRow(); for ($rowNum = 2; $rowNum <= $maxRow; $rowNum++) { $insee = $sheet->getCellByCoords($colonneNames['insee'], $rowNum)->getContent(); $pec = $sheet->getCellByCoords($colonneNames['numero pec'], $rowNum)->getContent(); $nom = $sheet->getCellByCoords($colonneNames['nom'], $rowNum)->getContent(); $lines[] = [ 'insee' => $insee, 'pec' => $pec, 'nom' => $nom, ]; } $datas['result'] = $lines; $datas['errors'] = $errors; return $datas; } } No newline at end of file