diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c9dc65a342b3d2c4974fd526e06ef383d59561e..a64af76b4f4f85bc8a04ef8b0a14908f9c96422a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,37 @@ Toutes les modifications apportées au projet seront documentées dans ce fichier. Le format est basé sur le modèle [Keep a Changelog](http://keepachangelog.com/) et adhère aux principes du [Semantic Versioning](http://semver.org/). +[2.1.1] - 09-11-2021 +===== + +### Ajouts +-[#623](https://gitlab.libriciel.fr/libriciel/pole-citoyens/web-DPO/web-DPO/-/issues/623) + Création d'un référentiel avec fichier annexe. + Mise à disposition du référentiel existante. + Modification d'un référentiel. + Abrogation d'un référentiel. + Association d'un référentiel sur un traitement. + Filtre via un référentiel dans le registre. + Ajout des champs normes et référentiel dans les formulaires. + +### Evolutions +- [#611](https://gitlab.libriciel.fr/libriciel/pole-citoyens/web-DPO/web-DPO/-/issues/611) + Lors de l'installation de l'application, pouvoir définir lors de l'exécution du SHELL le SALT, le cipherSeed et le mot de passe de l'utilisateur "superadmin". + +- Abrogation normes (RU-005, RU-063, AU-004, AU-006, AU-010, AU-028, AU-034, AU-035, AU-046, AU-047, AU-048, AU-049, AU-050, NS-009, NS-016, NS-020, NS-042, NS-046, NS-048, NS-049, NS-050, NS-051, NS-052, NS-054, NS-057) + +### Corrections +- [#612](https://gitlab.libriciel.fr/libriciel/pole-citoyens/web-DPO/web-DPO/-/issues/612) + Correction de l'application des conditions sur les différents champs crée dans le formulaire lors de la rédaction d'un traitement + +- [#613](https://gitlab.libriciel.fr/libriciel/pole-citoyens/web-DPO/web-DPO/-/issues/613) + Correction de l'affichage de la modal permettant de répondre à un commentaire. + +- [#622](https://gitlab.libriciel.fr/libriciel/pole-citoyens/web-DPO/web-DPO/-/issues/622) + Correction de la modification du mot de passe de l'utilisateur. + +- Correction de l'affichage de la norme sélectionné sur un traitement après abrogation de celle-ci. + [2.1.0] - 18-06-2021 ===== diff --git a/README.md b/README.md index 0613f229cb3438b3a0ca406a985b4f0c621e239c..eaacf005ef3f057c4f0ec5896c973227ce78535a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Application web-DPO v2.1.0 +# Application web-DPO v2.1.1 [](https://php.net/) [](http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html) [](http://book.cakephp.org/3.0/fr/index.html) ## Présentation -Vous êtes en présence des sources de l'application **web-DPO** version 2.1.0 +Vous êtes en présence des sources de l'application **web-DPO** version 2.1.1 Avant toute nouvelle installation, veuillez faire une sauvegarde de la base de données ainsi que la version actuelle des sources. diff --git a/VERSION.txt b/VERSION.txt index 7ec1d6db40877765247db18e7f9a4e36a0def4ad..3e3c2f1e5edb083aab93646ac7b076daa38516dd 100755 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -2.1.0 +2.1.1 diff --git a/app/Config/Schema/CreationBase/patchs/2.1.0_to_2.1.1.sql b/app/Config/Schema/CreationBase/patchs/2.1.0_to_2.1.1.sql new file mode 100644 index 0000000000000000000000000000000000000000..97e8bbc10c8a093dc851debb17967fbfe3a3b042 --- /dev/null +++ b/app/Config/Schema/CreationBase/patchs/2.1.0_to_2.1.1.sql @@ -0,0 +1,281 @@ +BEGIN; + +UPDATE normes SET abroger = true WHERE norme='RU' AND numero='005'; +UPDATE normes SET abroger = true WHERE norme='RU' AND numero='063'; + +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='004'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='006'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='010'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='028'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='034'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='035'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='046'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='047'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='048'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='049'; +UPDATE normes SET abroger = true WHERE norme='AU' AND numero='050'; + +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='009'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='016'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='020'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='042'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='046'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='048'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='049'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='050'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='051'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='052'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='054'; +UPDATE normes SET abroger = true WHERE norme='NS' AND numero='057'; + +CREATE TABLE referentiels ( + id serial NOT NULL PRIMARY KEY, + name VARCHAR(500) NOT NULL, + description TEXT NOT NULL, + abroger BOOLEAN DEFAULT FALSE, + name_fichier VARCHAR, + fichier VARCHAR(500), + created timestamp without time zone NOT NULL, + modified timestamp without time zone NOT NULL +); +CREATE UNIQUE INDEX referentiels_name_idx ON referentiels (name); + +ALTER TABLE fiches ADD COLUMN referentiel_id integer REFERENCES referentiels (id) ON UPDATE CASCADE; + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel relatif à la gestion des ressources humaines', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<h2>L’encadrement des traitements courants en matière RH</h2> +<p>Adopté à la suite d’une consultation publique, <a title="Référentiel relatif aux traitements de données à caractère personnel mis en oeuvre aux fins de gestion du personnel (PDF, 379 ko) - Nouvelle fenêtre" href="https://www.cnil.fr/sites/default/files/atoms/files/referentiel_grh_novembre_2019_0.pdf" target="_blank" rel="noopener">ce référentiel</a> s’adresse à l’ensemble des organismes privés et publics qui mettent en place des traitements de données à des fins de gestion des ressources humaines.</p> +<p>Outil d’aide à la mise en conformité, il applique les règles de protection des données aux traitements courants de gestion du personnel, tels que le recrutement, la gestion administrative du personnel, la rémunération, ou encore la mise à disposition des salariés d’outils de travail.</p> +<h2>Les traitements exclus du référentiel</h2> +<p>Certains traitements sont exclus du champ d’application du référentiel en raison de leurs spécificités et font l’objet d’un encadrement particulier (<a title="Le contrôle d’accès biométrique sur les lieux de travail - Nouvelle fenêtre" href="https://www.cnil.fr/fr/le-controle-dacces-biometrique-sur-les-lieux-de-travail" target="_blank" rel="noopener">contrôle d’accès aux locaux de travail à l’aide des dispositifs biométriques</a>, <a title="Dispositifs d’alertes professionnelles : publication du référentiel pour les traitements de données personnelles - Nouvelle fenêtre" href="https://www.cnil.fr/fr/dispositifs-dalertes-professionnelles-publication-du-referentiel-pour-les-traitements-de-donnees" target="_blank" rel="noopener">dispositif d’alertes professionnelles</a>, <a title=" La vidéosurveillance – vidéoprotection au travail - Nouvelle fenêtre" href="https://www.cnil.fr/fr/la-videosurveillance-videoprotection-au-travail" target="_blank" rel="noopener">vidéosurveillance</a>, <a title="Ecoute et enregistrement des conversations téléphoniques sur le lieu de travail - Nouvelle fenêtre" href="https://www.cnil.fr/fr/declaration/ns-057-ecoute-et-enregistrement-des-conversations-telephoniques-sur-le-lieu-de-travail" target="_blank" rel="noopener">d’écoute et enregistrement des conversations téléphoniques</a>, des analyses algorithmiques visant à prédire le comportement ou la productivité des salariés, etc.). Il en va de même pour certains traitements invasifs ou ayant recours à des outils particulièrement innovants.</p> +<p>Aussi, un responsable de traitement qui souhaiterait mettre en œuvre de tels dispositifs devra s’assurer de la conformité de sa démarche à la réglementation en vigueur, en procédant à sa propre analyse. Il pourra partiellement s’aider du présent référentiel, mais ce dernier ne garantira pas la conformité de son traitement.</p> +<h2>Les principales évolutions du référentiel</h2> +<p>Afin de répondre au mieux aux besoins des organismes, le champ d’application du référentiel a été élargi et couvre désormais non seulement la gestion des ressources humaines, mais également la gestion de la paye et les traitements les plus répandus en matière de recrutement.</p> +<p>Des développements nouveaux ont été rajoutés concernant l’identification des <a title="Les bases légales - Nouvelle fenêtre" href="https://www.cnil.fr/fr/les-bases-legales" target="_blank" rel="noopener">bases légales</a> susceptibles de fonder les traitements courants en matière RH. Des précisions ont été également apportées sur les hypothèses dans lesquelles la réalisation d’une <a title="L''analyse d’impact relative à la protection des données (AIPD) - Nouvelle fenêtre" href="https://www.cnil.fr/fr/RGPD-analyse-impact-protection-des-donnees-aipd" target="_blank" rel="noopener">analyse d’impact sur la protection des données (AIPD)</a> est obligatoire, ou non, pour le responsable de traitement.</p> +<p><a title="Le référentiel relatif à la gestion des ressources humaines en questions - Nouvelle fenêtre" href="https://www.cnil.fr/fr/le-referentiel-relatif-la-gestion-des-ressources-humaines-en-questions" target="_blank" rel="noopener">Une FAQ accompagne la publication du référentiel</a> pour répondre aux questions les plus fréquentes.</p> +</div> +</div> +</div>', false, 'Referentiel_relatif_aux_traitements_de_données_a_caractere_personnel_mis_en_oeuvre_aux_fins_de_gestion_du_personnel.pdf', '1635145836.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel relatif à la désignation des conducteurs ayant commis une infraction au code la route', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<h2>L’encadrement des traitements dans le cadre de la désignation des conducteurs</h2> +<p>Les organismes titulaires de certificats d’immatriculation de véhicules mis à disposition du public (agences de location, entreprises de livraison) sont destinataires des procès-verbaux en cas d’infraction : ils doivent, dans ce cas, désigner le conducteur aux autorités compétentes.</p> +<p>Ce référentiel, adopté suite à une consultation publique, permet à ces organismes d’encadrer les traitements de données relatifs à ces désignations en respectant les droits des personnes concernées.</p> +<p>Il actualise l’autorisation unique n° 10 qui n’a plus de valeur juridique en tant que formalité préalable depuis l’entrée en vigueur du règlement général sur la protection des données (RGPD).</p> +<h2>Périmètre du référentiel</h2> +<p>Le référentiel cible trois finalités (objectifs) différentes :</p> +<ul> +<li>la désignation, auprès de l''Agence nationale de traitement automatisé des infractions (ANTAI), de la personne qui conduisait ou était susceptible de conduire le véhicule lorsque l''infraction a été constatée ;</li> +<li>le suivi de la procédure de recouvrement des contraventions au code de la route dont peuvent être redevables pécuniairement les organismes publics ou privés ;</li> +<li>la réalisation de statistiques anonymes (analyses statistiques des types d''infractions routières et des sinistres), notamment en vue d''adapter les formations de prévention routière.</li> +</ul> +<h2>Les principales évolutions du référentiel</h2> +<p>Les contributions reçues par la CNIL lors de sa consultation publique ont soulevé différentes problématiques et ont permis d’enrichir le référentiel afin de répondre au mieux aux besoins des organismes concernés. Des précisions ont ainsi été apportées concernant :</p> +<ul> +<li>les organismes concernés par le référentiel ;</li> +<li>les données susceptibles d’être collectées ;</li> +<li>la réutilisation des données ;</li> +<li>les destinataires.</li> +</ul> +</div> +</div> +</div>', false, 'referentiel_relatif_aux_traitements_de_donnees_personnelles_mis_en_oeuvre_dans_le_cadre_de_la_designation_des_conducteurs_ayant_commis_une_infraction_au_code_de_la_route.pdf', '1635145900.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel relatif à la gestion locative', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<h2>L’encadrement des traitements dans le cadre de la gestion locative</h2> +<p>Les organismes mettant un logement en location ainsi que les intermédiaires participant à la mise en location d’un logement sont amenés à traiter de nombreuses données personnelles de candidats à la location, locataires et garants.</p> +<p>Ce référentiel, adopté à la suite d’une consultation publique, permet à ces organismes d’encadrer les traitements de données relatifs à la gestion locative en respectant les principes relatifs à la protection des données ainsi que les droits des personnes.</p> +<p>Il actualise la norme simplifiée n°21 qui n’a plus de valeur juridique depuis l’entrée en application du règlement général sur la protection des données (RGPD).</p> +<h2>Périmètre du référentiel</h2> +<p>Le référentiel a vocation à encadrer l’ensemble des traitements mis en œuvre pendant toute la durée d’un contrat de bail.</p> +<p>Il cible ainsi de nombreuses finalités (objectifs) qui peuvent être regroupées en quatre thématiques distinctes :</p> +<ul> +<li>la <strong>proposition de biens à louer</strong> (analyse des critères de potentiels futurs locataires, envoi de propositions de location) ;</li> +<li>la <strong>pré-contractualisation et la conclusion du contrat de bail</strong> (organisation des visites du logement, appréciation de la solvabilité des candidats à la location, etc.) ;</li> +<li>le <strong>déroulement du contrat de bail</strong> (suivi du paiement des loyers, vérification de la souscription d’une assurance, etc.) ;</li> +<li>la <strong>fin du contrat</strong> (résiliation du contrat, fin de solidarité des locataires pour le paiement des loyers).</li> +</ul> +<h2>Les principales évolutions du référentiel</h2> +<p>Les contributions reçues par la CNIL lors de sa consultation publique ont soulevé différentes problématiques et ont permis d’enrichir le référentiel afin de répondre au mieux aux besoins des organismes concernés. Des précisions ont ainsi été apportées concernant :</p> +<ul> +<li>les organismes concernés par le référentiel ;</li> +<li>les données susceptibles d’être collectées ;</li> +<li>les destinataires ;</li> +<li>les durées de conservation.</li> +</ul> +</div> +</div> +</div>', false, 'referentiel_relatif_aux_traitements_de_donnees_personnelles_mis_en_oeuvre_dans_le_cadre_de_la_gestion_locative.pdf', '1635145939.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel pour la prise en charge médico-sociale des personnes âgées, en situation de handicap ou en difficulté', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<h2>L’encadrement des traitements dans le secteur social et médico-social</h2> +<p>Adopté à la suite d’une consultation publique, ce référentiel s’adresse à l’ensemble des organismes privés ou publics concernés par l’accueil, l’hébergement ou l’accompagnement des personnes âgées, en situation de handicap ou en difficulté.</p> +<p>Outil d’aide à la mise en conformité, ce référentiel permet d’<strong>appliquer les règles de protection des données aux traitements relevant du secteur social et/ou médico-social</strong>, tels que l’instruction, la gestion, l’ouverture et/ou le versement des prestations sociales légales ou facultatives ou encore l’accompagnement social et médico-social adapté aux difficultés rencontrées.</p> +<p>Suite à la consultation publique et pour répondre au mieux aux besoins des organismes concernés, de nouvelles précisions ont notamment été ajoutées sur :</p> +<ul> +<li>les bases légales qui peuvent être retenues dans le secteur social et médico-social ;</li> +<li>les données susceptibles d’être collectées ;</li> +<li>les durées de conservation ;</li> +<li>les destinataires ;</li> +<li>l’information et les droits des personnes concernées.</li> +</ul> +<p>Certaines finalités ont également été regroupées.</p> +<p><a title="Questions-réponses sur le référentiel pour le suivi médico-social des personnes âgées, en situation de handicap ou en difficulté - Nouvelle fenêtre" href="https://www.cnil.fr/fr/questions-reponses-referentiel-suivi-medico-social-des-personnes-agees-handicap-difficulte" target="_blank" rel="noopener">Une FAQ accompagne la publication du référentiel</a>.</p> +<h2>Les traitements exclus du référentiel</h2> +<p>Certains traitements sont exclus du champ d’application du référentiel en raison de leurs spécificités. C’est le cas :</p> +<ul> +<li>Des traitements portant sur <strong>la prévention et la protection de l’enfance.</strong> Un projet de référentiel distinct est actuellement en cours d’élaboration et fera l''objet d''une consultation publique avant son adoption définitive. Il aura notamment vocation à regrouper les anciennes autorisations uniques relatives à : +<ul> +<li>l’accompagnement et suivi-social dans le cadre de la prévention et de la protection des mineurs et jeunes majeurs (<a title="Autorisation unique 49 - Accompagnement et suivi social dans le cadre de la prévention et de la protection des mineurs et jeunes majeurs (PDF, 288 ko) - Nouvelle fenêtre" href="https://www.cnil.fr/sites/default/files/atoms/files/au49.pdf" target="_blank" rel="noopener">AU-49</a>) ;</li> +<li>l’enfance en danger et « Informations préoccupantes » (<a title="Autorisation unique 28 - Enfance en danger et "informations préoccupantes" (PDF, 44 ko) - Nouvelle fenêtre" href="https://www.cnil.fr/sites/default/files/atoms/files/au28.pdf" target="_blank" rel="noopener">AU-28</a>).</li> +</ul> +</li> +<li>Des traitements mis en œuvre par <strong>les mandataires judiciaires à la protection des majeurs</strong> (MJPM). Dans l’attente de la production d’un référentiel propre à ce secteur, les organismes concernés peuvent s’inspirer de l’ancienne <a title="Autorisation unique 50 - Mandataires judiciaires à la protection des majeurs (PDF, 293 ko) - Nouvelle fenêtre" href="https://www.cnil.fr/sites/default/files/atoms/files/au50.pdf" target="_blank" rel="noopener">AU-050</a> pour les mandataires judiciaires agréés à la protection des majeurs aux fins d’assurer la gestion et le suivi de la représentation juridique, de l’assistance et du contrôle des personnes placées par l’autorité judiciaire (sauvegarde judiciaire, curatelle, tutelle, mesure d’accompagnement judiciaire).</li> +</ul> +</div> +</div> +</div>', false, 'referentiel_relatif_aux_traitements_de_donnees_personnelles_pour_le_suivi_social_et_medico-social_des_personnes_agees_en_situation_de_handicap_ou_en_difficulte.pdf', '1635145996.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel relatif au dispositif d’alertes professionnelles', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<h2>L’encadrement des dispositifs d’alertes</h2> +<p>La CNIL a publié <a title="Référentiel relatif aux traitements de données à caractère personnel destinsé à la mise en oeuvre d''un dispositif d''alertes professionnelles - Nouvelle fenêtre" href="https://www.cnil.fr/sites/default/files/atoms/files/referentiel-alertes-professionnelles_decembre-2019.pdf" target="_blank" rel="noopener">un référentiel relatif aux dispositifs d''alertes professionnelles (DAP)</a>, adopté à la suite d''une consultation publique.</p> +<p>Les traitements respectant les préconisations du référentiel s’inscrivent dans le respect des dispositions du RGPD. Le référentiel peut également constituer un outil de référence en vue de la conception d’une analyse d’impact relative à la protection des données (AIPD).</p> +<h2>Les principales évolutions du référentiel</h2> +<p>Ce référentiel actualise et consolide la doctrine de la CNIL sur les alertes professionnelles, en intégrant les évolutions liées à l’entrée en application du RGPD et à la modification de la loi « Informatique et Libertés ». Il s’inscrit dans la continuité de l’autorisation unique AU-004.</p> +<p>Il anticipe par ailleurs certaines évolutions introduites par la directive européenne relative à la protection des lanceurs d’alerte dont le texte a été adopté début octobre par le Conseil de l’Union européenne, pour une application effective prévue à partir de 2021. </p> +<p>Parmi les évolutions notables du référentiel figurent :</p> +<ul> +<li>l’encadrement des dispositifs résultant à la fois d''une obligation légale (<a title=" LOI n° 2017-399 du 27 mars 2017 relative au devoir de vigilance des sociétés mères et des entreprises donneuses d''ordre - Légifrance - Nouvelle fenêtre" href="https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000034290626&dateTexte=20191211" target="_blank" rel="noopener">loi dite « devoir de vigilance »</a>, <a title=" LOI n° 2016-1691 du 9 décembre 2016 relative à la transparence, à la lutte contre la corruption et à la modernisation de la vie économique - Légifrance - Nouvelle fenêtre" href="https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000033558528&categorieLien=id" target="_blank" rel="noopener">loi « Sapin II »</a>, etc.), et ceux mis en place à la seule initiative du responsable de traitement (notamment les alertes dites « éthiques ») ;</li> +<li>l’instauration d’un cadre unique pour l''ensemble des dispositifs d’alerte, qui améliore leur lisibilité pour les personnes concernées ;</li> +<li>l’ajout de précisions sur les durées de conservation des données.</li> +</ul> +<p>La CNIL rappelle également que la mise en place d''un tel dispositif vient en complément des autres possibilités de remontées d’alertes (comme la voie hiérarchique) et ne doit avoir ni pour objet ni pour effet d''exonérer l''employeur de ses obligations (telle que celle de prévenir les risques psychosociaux), et du respect de la règlementation qui lui est applicable (droits et libertés fondamentales, Code du travail, etc.).</p> +<p>Une <a title="Le référentiel relatif au dispositif d’alertes professionnelles en questions - Nouvelle fenêtre" href="https://www.cnil.fr/fr/le-referentiel-relatif-au-dispositif-dalertes-professionnelles-en-questions" target="_blank" rel="noopener">FAQ</a> pour répondre à certaines questions pratiques régulièrement posées à la CNIL accompagne la publication du référentiel.</p> +</div> +</div> +</div>', false, 'Referentiel_relatif_au_dispositif_d_alertes_professionnelles.pdf', '1635146060.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel vigilance sanitaire', '<div class="field field-name-body field-type-text-with-summary field-label-hidden"> +<div class="field-items"> +<div class="field-item even"> +<p>Avant l’entrée en application du RGPD, la CNIL avait adopté une autorisation unique spécifiquement dédiée à la pharmacovigilance.</p> +<p>Ce nouveau référentiel décline au domaine des vigilances sanitaires, de manière pragmatique et opérationnelle, les principes du RGPD.</p> +<p>Ce référentiel fait suite à une concertation organisée auprès de l’Institut national des données de santé (INDS) et d’organismes publics et privés représentatifs des acteurs concernés*. Cette concertation a permis aux professionnels de soumettre des propositions. Cela a notamment conduit à exclure expressément du référentiel les traitements de données à caractère personnel mis en œuvre par les professionnels et établissements de santé ainsi que par les agences sanitaires. De même, à la suite de cette concertation, la durée de conservation des données a été allongée.</p> +<p>Le système des vigilances sanitaires fonctionne sur la base de principes communs, en termes de finalité, de catégories de données traitées, et de destinataires. La CNIL a donc élaboré un référentiel unique, applicable à l’ensemble des vigilances sanitaires (pharmacovigilance, addictovigilance, biovigilance, cosmétovigilance, hémovigilance, etc.).</p> +<p>Si les traitements de données à caractère personnel des organismes respectent toutes les exigences qui y sont fixées, ces organismes n’ont pas à demander à la CNIL une autorisation : ils peuvent se contenter de procéder en ligne à une simple <a href="https://declarations.cnil.fr/declarations/declaration/brouillon.action?declarationType=DS" target="_blank" rel="noopener">déclaration de conformité</a> avant de mettre en œuvre leurs traitements de données. Si, en revanche, ils souhaitent s’écarter du référentiel, ces organismes devront formuler une <a href="https://declarations.cnil.fr/declarations/declaration/brouillon.action?declarationType=DT" target="_blank" rel="noopener">demande d’autorisation</a> auprès de la CNIL.</p> +<p>Une FAQ accompagne la publication du référentiel « vigilances sanitaires » afin d’en faciliter la compréhension.</p> +<p> </p> +<p><em>*Santé publique France, Agence nationale de sécurité du médicament et des produits de santé, Autorité de sûreté nucléaire, Agence de la biomédecine, Agence nationale de sécurité sanitaire de l’alimentation, de l’environnement et du travail, ministère des solidarités et de la santé, Les Entreprises du médicament, le Syndicat National de l’Industrie des Technologies Médicales, France Assos Santé.</em></p> +</div> +</div> +</div>', false, 'referentiel_vigilances_sanitaires.pdf', '1635146149.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel pour la gestion des traitements courants des cabinets médicaux et paramédicaux', '<p style="font-size: 18px;">Pour aider les professionnels de santé libéraux dans leurs démarches de conformité, la CNIL a adopté un nouveau référentiel qui recense et applique les principes du RGPD aux traitements de <a title="Donnée sensible - nouvelle page" href="https://www.cnil.fr/fr/definition/donnee-sensible" target="_blank" rel="noopener">données sensibles</a> couramment mis en œuvre dans le cadre de la gestion médicale et administrative d’une patientèle.</p> +<h3>Faciliter la mise en conformité</h3> +<p style="font-size: 18px;">Ce référentiel est <strong>un cadre de référence</strong> <strong>qui permet aux professionnels de santé libéraux de mettre en conformité les traitements de données personnelles utilisés pour la gestion de leurs cabinets médicaux et paramédicaux</strong>. Il a été adopté à la suite d’une consultation des principaux représentants du secteur.</p> +<p style="font-size: 18px;">Il a vocation à remplacer l’ancienne norme simplifiée NS-50 destinée aux membres des professions médicales et paramédicales exerçant à titre libéral à des fins de gestion de leur cabinet.</p> +<p style="font-size: 18px;"><strong>Le référentiel n’est pas contraignant</strong>. Les responsables de traitement peuvent s’écarter de ses préconisations (par exemple, en identifiant d’autres bases de traitement pour tel ou tel traitement spécifique, etc.), à condition toutefois de pouvoir justifier leur choix et sous leur responsabilité.</p> +<h3>Qui est concerné par le référentiel ?</h3> +<p style="font-size: 18px;">Il s’agit des <strong>professionnels de santé, exerçant à titre libéral, en cabinet individuel ou groupé, ou encore au sein de maisons de santé</strong>. Sont donc concernés les médecins généralistes ou spécialistes, les infirmiers, les radiologues, les masseurs kinésithérapeutes, les sages-femmes, les pédicures-podologues, les orthophonistes et orthoptistes etc.</p> +<p style="font-size: 18px;">La référentiel n’a en revanche pas vocation à s’appliquer aux traitements mis en œuvre par les services de soins (établissements de santé, centres de santé, communautés professionnelles territoriales de santé, etc.), ni à ceux mis en œuvre par les services de médecine d’entités publiques ou privées (médecine du travail, médecine scolaire, PMI, etc.), par les pharmaciens, par les laboratoires d’analyses de biologie médicale ou par les opticiens.</p> +<h3>Les principales évolutions par rapport à la norme simplifiée 50</h3> +<p style="font-size: 18px;">Certaines règles de fond ont été précisées : celles relatives à l’identification des bases légales susceptibles de fonder des traitements en matière de gestion médicale et administrative de la patientèle, ou encore en matière de sécurité des données.</p> +<p style="font-size: 18px;">Ont également été intégrées les nouvelles obligations liées au processus de conformité, concernant notamment la tenue d’un registre des traitements <strong>ainsi que l’élaboration d’une AIPD dans certaines hypothèses bien précises</strong>.</p> +<ul> +<li><a title="Référentiel Cabinet médicaux - nouvelle fenêtre " href="https://www.cnil.fr/sites/default/files/atoms/files/referentiel_-_cabinet.pdf" target="_blank" rel="noopener"><strong>Pour en savoir plus</strong> : Un référentiel pour la gestion des traitements courants des cabinets médicaux et paramédicaux</a></li> +</ul>', false, 'Referentiel_pour_la_gestion_des_traitements_courants_des_cabinets_medicaux_et_paramedicaux.pdf', '1635146223.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel vise les traitements de données dans le domaine de la santé', '<p style="font-size: 18px;">La gestion du cycle de vie des données et la détermination de leurs durées de conservation constituent une étape indispensable dans la mise en conformité des traitements de données personnelles des organismes publics et privés.</p> +<p style="font-size: 18px;">La CNIL, qui a publié <a title="Guide durée de conservation - nouvelle fenêtre " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">un guide des durées de conservation</a>, adopte également deux référentiels spécifiques aux secteurs de la santé et de la recherche en santé.</p> +<h3>Les référentiels spécifiques pour identifier les durées pertinentes dans le secteur de la santé et de la recherche</h3> +<p style="font-size: 18px;">Les référentiels de durées de conservation ont pour objectif d’accompagner, de manière opérationnelle, les acteurs dans <strong>l’identification et la détermination de la durée pertinente pour les traitements</strong>.</p> +<p>Le référentiel vise les traitements de données dans le domaine de la santé – hors recherche (ex : tenue du dossier patient, ordonnancier, vigilances sanitaires, etc.)</p> +<p style="font-size: 18px;">Ils sont une aide à la <strong>prise de décision</strong> en orientant le responsable de traitement vers :</p> +<ul> +<li>les durées obligatoires du fait de la réglementation en vigueur, et en particulier le Code de la santé publique ;</li> +<li>les durées recommandées par la CNIL, qui sont des points de repère pour déterminer la durée pertinente.</li> +</ul> +<p style="font-size: 18px;"><strong>Les référentiels ne sont pas exhaustifs</strong> : ils listent les durées pertinentes pour les traitements les plus fréquents pour ces deux secteurs d’activité.</p> +<h3>Pour aller plus loin : le guide des durées de conservation</h3> +<p style="font-size: 18px;">La CNIL a publié <a title="guide pratique conservation des données - nouvelle fenêtre " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">un guide pratique</a>, plus général, qui a vocation à apporter les réponses aux questions les plus fréquentes des professionnels sur le principe de limitation de la conservation des données. Il détaille les éléments clés de cette obligation et apporte des conseils pratiques pour l’implémenter de manière concrète au sein des organismes publics ou privées.</p> +<p style="font-size: 18px;">Élaboré en partenariat avec le <strong>Service interministériel des archives de France (SIAF)</strong>, le guide met en relation les obligations du RGPD et celles du Code du patrimoine.</p> +<ul> +<li><a title="Guide pratique durée de conservation des données " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">Consulter le guide pratique</a></li> +</ul>', false, 'Referentiel_vise_les_traitements_de_donnees_dans_le_domaine_de_la_sante.pdf', '1635146344.pdf', NOW(), NOW()); + +INSERT INTO referentiels (name, description, abroger, name_fichier, fichier, created, modified) VALUES ('Référentiel vis les traitements de données mis en Å“uvre à des fins de recherche, d’étude, et d’évaluation dans le domaine de la santé', '<p style="font-size: 18px;">La gestion du cycle de vie des données et la détermination de leurs durées de conservation constituent une étape indispensable dans la mise en conformité des traitements de données personnelles des organismes publics et privés.</p> +<p style="font-size: 18px;">La CNIL, qui a publié <a title="Guide durée de conservation - nouvelle fenêtre " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">un guide des durées de conservation</a>, adopte également deux référentiels spécifiques aux secteurs de la santé et de la recherche en santé.</p> +<h3>Les référentiels spécifiques pour identifier les durées pertinentes dans le secteur de la santé et de la recherche</h3> +<p style="font-size: 18px;">Les référentiels de durées de conservation ont pour objectif d’accompagner, de manière opérationnelle, les acteurs dans <strong>l’identification et la détermination de la durée pertinente pour les traitements</strong>.</p> +<p>Le référentiel vis les traitements de données mis en œuvre à des fins de recherche, d’étude, et d’évaluation dans le domaine de la santé (ex : les recherches interventionnelles, les recherches sur des données déjà collectées, etc.).</p> +<p style="font-size: 18px;">Ils sont une aide à la <strong>prise de décision</strong> en orientant le responsable de traitement vers :</p> +<ul> +<li>les durées obligatoires du fait de la réglementation en vigueur, et en particulier le Code de la santé publique ;</li> +<li>les durées recommandées par la CNIL, qui sont des points de repère pour déterminer la durée pertinente.</li> +</ul> +<p style="font-size: 18px;"><strong>Les référentiels ne sont pas exhaustifs</strong> : ils listent les durées pertinentes pour les traitements les plus fréquents pour ces deux secteurs d’activité.</p> +<h3>Pour aller plus loin : le guide des durées de conservation</h3> +<p style="font-size: 18px;">La CNIL a publié <a title="guide pratique conservation des données - nouvelle fenêtre " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">un guide pratique</a>, plus général, qui a vocation à apporter les réponses aux questions les plus fréquentes des professionnels sur le principe de limitation de la conservation des données. Il détaille les éléments clés de cette obligation et apporte des conseils pratiques pour l’implémenter de manière concrète au sein des organismes publics ou privées.</p> +<p style="font-size: 18px;">Élaboré en partenariat avec le <strong>Service interministériel des archives de France (SIAF)</strong>, le guide met en relation les obligations du RGPD et celles du Code du patrimoine.</p> +<ul> +<li><a title="Guide pratique durée de conservation des données " href="https://www.cnil.fr/sites/default/files/atoms/files/guide_durees_de_conservation.pdf" target="_blank" rel="noopener">Consulter le guide pratique</a></li> +</ul>', false, 'Referentiel_vis_les_traitements_de_donnees_mis_en_oeuvre_a_des_fins_de_recherche_d_etude_et_d_evaluation_dans_le_domaine_de_la_sante.pdf', '1635146435.pdf', NOW(), NOW()); + +INSERT INTO liste_droits (libelle, value, created, modified) VALUES +('Créer un référentiel', 40, NOW(), NOW()), +('Visualiser un référentiel', 41, NOW(), NOW()), +('Modifier un référentiel', 42, NOW(), NOW()), +('Abroger un référentiel', 43, NOW(), NOW()); + +INSERT INTO role_droits (role_id, liste_droit_id) +SELECT roles.id, liste_droits.id +FROM roles + INNER JOIN liste_droits ON (1 = 1) +WHERE + roles.libelle = 'DPO' + AND liste_droits.libelle IN ( + 'Créer un référentiel', + 'Visualiser un référentiel', + 'Modifier un référentiel', + 'Abroger un référentiel' + ) + AND liste_droits.id NOT IN ( + SELECT existing_roles_droits.liste_droit_id + FROM role_droits AS existing_roles_droits + WHERE existing_roles_droits.role_id = roles.id +) +ORDER BY roles.id, liste_droits.id; + +INSERT INTO droits (organisation_user_id, liste_droit_id, created, modified) +SELECT organisations_users.id, liste_droits.id, NOW(), NOW() +FROM organisations_users + INNER JOIN liste_droits ON (1 = 1) +WHERE (organisations_users.organisation_id, organisations_users.user_id) IN ( + SELECT organisations.id, organisations.dpo + FROM organisations + WHERE organisations.dpo IS NOT NULL +) + AND liste_droits.libelle IN ( + 'Créer un référentiel', + 'Visualiser un référentiel', + 'Modifier un référentiel', + 'Abroger un référentiel' + ) + AND liste_droits.id NOT IN ( + SELECT existing_droits.liste_droit_id + FROM droits AS existing_droits + WHERE existing_droits.organisation_user_id = organisations_users.id +) +ORDER BY organisations_users.id, liste_droits.id; + +COMMIT; diff --git a/app/Config/webdpo.inc.default b/app/Config/webdpo.inc.default index d76fad2bb8389c312c37c1f099458b9b10d323d2..28d6f7937bf73b52e16980b5d44b171adeb31e64 100755 --- a/app/Config/webdpo.inc.default +++ b/app/Config/webdpo.inc.default @@ -68,6 +68,11 @@ define('NORMES', DS . "normes"); define('CHEMIN_NORMES', APP . FICHIER . NORMES . DS); define('CHEMIN_NEW_NORMES', CHEMIN_FICHIER . NORMES . DS); +//Dossier qui va contenir toutes les référentiels +define('REFERENTIELS', DS . "referentiels"); +define('CHEMIN_REFERENTIELS', APP . FICHIER . REFERENTIELS . DS); +define('CHEMIN_NEW_REFERENTIELS', CHEMIN_FICHIER . REFERENTIELS . DS); + //Dossier qui va contenir le fichier exemple pour l'import des services define('SERVICES', DS . "services"); define('FILE_EXEMPLE_IMPORT_SERVICES', APP . FICHIER . SERVICES . DS . 'exemple_import_services.csv'); diff --git a/app/Console/Command/InstallationsShell.php b/app/Console/Command/InstallationsShell.php index 7c36d305cc1d2010eb986161af0c8c8b110419b5..aa6837b7ccba922e3af10ff345a159691336e2b2 100644 --- a/app/Console/Command/InstallationsShell.php +++ b/app/Console/Command/InstallationsShell.php @@ -39,10 +39,31 @@ class InstallationsShell extends Shell { */ public function getOptionParser() { - return parent::getOptionParser() - ->addSubcommand('updateSaltAndCipherSeed', [ - 'help' => __("Ajout du SALT et du cipherSeed dans le core.php"), - ]); + $parser = parent::getOptionParser(); + + $parser->description([ + 'Ajout du SALT et du cipherSeed dans le core.php', + '', + 'Exemple: cake users updateSaltAndCipherSeed -s xxxxxxxxxxxxxxxxxxxxxxxxx -c 00000000000000000000000', + ]); + + $options = [ + 'salt' => [ + 'short' => 's', + 'help' => "Chaîne aléatoire de 40 caractères minimum composée de lettre de l'alphabet de A à Z (minuscule et majuscule) et de chiffre entre 0 et 9.", + 'default' => null, + 'required' => false, + ], + 'cipher' => [ + 'short' => 'c', + 'help' => "Chaîne aléatoire de 30 chiffres minimum composée uniquement de chiffre entre 0 et 9.", + 'default' => null, + 'required' => false, + ] + ]; + $parser->addOptions($options); + + return $parser; } public function updateSaltAndCipherSeed() @@ -57,10 +78,36 @@ class InstallationsShell extends Shell { $this->error("Le fichier {$pathCore} n'est pas accessible en écriture."); } - $salt = PasswordGeneratorAnssi::generate(40); + $refNbSalt = 40; + $salt = Hash::get($this->params, 'salt'); + if (empty($salt)) { + $salt = PasswordGeneratorAnssi::generate($refNbSalt); + } else { + $nbSalt = strlen($salt); + if ($nbSalt < $refNbSalt) { + $this->error("Le SALT défini ne respect pas la contrainte de taille : 40 caractères minimum."); + } + + if (ctype_alnum($salt) === false) { + $this->error("Le SALT défini ne respect pas la contrainte de composition : lettre de l'alphabet de A à Z (minuscule et majuscule) et de chiffre entre 0 et 9."); + } + } - $params = ['numbers' => true] + array_fill_keys(array_keys(PasswordGeneratorAnssi::defaults()), false); - $cipherSeed = PasswordGeneratorAnssi::generate(30, $params); + $refNbCipherSeed = 30; + $cipherSeed = Hash::get($this->params, 'cipher'); + if (empty($cipherSeed)) { + $params = ['numbers' => true] + array_fill_keys(array_keys(PasswordGeneratorAnssi::defaults()), false); + $cipherSeed = PasswordGeneratorAnssi::generate($refNbCipherSeed, $params); + } else { + $nbCipherSeed = strlen($cipherSeed); + if ($nbCipherSeed < $refNbCipherSeed) { + $this->error("Le cipherSeed défini ne respect pas la contrainte de taille : 30 chiffres minimum."); + } + + if (is_numeric($cipherSeed) === false) { + $this->error("Le cipherSeed défini ne respect pas la contrainte numérique : uniquement de chiffre entre 0 et 9."); + } + } $keySalt = 'webdpo_security_salt_core'; $keycipherSeed = 'webdpo_security_cipherSeed_core'; diff --git a/app/Console/Command/UsersShell.php b/app/Console/Command/UsersShell.php index 8a7725d772c8e7a5ab6037ee06193fcf9671f06c..af0568a7b043621c16c0694a563079d6289fc063 100644 --- a/app/Console/Command/UsersShell.php +++ b/app/Console/Command/UsersShell.php @@ -34,15 +34,30 @@ class UsersShell extends Shell * * Options d'exécution et validation des arguments * - * @return Parser $parser + * @return ConsoleOptionParser $parser * @version v1.0.0 */ public function getOptionParser() { - return parent::getOptionParser() - ->addSubcommand('addFirstUserSuperadmin', [ - 'help' => __("Création du premier utilisateur superadmin dans l'application"), - ]); + $parser = parent::getOptionParser(); + + $parser->description([ + 'Création du premier utilisateur superadmin dans l\'application', + '', + 'Exemple: cake users addFirstUserSuperadmin -p Lem0tdepassedemonSuperadmin', + ]); + + $options = [ + 'password' => [ + 'short' => 'p', + 'help' => 'Mot de passe de force 5 minimum', + 'default' => null, + 'required' => false, + ] + ]; + $parser->addOptions($options); + + return $parser; } public function addFirstUserSuperadmin() @@ -70,7 +85,10 @@ class UsersShell extends Shell $success = true; $this->User->begin(); - $password = PasswordGeneratorAnssi::generate(); + $password = Hash::get($this->params, 'password'); + if (empty($password)) { + $password = PasswordGeneratorAnssi::generate(); + } $data = [ 'User' => [ @@ -110,6 +128,7 @@ class UsersShell extends Shell echo "\n"; } else { $this->User->rollback(); + var_dump($this->User->validationErrors); $this->error("Une erreur est survenue lors de l'enregistrement de l'utilisateur."); } } diff --git a/app/Controller/Component/BanettesComponent.php b/app/Controller/Component/BanettesComponent.php index fae45732435b4af402ddfed430c16b56fb75d6ca..e8f0f04fdbe2ba454cf3b73565eb39e7830d1213 100755 --- a/app/Controller/Component/BanettesComponent.php +++ b/app/Controller/Component/BanettesComponent.php @@ -105,6 +105,12 @@ class BanettesComponent extends Component { 'fichier' ] ], + 'Referentiel' => [ + 'fields' => [ + 'id', + 'name' + ], + ], 'Service' => [ 'fields' => [ 'libelle' diff --git a/app/Controller/EtatFichesController.php b/app/Controller/EtatFichesController.php index 41539018caaf48552007bd566aecc4a33abbd14f..a51609730882e23b403012250956678b49e57051 100644 --- a/app/Controller/EtatFichesController.php +++ b/app/Controller/EtatFichesController.php @@ -663,20 +663,37 @@ class EtatFichesController extends AppController case EtatFiche::ENCOURS_REDACTION: $etat_fiches_id = $traitementEnReponse['EtatFiche']['previous_etat_id']; break; + case EtatFiche::ENCOURS_VALIDATION: if ($previousTraitement['EtatFiche']['actif'] == true) { $etat_fiches_id = $traitementEnReponse['EtatFiche']['previous_etat_id']; $actif = false; } break; + case EtatFiche::REPLACER_REDACTION: + case EtatFiche::TRAITEMENT_INITIALISE_REDIGER: $etat_fiches_id = $traitementEnReponse['EtatFiche']['previous_etat_id']; $actif = true; break; - case EtatFiche::TRAITEMENT_INITIALISE_RECU: - $etat_fiches_id = $traitementEnReponse['EtatFiche']['previous_etat_id']; + + case EtatFiche::REPONSE_AVIS: + $lastEtatTraitement = $this->EtatFiche->find('first', [ + 'conditions' => [ + 'etat_id' => [ + EtatFiche::ENCOURS_REDACTION, + EtatFiche::REPLACER_REDACTION, + EtatFiche::TRAITEMENT_INITIALISE_REDIGER + ], + 'fiche_id' => $this->request->data['EtatFiche']['ficheNum'], + 'actif' => false + ] + ]); + + $etat_fiches_id = $lastEtatTraitement['EtatFiche']['id']; $actif = true; break; + default: break; } @@ -710,12 +727,18 @@ class EtatFichesController extends AppController //@todo foreach ($traitements as $fiche) { - if ($previousTraitement['EtatFiche']['etat_id'] == EtatFiche::REPONSE_AVIS && $previousTraitement['EtatFiche']['actif'] == false && $fiche['EtatFiche']['etat_id'] == EtatFiche::ENCOURS_REDACTION) { + if ($previousTraitement['EtatFiche']['etat_id'] == EtatFiche::REPONSE_AVIS && + $previousTraitement['EtatFiche']['actif'] == false && + $fiche['EtatFiche']['etat_id'] == EtatFiche::ENCOURS_REDACTION + ) { $etat_fiches_id = $fiche['EtatFiche']['id']; $actif = true; } - if ($previousTraitement['EtatFiche']['etat_id'] == EtatFiche::REPONSE_AVIS && $previousTraitement['EtatFiche']['actif'] == false && $fiche['EtatFiche']['etat_id'] == EtatFiche::REPLACER_REDACTION) { + if ($previousTraitement['EtatFiche']['etat_id'] == EtatFiche::REPONSE_AVIS && + $previousTraitement['EtatFiche']['actif'] == false && + $fiche['EtatFiche']['etat_id'] == EtatFiche::REPLACER_REDACTION + ) { $etat_fiches_id = $fiche['EtatFiche']['id']; $actif = true; } @@ -723,12 +746,14 @@ class EtatFichesController extends AppController } } - $success = $success && $this->EtatFiche->updateAll([ + $success = $success && $this->EtatFiche->updateAll( + [ 'actif' => false - ], [ - 'id' => $this->request->data['EtatFiche']['etatFiche'] - ] - ) !== false; + ], + [ + 'id' => $this->request->data['EtatFiche']['etatFiche'] + ] + ) !== false; $this->EtatFiche->create([ 'EtatFiche' => [ @@ -1104,7 +1129,6 @@ class EtatFichesController extends AppController * * @param int $id * @param string|null $numero - * @param int|null $norme * * @access public * @@ -1116,7 +1140,7 @@ class EtatFichesController extends AppController * @modified 11/06/2021 * @version V2.1.0 */ - public function insertRegistre($fiche_id, $numero, $norme) + public function insertRegistre($fiche_id, $numero) { if (empty($fiche_id)) { throw new NotFoundException(); @@ -1138,7 +1162,7 @@ class EtatFichesController extends AppController $this->EtatFiche->begin(); - $dataReturn = $this->saveNumeroFicheRegistre($organisation_id, $fiche_id, $numero, $norme); + $dataReturn = $this->saveNumeroFicheRegistre($organisation_id, $fiche_id, $numero); if ($dataReturn['success'] === true) { $success = true; @@ -1263,7 +1287,6 @@ class EtatFichesController extends AppController * @param int $organisation_id : ID de l'organisation en session * @param int $fiche_id : ID de la fiche * @param string|null $dataNumero : numero du traitement au registre défini par l'utilisateur - * @param int|null $dataNorme : ID de la norme * @return array * * @access private @@ -1271,16 +1294,12 @@ class EtatFichesController extends AppController * @created 24/09/2020 * @version V2.1.0 */ - private function saveNumeroFicheRegistre($organisation_id, $fiche_id, $dataNumero, $dataNorme) + private function saveNumeroFicheRegistre($organisation_id, $fiche_id, $dataNumero) { if ($dataNumero === 'null') { $dataNumero = null; } - if ($dataNorme === 'null') { - $dataNorme = null; - } - $success = true; $dataReturn = []; @@ -1340,8 +1359,7 @@ class EtatFichesController extends AppController $dataFiche = [ 'id' => $fiche_id, - 'numero' => $numeroGenerate, - 'norme_id' => $dataNorme + 'numero' => $numeroGenerate ]; $success = $success && $this->Fiche->save($dataFiche, ['atomic' => false]) !== false; diff --git a/app/Controller/FichesController.php b/app/Controller/FichesController.php index ad3b3b98f008b4b5c8f416fc572166ac0bd91b59..54abea80e8cbceb653608d326d37a0a432c7488d 100644 --- a/app/Controller/FichesController.php +++ b/app/Controller/FichesController.php @@ -58,6 +58,7 @@ class FichesController extends AppController 'ModelePresentation', 'Norme', 'Organisation', + 'Referentiel', 'Service', 'Soustraitant', 'Soustraitance', @@ -614,6 +615,8 @@ class FichesController extends AppController // Récupère en BDD les normes. Renvoie les normes et les descriptions $this->getNormes(); + $this->getReferentiel(); + // On récupère les types d'annexes $typages = $this->_typages(); @@ -1187,6 +1190,7 @@ class FichesController extends AppController 'user_id', 'form_id', 'norme_id', + 'referentiel_id', 'coresponsable', 'soustraitance', 'obligation_pia', @@ -1204,13 +1208,17 @@ class FichesController extends AppController $this->getFormulaireFields($fiche['Fiche']['form_id'], false); // Récupère en BDD les normes. Renvoie les normes et les descriptions - $this->getNormes(); + $this->getNormes($fiche['Fiche']['norme_id']); + + // Récupère en BDD le référentiel. + $this->getReferentiel($fiche['Fiche']['referentiel_id']); if (empty($this->request->data)) { $this->request->data['Fiche']['user_id'] = $fiche['Fiche']['user_id']; $this->request->data['Fiche']['partage'] = $fiche['Fiche']['partage']; $this->request->data['Fiche']['norme_id'] = $fiche['Fiche']['norme_id']; + $this->request->data['Fiche']['referentiel_id'] = $fiche['Fiche']['referentiel_id']; $this->request->data['Fiche']['coresponsable'] = $fiche['Fiche']['coresponsable']; $this->request->data['Fiche']['soustraitance'] = $fiche['Fiche']['soustraitance']; @@ -1421,6 +1429,21 @@ class FichesController extends AppController ] ]); + if (isset($fiche['Fiche']['referentiel_id'])) { + $referentielTraitement = $this->Referentiel->find('first', [ + 'conditions' => [ + 'id' => $fiche['Fiche']['referentiel_id'] + ], + 'fields' => [ + 'id', + 'name', + 'name_fichier', + 'fichier' + ] + ]); + $this->set(compact('referentielTraitement')); + } + if (isset($fiche['Fiche']['norme_id'])) { $normeTraitement = $this->Norme->find('first', [ 'conditions' => [ @@ -2646,7 +2669,7 @@ class FichesController extends AppController * @version V2.0.0 * @author Théo GUILLON <theo.guillon@libriciel.coop> */ - private function getNormes() + private function getNormes($norme_id = null) { $query = [ 'conditions' => [ @@ -2677,6 +2700,38 @@ class FichesController extends AppController ] ); + if ($norme_id !== null) { + if (array_key_exists($norme_id, $options_normes) === false) { + $normes = $this->Norme->find('all', [ + 'conditions' => [ + 'id' => $norme_id + ], + 'fields' => [ + 'id', + 'norme', + 'numero', + 'libelle', + 'description' + ], + 'order' => [ + 'norme', + 'numero' + ] + ]); + + $options_normes += Hash::combine( + $normes, + '{n}.Norme.id', + [ + '%s-%s : %s', + '{n}.Norme.norme', + '{n}.Norme.numero', + '{n}.Norme.libelle' + ] + ); + } + } + $descriptions_normes = Hash::combine( $normes, '{n}.Norme.id', @@ -2686,6 +2741,40 @@ class FichesController extends AppController $this->set(compact('options_normes', 'descriptions_normes')); } + private function getReferentiel($referentiel_id = null) + { + $query = [ + 'conditions' => [ + 'abroger' => false + ], + 'fields' => [ + 'id', + 'name' + ], + 'order' => [ + 'name ASC' + ] + ]; + $options_referentiel = $this->Referentiel->find('list', $query); + + if ($referentiel_id !== null) { + if (array_key_exists($referentiel_id, $options_referentiel) === false) { + $query = [ + 'conditions' => [ + 'id' => $referentiel_id + ], + 'fields' => [ + 'id', + 'name' + ] + ]; + $options_referentiel = $this->Referentiel->find('list', $query); + } + } + + $this->set(compact('options_referentiel')); + } + /** * Récupére en BDD les options défini dans le formulaire en rapport avec les champs sous-finalité, base légale, * décision automatique, transfert hors ue, données sensible diff --git a/app/Controller/FormulairesController.php b/app/Controller/FormulairesController.php index a64a3f9e351928ea0c74e29382364891763a3a49..4ef80cd3eb713dcdff13571f25c90e2f995558c8 100644 --- a/app/Controller/FormulairesController.php +++ b/app/Controller/FormulairesController.php @@ -28,6 +28,8 @@ class FormulairesController extends AppController 'Champ', 'Formulaire', 'FormulaireOrganisation', + 'Norme', + 'Referentiel', ]; /** @@ -826,9 +828,51 @@ class FormulairesController extends AppController $usefieldsredacteur = $usefieldsredacteur['Organisation']['usefieldsredacteur']; $this->set(compact('usefieldsredacteur')); + $this->_getReferentiel(); + $this->_getNormes(); + $this->view = 'edit'; } + private function _getReferentiel() + { + $options_referentiels = $this->Referentiel->find('list', [ + 'conditions' => [ + 'abroger' => false + ], + 'fields' => [ + 'id', + 'name' + ], + 'order' => [ + 'name ASC' + ] + ]); + $this->set(compact('options_referentiels')); + } + + private function _getNormes() + { + $query = [ + 'conditions' => ['abroger' => false], + 'fields' => ['id', 'norme', 'numero', 'libelle'], + 'order' => ['norme', 'numero'] + ]; + $normes = $this->Norme->find('all', $query); + + $options_normes = Hash::combine( + $normes, + '{n}.Norme.id', + [ + '%s-%s : %s', + '{n}.Norme.norme', + '{n}.Norme.numero', + '{n}.Norme.libelle' + ] + ); + $this->set(compact('options_normes')); + } + private function begnWith($str, $begnString) { $len = strlen($begnString); @@ -1189,6 +1233,9 @@ class FormulairesController extends AppController $this->set('rt_externe', $formulaire['Formulaire']['rt_externe']); $this->set(compact('formulaireOLD', 'soustraitantOLD', 'usefieldsredacteur')); + + $this->_getReferentiel(); + $this->_getNormes(); } /** diff --git a/app/Controller/ModelesController.php b/app/Controller/ModelesController.php index 3b7b830b7a334d5f3cfa6820fdfd249e9fd86456..23a09efed15e4836c593e1d855005539051252b0 100644 --- a/app/Controller/ModelesController.php +++ b/app/Controller/ModelesController.php @@ -632,6 +632,8 @@ class ModelesController extends AppController { 'norme', 'normelibelle', 'normedescription', + 'referentiel', + 'referentieldescription', 'fichecreated', 'fichemodified', ] diff --git a/app/Controller/ReferentielsController.php b/app/Controller/ReferentielsController.php new file mode 100644 index 0000000000000000000000000000000000000000..b8b60da5c3ef534e159ab712a840ff486e6f40cf --- /dev/null +++ b/app/Controller/ReferentielsController.php @@ -0,0 +1,308 @@ +<?php + +App::uses('ListeDroit', 'Model'); + +class ReferentielsController extends AppController +{ + public $uses = [ + 'Referentiel' + ]; + + /** + * Vérification de l'accès aux actions en fonction du profil de l'utilisateur connecté. + * Les vérifications de l'accès aux enregistrements se font dans les méthodes d'actions. + */ + public function beforeFilter() + { + parent::beforeFilter(); + + $action = Inflector::underscore($this->request->params['action']); + $listeDroitIndex = [ + ListeDroit::CREER_REFERENTIEL, + ListeDroit::VISUALISER_REFERENTIEL, + ListeDroit::MODIFIER_REFERENTIEL, + ListeDroit::ABROGER_REFERENTIEL + ]; + + if ($action === 'index') { + $this->Droits->assertAuthorized($listeDroitIndex); + } elseif ($action === 'add') { + $this->Droits->assertAuthorized([ListeDroit::CREER_REFERENTIEL]); + $this->Droits->isSu(); + } elseif ($action === 'edit') { + $this->Droits->assertAuthorized([ListeDroit::MODIFIER_REFERENTIEL]); + $this->Droits->isSu(); + } elseif ($action === 'show') { + $this->Droits->assertAuthorized([ListeDroit::VISUALISER_REFERENTIEL]); + $this->Droits->isSu(); + } elseif ($action === 'abroger') { + $this->Droits->assertAuthorized([ListeDroit::ABROGER_REFERENTIEL]); + $this->Droits->isSu(); + } elseif ($action === 'download') { + $this->Droits->assertAuthorized([ListeDroit::MODIFIER_REFERENTIEL, ListeDroit::VISUALISER_REFERENTIEL]); + $this->Droits->isSu(); + } elseif ($action === 'delete_file_save') { + $this->Droits->assertAuthorized([ListeDroit::MODIFIER_REFERENTIEL]); + $this->Droits->isSu(); + } else { + throw new ForbiddenException(__d('default', 'default.flasherrorPasDroitPage')); + } + } + + public function index() + { + $this->set('title', __d('referentiel', 'referentiel.titreIndex')); + + $query = [ + 'order' => 'Referentiel.name ASC', + 'limit' => 20 + ]; + + $this->paginate = $query; + $referentiels = $this->paginate('Referentiel'); + + $this->set('referentiels', $referentiels); + } + + public function add() + { + $this->set('title', __d('referentiel', 'referentiel.titreAdd')); + + if ($this->request->is('post')) { + if ('Cancel' === Hash::get($this->request->data, 'submit')) { + $this->redirect($this->Referers->get()); + } + + $data = $this->request->data; + $success = true; + $info['message'] = __d('referentiel','referentiel.flasherrorErreurEnregistrementNorme'); + $info['statutMessage'] = 'flasherror'; + + // Tentative de sauvegarde + $this->Referentiel->begin(); + + $this->Referentiel->create([ + 'name' => $data['Referentiel']['name'], + 'description' => $data['Referentiel']['description'] + ]); + $success = $success && false !== $this->Referentiel->save(null, ['atomic' => false]); + + if ($success === true && + isset($data['Referentiel']['fichier']) && + file_exists($data['Referentiel']['fichier']['tmp_name']) + ) { + $info = $this->Referentiel->saveFileReferentiel($data['Referentiel']['fichier'], $this->Referentiel->getLastInsertId()); + $success = false !== $info['success']; + } + + if ($success === true) { + $this->Referentiel->commit(); + $this->Session->setFlash(__d('referentiel', 'referentiel.flashsuccessReferentielEnregistrer'), 'flashsuccess'); + + $this->redirect($this->Referers->get()); + } else { + $this->Referentiel->rollback(); + $this->Session->setFlash($info['message'], $info['statutMessage']); + } + } + + $this->view = 'edit'; + } + + public function edit($id) + { + $this->Droits->assertRecordExists('Referentiel', $id); + + $referentiel = $this->Referentiel->findById($id); + $this->set('title', __d('referentiel', 'referentiel.titreEdit') . $referentiel['Referentiel']['name']); + + if ($this->request->is(['post', 'put'])) { + if ('Cancel' === Hash::get($this->request->data, 'submit')) { + $this->redirect($this->Referers->get()); + + $this->Session->delete('Auth.User.uuid'); + } + + $data = $this->request->data; + + // Tentative de sauvegarde + $this->Referentiel->begin(); + $success = true; + + $this->Referentiel->id = $id; + $this->Referentiel->create([ + 'id' => $id, + 'name' => $data['Referentiel']['name'], + 'description' => $data['Referentiel']['description'] + ]); + $success = $success && false !== $this->Referentiel->save(null, ['atomic' => false]); + + if ($success === true && + isset($data['Referentiel']['fichier']) && + file_exists($data['Referentiel']['fichier']['tmp_name']) + ) { + $info = $this->Referentiel->saveFileReferentiel($data['Referentiel']['fichier'], $this->Referentiel->getLastInsertId()); + $success = false !== $info['success']; + } + + if ($success === true) { + $this->Referentiel->commit(); + $this->Session->setFlash(__d('referentiel', 'referentiel.flashsuccessReferentielEnregistrer'), 'flashsuccess'); + + $this->Session->delete('Auth.User.uuid'); + + $this->redirect($this->Referers->get()); + } else { + $this->Referentiel->rollback(); + $this->Session->setFlash(__d('referentiel', 'referentiel.flasherrorErreurEnregistrementReferentiel'), 'flasherror'); + } + } else { + $this->request->data = $referentiel; + } + + $this->set(compact('referentiel')); + } + + public function show($id) + { + if ('Back' === Hash::get($this->request->data, 'submit')) { + $this->redirect($this->Referers->get()); + } + + $referentiel = $this->Referentiel->find('first', [ + 'conditions' => [ + 'id' => $id + ], + 'fields' => [ + 'name', + 'description', + 'fichier', + 'name_fichier' + ] + ]); + $this->set('title', $referentiel['Referentiel']['name']); + + $this->request->data = $referentiel; + } + + /** + * Fonction qui permet d'abroger d'une norme. + * + * @param int $id + * + * @access public + * + * @created 22/10/2021 + * @version V2.1.1 + * @author Théo GUILLON <theo.guillon@libriciel.coop> + */ + public function abroger($id, $state = null) + { + $this->Droits->assertRecordExists('Referentiel', $id); + + $this->Referentiel->begin(); + + $abroger = (int) !$state; + + $this->Referentiel->id = $id; + $success = $this->Referentiel->updateAll( + [ + 'abroger' => $abroger + ], + [ + 'id' => $id + ] + ) !== false; + + if ($success == true) { + $this->Referentiel->commit(); + + if ($abroger == true) { + $this->Session->setFlash(__d('referentiel', 'referentiel.flashsuccessReferentielAbroger'), 'flashsuccess'); + } else { + $this->Session->setFlash(__d('referentiel', 'referentiel.flashsuccessReferentielRevocationAbroger'), 'flashsuccess'); + } + + $this->redirect($this->Referers->get()); + } else { + $this->Referentiel->rollback(); + $this->Session->setFlash(__d('default', 'default.flasherrorEnregistrementErreur'), 'flasherror'); + } + } + + /** + * Permet de télécharger le fichier sur le serveur + * + * @param string $urlFichier : nom du fichier sur le serveur + * @param string $nameFichier : nom du fichier déposer par l'utilisateur + * @return file téléchargement du fichier + * + * @access public + * + * @created 25/10/2021 + * @version V2.1.1 + * @author Théo GUILLON <theo.guillon@libriciel.coop> + */ + public function download($urlFichier, $nameFichier) + { + $path = CHEMIN_REFERENTIELS . $urlFichier; + if (file_exists($path) === false) { + $path = CHEMIN_NEW_REFERENTIELS . DS . $urlFichier; + if (file_exists($path) === false) { + throw new NotFoundException(); + } + } + + $this->response->file($path, ['download' => true, 'name' => $nameFichier]); + return $this->response; + } + + /** + * Fonction qui permet de supprimer le fichier associé au référentiel + * Supprimer les informations en BDD et le fichier sur le serveur + * + * @param int $id + * @param string $urlFile : nom du fichier sur le serveur + * + * @access public + * + * @created 25/10/2021 + * @version V2.1.1 + * @author Théo GUILLON <theo.guillon@libriciel.coop> + */ + public function deleteFileSave($id, $urlFile) + { + $this->autoRender = false; + + $success = true; + $this->Referentiel->begin(); + + $this->Referentiel->id = $id; + $record = [ + 'id' => $id, + 'fichier' => null, + 'name_fichier' => null + ]; + $success = false !== $this->Referentiel->save($record, ['atomic' => false]) && $success; + + if ($success === true) { + $cheminFile = CHEMIN_REFERENTIELS . $urlFile; + + if (file_exists($cheminFile) === false) { + $cheminFile = CHEMIN_NEW_REFERENTIELS . $urlFile; + } + + $success = unlink($cheminFile); + } + + if ($success == true) { + $this->Referentiel->commit(); + $this->Session->setFlash(__d('referentiel', 'referentiel.flashsuccessFichierSupprimer'), 'flashsuccess'); + } else { + $this->Referentiel->rollback(); + $this->Session->setFlash(__d('referentiel', 'referentiel.flasherrorFichierSupprimer'), 'flasherror'); + } + + $this->redirect($this->Referers->get()); + } +} diff --git a/app/Controller/RegistresController.php b/app/Controller/RegistresController.php index b5e4ee2aa0fcfc4576e89f03cb45af0fd515a3f4..18a82c8c5726c26a74bcd30c58c112918f1e56f9 100644 --- a/app/Controller/RegistresController.php +++ b/app/Controller/RegistresController.php @@ -41,6 +41,7 @@ class RegistresController extends AppController { 'Soustraitant', 'Soustraitance', 'Responsable', + 'Referentiel', 'Coresponsable', 'Typage' ]; @@ -178,6 +179,11 @@ class RegistresController extends AppController { $condition['Fiche.norme_id'] = $this->request->data['Registre']['norme']; } + // Filtre sur un référentiel + if (!empty($this->request->data['Registre']['referentiel'])) { + $condition['Fiche.referentiel_id'] = $this->request->data['Registre']['referentiel']; + } + // Filtre sur les formulaires if (!empty($this->request->data['Registre']['formulaire'])) { $condition['Fiche.form_id'] = $this->request->data['Registre']['formulaire']; @@ -343,6 +349,12 @@ class RegistresController extends AppController { 'description', ], ], + 'Referentiel' => [ + 'fields' => [ + 'id', + 'name' + ], + ], 'Formulaire' => [ 'fields' => [ 'soustraitant' @@ -372,9 +384,6 @@ class RegistresController extends AppController { $this->set(compact('enumsNormes')); $query = [ - 'conditions' => [ - 'abroger' => false - ], 'fields' => ['id', 'norme', 'numero', 'libelle', 'description'], 'order' => ['norme', 'numero'] ]; @@ -391,6 +400,17 @@ class RegistresController extends AppController { ] ); $this->set(compact('options_normes')); + + $options_referentiels = $this->Referentiel->find('list', [ + 'fields' => [ + 'id', + 'name' + ], + 'order' => [ + 'name ASC' + ] + ]); + $this->set(compact('options_referentiels')); foreach ($fichesValid as $key => $value) { if ($value['EtatFiche']['etat_id'] == EtatFiche::ARCHIVER) { @@ -561,8 +581,7 @@ class RegistresController extends AppController { 'controller' => 'etat_fiches', 'action' => 'insertRegistre', $data['Registre']['idfiche'], - $data['Registre']['numero'] ?: 'null', - $data['Registre']['norme'] ?: 'null' + $data['Registre']['numero'] ?: 'null' ]); } } diff --git a/app/Controller/UsersController.php b/app/Controller/UsersController.php index 6709449b30866aa72e3794510a2807b037c2f8e5..2d820838c4647daa2454a0faea4701e77fa43efd 100644 --- a/app/Controller/UsersController.php +++ b/app/Controller/UsersController.php @@ -627,7 +627,8 @@ class UsersController extends AppController { 'organisation_id' => Hash::extract($organisationsUser, '{n}.OrganisationUser.organisation_id') ]; - if (AuthComponent::password($data['User']['old_password']) != $user['User']['password']) { + $passwordHasher = new SimplePasswordHasher(['hashType' => 'sha256']); + if ($passwordHasher->hash($data['User']['old_password']) != $user['User']['password']) { $success = false; $this->User->invalidate('old_password', 'Le mot de passe actuel n\'est pas correct'); } diff --git a/app/Lib/basics.php b/app/Lib/basics.php index 3d543df239b8f135fe92338befb88a5791003a1a..724880ae2c14d8d12d3621cac2ca298c655b25d6 100755 --- a/app/Lib/basics.php +++ b/app/Lib/basics.php @@ -268,7 +268,9 @@ function create_arborescence_files($user_id = null) CHEMIN_CONFIGURATION_LOGIN, CHEMIN_LOGOS, CHEMIN_CERTIFICATS, - CHEMIN_EXTRAIT_REGISTRE_HTML + CHEMIN_EXTRAIT_REGISTRE_HTML, + CHEMIN_REFERENTIELS, + CHEMIN_NEW_REFERENTIELS ]; if ($user_id !== null) { diff --git a/app/Locale/fra/LC_MESSAGES/default.po b/app/Locale/fra/LC_MESSAGES/default.po index a057ba48252cc7b96b6e5521429d6e3f1d0d2ec0..c6f11e076d18bbaafcb810fd5dbafb9ac22849f9 100755 --- a/app/Locale/fra/LC_MESSAGES/default.po +++ b/app/Locale/fra/LC_MESSAGES/default.po @@ -193,6 +193,9 @@ msgstr "Normes" msgid "default.sousTitreLesNormes" msgstr "Les Normes" +msgid "default.sousTitreReferentiels" +msgstr "Référentiels" + msgid "default.titreMaintenance" msgstr "Maintenance" diff --git a/app/Locale/fra/LC_MESSAGES/fiche.po b/app/Locale/fra/LC_MESSAGES/fiche.po index b0d8022c59f9ce13b7ab60901ee74efd9824340f..8e5d46dd93ab3a347bb672aa4d242cbfa2525f42 100755 --- a/app/Locale/fra/LC_MESSAGES/fiche.po +++ b/app/Locale/fra/LC_MESSAGES/fiche.po @@ -153,6 +153,15 @@ msgstr "Informations concernant le traitement :" msgid "fiche.champNorme" msgstr "Norme" +msgid "fiche.champReferentiel" +msgstr "Référentiel" + +msgid "fiche.champReferentieldescription" +msgstr "Description du référentiel" + +msgid "fiche.placeholderChampReferentiel" +msgstr "Choisir un référentiel" + msgid "fiche.champDescriptionNorme" msgstr "Description de la norme" diff --git a/app/Locale/fra/LC_MESSAGES/pannel.po b/app/Locale/fra/LC_MESSAGES/pannel.po index 867515ebb36e9c2e0e2d60df9497030aea549162..0cd5029ce010c80dcaf97fbd07fee8891cd3c288 100755 --- a/app/Locale/fra/LC_MESSAGES/pannel.po +++ b/app/Locale/fra/LC_MESSAGES/pannel.po @@ -238,6 +238,9 @@ msgstr "Sélectionnez un consultant " msgid "pannel.textNorme" msgstr "Norme :" +msgid "pannel.textReferentiel" +msgstr "Référentiel :" + msgid "pannel.btnVoirHistoriqueComplet" msgstr "Visualiser l'historique complet" diff --git a/app/Locale/fra/LC_MESSAGES/referentiel.po b/app/Locale/fra/LC_MESSAGES/referentiel.po new file mode 100644 index 0000000000000000000000000000000000000000..a58a0384b702b3b11991878120b9b20681909e42 --- /dev/null +++ b/app/Locale/fra/LC_MESSAGES/referentiel.po @@ -0,0 +1,120 @@ +msgid "" +msgstr "" +"Project-Id-Version: web-DPO 1.2\n" +"PO-Revision-Date: 2020-04-03 12:00+0100\n" +"Last-Translator: Théo GUILLON <theo.guillon@libriciel.coop>\n" +"Language-Team: Théo GUILLON <theo.guillon@libriciel.coop>\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n>1);\n" + +# ====================================================================================================================== + +####################### Controller/AdminsController.php ####################### + +msgid "referentiel.titreIndex" +msgstr "Liste des référentiels" + +msgid "referentiel.titreAdd" +msgstr "Ajouter un référentiel" + +msgid "referentiel.titreEdit" +msgstr "Modifier le référentiel : " + +############################################################################### + +############################## Session->setFlash ############################## + +#### SUCCESS #### + +msgid "referentiel.flashsuccessReferentielEnregistrer" +msgstr "Le référentiel a bien été enregistré" + +msgid "referentiel.flashsuccessReferentielAbroger" +msgstr "Le référentiel a bien été abroger" + +msgid "referentiel.flashsuccessReferentielRevocationAbroger" +msgstr "La révocation de l'abrogation du référentiel a bien été enregistré" + +msgid "referentiel.flashsuccessFichierSupprimer" +msgstr "Le fichier associé au référentiel à été supprimé" + +################ + +#### ERREUR #### + +msgid "referentiel.flasherrorErreurEnregistrementReferentiel" +msgstr "Une erreur s'est produite lors de l'enregistrement du référentiel" + +msgid "referentiel.flasherrorFichierSupprimer" +msgstr "Une erreur s'est produite lors de la suppression du fichier associé au référentiel" + +################ + +############################################################################### + +######################### View/Referentiels/index.ctp ######################### + +msgid "referentiel.btnFiltrerReferentiel" +msgstr " Filtrer les référentiels" + +msgid "referentiel.btnAjouterReferentiel" +msgstr " Ajouter un référentiel" + +msgid "referentiel.AucunReferentiel" +msgstr "Il n'existe aucun référentiel" + +msgid "referentiel.filtreAucunReferentiel" +msgstr "Il n'existe aucun référentiel pour ces filtres" + +msgid "referentiel.commentaireBtnAbrogerReferentiel" +msgstr "Abroger le référentiel" + +msgid "referentiel.commentaireBtnRevoquerAbrogerReferentiel" +msgstr "Révocation de l'abrogation du référentiel" + +msgid "referentiel.commentaireBtnVisualiserReferentiel" +msgstr "Visualiser le référentiel" + +msgid "referentiel.commentaitreModifierReferentiel" +msgstr "Modifier le référentiel" + +msgid "referentiel.titreTableauEtat" +msgstr "Etat" + +msgid "referentiel.titreTableauLibelle" +msgstr "Libelle" + +msgid "referentiel.titreTableauAction" +msgstr "Actions" + +msgid "referentiel.titreTableauAbroger" +msgstr "Abrogée" + +############################################################################### + +#################### View/Referentiels/edit.ctp | add.ctp #################### + +msgid "referentiel.champName" +msgstr "Titre du référentiel" + +msgid "referentiel.placeholderChampName" +msgstr "Titre du référentiel (requis)" + +msgid "referentiel.champDescription" +msgstr "Description du référentiel" + +msgid "referentiel.placeholderChampDescription" +msgstr "Texte descriptif du référentiel (requis)" + +############################################################################### + +######################### index.ctp | edit.ctp ######################### + +msgid "referentiel.placeholderSelectOrganisation" +msgstr "Sélectionnez une ou plusieurs entité(s) (facultatif)" + +############################################################################### diff --git a/app/Locale/fra/LC_MESSAGES/registre.po b/app/Locale/fra/LC_MESSAGES/registre.po index 0c4db0f341a199fb048b1f60bef2b367fe4db164..4a2f50ca2c614386fc6a1f2d54601bc5e5823248 100755 --- a/app/Locale/fra/LC_MESSAGES/registre.po +++ b/app/Locale/fra/LC_MESSAGES/registre.po @@ -60,6 +60,9 @@ msgstr "Service déclarant : " msgid "registre.textTableauNorme" msgstr "Norme : " +msgid "registre.textTableauReferentiel" +msgstr "Référentiel : " + msgid "registre.textTableauAnnexe" msgstr "Annexe(s) : " @@ -153,6 +156,12 @@ msgstr "Sélectionnez une norme" msgid "registre.filtreNorme" msgstr "Filtrer par norme" +msgid "registre.filtreReferentiel" +msgstr "Filtrer par référentiel" + +msgid "registre.placeholderSelectionnerReferentiel" +msgstr "Sélectionnez un référentiel" + msgid "registre.popupTitreEditionTraitementRegistre" msgstr "Modifier un traitement du registre" @@ -186,6 +195,9 @@ msgstr "Position" msgid "registre.textAucuneNormeDefini" msgstr " Aucune norme n'a été définie" +msgid "registre.textAucunReferentielDefini" +msgstr " Aucun référentiel n'a été défini" + msgid "registre.btnExportCsv" msgstr "Exporter au format .csv" diff --git a/app/Model/Fiche.php b/app/Model/Fiche.php index 2268d6eabf018596fb73cb08b234d8fc42a316fc..363f8b2ad904e0a54ffe42d0c226cedd2a2954e0 100644 --- a/app/Model/Fiche.php +++ b/app/Model/Fiche.php @@ -430,6 +430,11 @@ class Fiche extends AppModel implements LinkedOrganisationInterface { 'className' => 'Service', 'foreignKey' => 'service_id' ], + 'Referentiel' => [ + 'className' => 'Referentiel', + 'foreignKey' => 'referentiel_id', + 'dependent' => true + ] ]; public $hasAndBelongsToMany = [ @@ -968,6 +973,7 @@ class Fiche extends AppModel implements LinkedOrganisationInterface { ], 'fields' => [ 'norme_id', + 'referentiel_id', 'coresponsable', 'created', 'modified', @@ -988,6 +994,10 @@ class Fiche extends AppModel implements LinkedOrganisationInterface { $data = $this->_addNorme($data, $value); break; + case 'referentiel_id': + $data = $this->_addReferentiel($data, $value); + break; + case 'coresponsable': if ($value === true) { $data = $this->_addValueData($data, 'Oui', $key); @@ -1092,6 +1102,35 @@ class Fiche extends AppModel implements LinkedOrganisationInterface { return $data; } + private function _addReferentiel($data, $referentiel_id) + { + $valueReferentiel = ''; + $valueReferentielDescription = ''; + + if (!empty($referentiel_id)) { + $referentiel = $this->Referentiel->find('first', [ + 'conditions' => [ + 'id' => $referentiel_id + ], + 'fields' => [ + 'name', + 'description' + ] + ]); + + if (!empty($referentiel)) { + $valueReferentiel = $referentiel['Referentiel']['name']; + $valueReferentielDescription = nl2br($referentiel['Referentiel']['description']); + $valueReferentielDescription = html_entity_decode(strip_tags(str_replace("<br />", "\n", $valueReferentielDescription))); + } + } + + $data = $this->_addValueData($data, $valueReferentiel,'referentiel'); + $data = $this->_addValueData($data, $valueReferentielDescription,'referentieldescription'); + + return $data; + } + private function _addCoresponsable($data, $fiche_id) { $schemaResponsableFields = array_filter(array_keys($this->Responsable->schema()), function($name) { diff --git a/app/Model/ListeDroit.php b/app/Model/ListeDroit.php index d03e601d6f43e1b87c467485dcce4acedee9c561..773067aa02f1089ae6aa2eddb05714a266128a11 100644 --- a/app/Model/ListeDroit.php +++ b/app/Model/ListeDroit.php @@ -66,6 +66,10 @@ class ListeDroit extends AppModel { const INITIALISATION_TRAITEMENT = 37; // Initialisation d'un traitement const GENERER_TRAITEMENT_EN_COURS = 38; // Génération d'un traitement en cours de rédaction (hors registre) const MODIFIER_TRAITEMENT_CONSULTATION = 39; // Modifier un traitement lors de la reception en demande d'avis + const CREER_REFERENTIEL = 40; // Créer un référentiel + const VISUALISER_REFERENTIEL = 41; // Visualiser un référentiel + const MODIFIER_REFERENTIEL = 42; // Modifier un référentiel + const ABROGER_REFERENTIEL = 43; // Abroger un référentiel const LISTE_DROITS_ADMINISTRATEUR = [ ListeDroit::REDIGER_TRAITEMENT, @@ -101,6 +105,10 @@ class ListeDroit extends AppModel { ListeDroit::GESTION_SOUSTRAITANT_TRAITEMENT, ListeDroit::DUPLIQUER_TRAITEMENT, ListeDroit::GENERER_TRAITEMENT_EN_COURS, + ListeDroit::CREER_REFERENTIEL, + ListeDroit::VISUALISER_REFERENTIEL, + ListeDroit::MODIFIER_REFERENTIEL, + ListeDroit::ABROGER_REFERENTIEL, ]; const LISTE_DROITS_REDACTEUR = [ @@ -108,7 +116,8 @@ class ListeDroit extends AppModel { ListeDroit::CONSULTER_REGISTRE, ListeDroit::TELECHARGER_TRAITEMENT_REGISTRE, ListeDroit::VISUALISER_NORME, - ListeDroit::CONSULTER_ARTICLE_FAQ + ListeDroit::CONSULTER_ARTICLE_FAQ, + ListeDroit::VISUALISER_REFERENTIEL ]; const LISTE_DROITS_VALIDEUR = [ @@ -116,7 +125,8 @@ class ListeDroit extends AppModel { ListeDroit::CONSULTER_REGISTRE, ListeDroit::TELECHARGER_TRAITEMENT_REGISTRE, ListeDroit::VISUALISER_NORME, - ListeDroit::CONSULTER_ARTICLE_FAQ + ListeDroit::CONSULTER_ARTICLE_FAQ, + ListeDroit::VISUALISER_REFERENTIEL ]; const LISTE_DROITS_CONSULTANT = [ @@ -124,7 +134,8 @@ class ListeDroit extends AppModel { ListeDroit::CONSULTER_REGISTRE, ListeDroit::VISUALISER_NORME, ListeDroit::CONSULTER_ARTICLE_FAQ, - ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION + ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION, + ListeDroit::VISUALISER_REFERENTIEL ]; const LISTE_DROITS_DPO = [ @@ -164,7 +175,11 @@ class ListeDroit extends AppModel { ListeDroit::DUPLIQUER_TRAITEMENT, ListeDroit::INITIALISATION_TRAITEMENT, ListeDroit::GENERER_TRAITEMENT_EN_COURS, - ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION + ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION, + ListeDroit::CREER_REFERENTIEL, + ListeDroit::VISUALISER_REFERENTIEL, + ListeDroit::MODIFIER_REFERENTIEL, + ListeDroit::ABROGER_REFERENTIEL, ]; const LISTE_DROITS_DPO_MINIMUM = [ @@ -191,7 +206,11 @@ class ListeDroit extends AppModel { ListeDroit::DUPLIQUER_TRAITEMENT, ListeDroit::INITIALISATION_TRAITEMENT, ListeDroit::GENERER_TRAITEMENT_EN_COURS, - ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION + ListeDroit::MODIFIER_TRAITEMENT_CONSULTATION, + ListeDroit::CREER_REFERENTIEL, + ListeDroit::VISUALISER_REFERENTIEL, + ListeDroit::MODIFIER_REFERENTIEL, + ListeDroit::ABROGER_REFERENTIEL, ]; /** diff --git a/app/Model/Referentiel.php b/app/Model/Referentiel.php new file mode 100644 index 0000000000000000000000000000000000000000..40b192eaa4df152b26c73d4874f221e94efb9386 --- /dev/null +++ b/app/Model/Referentiel.php @@ -0,0 +1,72 @@ +<?php + +App::uses('AppModel', 'Model'); +App::uses('LinkedOrganisationInterface', 'Model/Interface'); + +class Referentiel extends AppModel +{ + public $name = 'Referentiel'; + + public $validationDomain = 'validation'; + + public $validate = [ + 'libelle' => [ + 'isUniqueMultiple' => [ + 'rule' => 'isUnique', + 'message' => 'validation.valeurDejaUtilisee' + ] + ] + ]; + + public $hasMany = [ + 'Fiche' => [ + 'className' => 'Fiche', + 'foreignKey' => 'fiche_id' + ] + ]; + + /** + * Enregistrement du fichier sur le disque et en BDD + * + * @param array $file + * @param int $referentiel_id + * @return array + * @throws Exception + * + * @access public + * + * @created 21/10/2021 + * @author Théo GUILLON <theo.guillon@libriciel.coop> + * @version V2.1.1 + */ + public function saveFileReferentiel($file, $referentiel_id) + { + $infoFile = $this->saveFileOnDisk( + $file, + ['application/pdf'], + '.pdf', + CHEMIN_NEW_REFERENTIELS + ); + + if ($infoFile['success'] == true) { + $this->id = $referentiel_id; + $record = [ + 'fichier' => $infoFile['nameFile'], + 'name_fichier' => $infoFile['name'] + ]; + $success = $this->save($record, ['atomic' => false]); + + if ($success == false) { + $infoFile = [ + 'success' => false, + 'nameFile' => null, + 'name' => null, + 'message' => __d('referentiel','referentiel.flasherrorErreurEnregistrementNorme'), + 'statutMessage' => 'flasherror' + ]; + } + } + + return $infoFile; + } +} diff --git a/app/View/Elements/Buttons/abroger.ctp b/app/View/Elements/Buttons/abroger.ctp new file mode 100644 index 0000000000000000000000000000000000000000..34f18fccbcf54a80497ded10fa80c982fe4e60ab --- /dev/null +++ b/app/View/Elements/Buttons/abroger.ctp @@ -0,0 +1,25 @@ +<?php +$controller = isset($controller) ? $controller : null; +$action = isset($action) ? $action : 'abroger'; +$id = isset($id) ? $id : null; +$active = isset($active) ? $active : null; +$titleBtn = isset($titleBtn) ? $titleBtn : null; + +if ($active === true) { + $icon = "fa-toggle-off"; + $class = "btn-outline-success borderless"; +} else { + $icon = "fa-toggle-on"; + $class = "btn-outline-danger borderless"; +} + +echo $this->Html->link('<i class="fas '.$icon.' fa-lg"></i>', [ + 'controller' => $controller, + 'action' => $action, + $id, + $active + ], [ + 'class' => 'btn ' . $class, + 'title' => $titleBtn, + 'escape' => false +]); diff --git a/app/View/Elements/Fiches/tabs/formulaire.ctp b/app/View/Elements/Fiches/tabs/formulaire.ctp index 2ab844a5fc0b562614954d55e3520fc3f7e8937c..fbdbd7afd01e8bc6a15d02dff1a4714f508e2189 100644 --- a/app/View/Elements/Fiches/tabs/formulaire.ctp +++ b/app/View/Elements/Fiches/tabs/formulaire.ctp @@ -291,10 +291,8 @@ $line = 1; // Si le champ a comme balise "select" (deroulant et multi-select) if ($(valueIfTheField).is('select')) { - + // Champ multi-select if ($(valueIfTheField).hasClass('multi-select2') === true) { - // Champ multi-select - // Si le champ multi-select est visible $(valueIfTheField).parent().parent().on('show', function() { let showCondition = false; @@ -320,22 +318,25 @@ $line = 1; }); if ($(valueIfTheField).parent().parent().css('display') !== 'none') { - $.each($(valueIfTheField).val(), function (k, v) { - if (jQuery.inArray(v, value['hasValue']) !== -1 && - $(valueIfTheField).parent().parent().css('display') !== 'none' - ) { - shownHideField(value['mustBe'], value['thenTheField']) - } else { - shownHideField(value['ifNot'], value['thenTheField']); - } - }); + let ifTheField_val = $(valueIfTheField).val(); + + if (ifTheField_val) { + $.each(ifTheField_val, function (k, v) { + if (jQuery.inArray(v, value['hasValue']) !== -1 && + $(valueIfTheField).parent().parent().css('display') !== 'none' + ) { + shownHideField(value['mustBe'], value['thenTheField']) + } else { + shownHideField(value['ifNot'], value['thenTheField']); + } + }); + } else { + shownHideField(value['ifNot'], value['thenTheField']); + } } else { shownHideField(value['ifNot'], value['thenTheField']); } - } else { - // Champ deroulant - // Si le champ déroulant est visible $(valueIfTheField).parent().parent().on('show', function() { if ($(valueIfTheField).val() === value['hasValue']) { @@ -392,21 +393,23 @@ $line = 1; // Si le champ a comme balise "input" if ($(valueIfTheField).is('input')) { + let valuehasValue = $('#'+value['hasValue']); + // Si le champ est de type "checkbox" - if ($('#'+value['hasValue']).attr('type') === "checkbox") { - $('#'+value['hasValue']).parent().parent().parent().on('show', function() { - if ($('#'+value['hasValue']).prop("checked") == true) { + if ($(valuehasValue).attr('type') === "checkbox") { + $(valuehasValue).parent().parent().parent().on('show', function() { + if ($(valuehasValue).prop("checked") === true) { shownHideField(value['mustBe'], value['thenTheField']) } else { shownHideField(value['ifNot'], value['thenTheField']); } }); - $('#'+value['hasValue']).parent().parent().parent().on('hide', function() { + $(valuehasValue).parent().parent().parent().on('hide', function() { shownHideField(value['ifNot'], value['thenTheField']); }); - if ($('#'+value['hasValue']).prop("checked") === true && + if ($(valuehasValue).prop("checked") === true && $(valueIfTheField).parent().parent().css('display') !== 'none' ) { shownHideField(value['mustBe'], value['thenTheField']) @@ -488,7 +491,6 @@ $line = 1; $('#' + thenTheField).parent().parent().show(); } else { $('#' + thenTheField).parent().parent().hide(); - // $('#' + thenTheField).val(''); } resizeFormContainer(); diff --git a/app/View/Elements/Fiches/tabs/informationGenerale.ctp b/app/View/Elements/Fiches/tabs/informationGenerale.ctp index f0073f61269a4c17b75370f1892f0408003c45fa..959f04a3d2f8a9707943213f48128db08d6fcd38 100644 --- a/app/View/Elements/Fiches/tabs/informationGenerale.ctp +++ b/app/View/Elements/Fiches/tabs/informationGenerale.ctp @@ -161,25 +161,123 @@ if ($usefieldsredacteur === true) { </div> <?php } - ?> - <!-- Information sur la norme --> - <div class="col-md-12"> - <span class='labelFormulaire'> - <?php - echo __d('fiche', 'fiche.textInfoNorme'); - ?> - </span> - <div class="row row35"></div> - </div> + if (!empty($options_referentiel)) { + $valueReferentiel = null; + ?> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo 'Informations concernant le référentiel à associer au traitement :'; + ?> + </span> + <div class="row row35"></div> + </div> + + <?php + if (isset($this->request->data['Fiche']['referentiel_id'])) { + $valueReferentiel = $this->request->data['Fiche']['referentiel_id']; + } + ?> + + <div class="row"> + <div class="col-md-12"> + <?php + echo $this->WebcilForm->input('referentiel_id', [ + 'id' => 'referentiel_id', + 'label' => [ + 'text' => __d('fiche', 'fiche.champReferentiel') + ], + 'options' => $options_referentiel, + 'class' => 'usersDeroulant form-control', + 'empty' => true, + 'placeholder' => false, + 'data-placeholder' => __d('fiche', 'fiche.placeholderChampReferentiel'), + 'value' => $valueReferentiel + ]); + ?> + </div> + </div> + <?php + } + + if (isset($referentielTraitement) && !empty($referentielTraitement)) { + ?> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo 'Informations concernant le référentiel associé au traitement :'; + ?> + </span> + <div class="row row35"></div> + </div> + + <div class="row"> + <div class="col-md-12"> + <?php + echo $this->WebcilForm->input('showreferentiel', [ + 'id' => 'showreferentiel', + 'label' => [ + 'text' => __d('fiche', 'fiche.champReferentiel') + ], + 'readonly' => true, + 'placeholder' => false, + 'value' => $referentielTraitement['Referentiel']['name'] + ]); + ?> + </div> + </div> + + <table class="table" id="renderReferentiel"> + <thead></thead> + <tbody> + <tr class="d-flex"> + <td class="col-md-1"> + <i class="far fa-file-alt fa-lg"></i> + </td> + + <td class="col-md-9"> + <?php + echo $referentielTraitement['Referentiel']['name_fichier']; + ?> + </td> + + <td class="col-md-2"> + <?php + echo $this->Html->link('<i class="fa fa-download fa-lg"></i>', [ + 'controller' => 'referentiels', + 'action' => 'download', + $referentielTraitement['Referentiel']['fichier'], + $referentielTraitement['Referentiel']['name_fichier'] + ], [ + 'class' => 'btn btn-outline-dark borderless boutonShow btn-sm my-tooltip', + 'title' => 'Télécharger le référentiel', + 'escapeTitle' => false + ]); + ?> + </td> + </tr> + </tbody> + </table> + <?php + } - <?php $valueNorme = null; if (isset($normeTraitement) && !empty($normeTraitement)) { $norme = $normeTraitement['Norme']['norme'] . '-' . sprintf('%03d', $normeTraitement['Norme']['numero']) . ' : ' . $normeTraitement['Norme']['libelle']; $normeDescription = preg_replace('@<[^>]*?>.*?>@si', "\n\r", $normeTraitement['Norme']['description']); ?> + <!-- Information sur la norme --> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo ("Informations concernant la norme associée au traitement : "); + ?> + </span> + <div class="row row35"></div> + </div> + <div class="row"> <!-- Colonne de gauche --> <div class="col-md-6"> @@ -213,7 +311,7 @@ if ($usefieldsredacteur === true) { $normeTraitement['Norme']['fichier'], $normeTraitement['Norme']['name_fichier'] ], [ - 'class' => 'btn btn-outline-dark boutonShow btn-sm my-tooltip', + 'class' => 'btn btn-outline-dark borderless boutonShow btn-sm my-tooltip', 'title' => 'Télécharger la norme', 'escapeTitle' => false ]); @@ -239,43 +337,58 @@ if ($usefieldsredacteur === true) { </div> <?php } else { - if (isset($this->request->data['Fiche']['norme_id'])) { - $valueNorme = $this->request->data['Fiche']['norme_id']; - } - ?> - <div class="row"> - <!-- Colonne de gauche --> - <div class="col-md-6"> - <?php - echo $this->WebcilForm->input('norme_id', [ - 'id' => 'norme_id', - 'label' => [ - 'text' => __d('fiche', 'fiche.champNorme') - ], - 'options' => $options_normes, - 'class' => 'usersDeroulant form-control', - 'empty' => true, - 'placeholder' => false, - 'data-placeholder' => __d('norme', 'norme.placeholderFiltreNorme'), - 'value' => $valueNorme - ]); - ?> + if (!empty($options_normes)) { + ?> + <!-- Information sur la norme --> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo __d('fiche', 'fiche.textInfoNorme'); + ?> + </span> + <div class="row row35"></div> </div> - <!-- Colonne de droite --> - <div class="col-md-6"> - <?php - echo $this->WebcilForm->input('descriptionNorme', [ - 'id' => 'descriptionNorme', - 'type' => 'textarea', - 'readonly' => true, - 'disabled' => true, - 'placeholder' => false - ]); - ?> + <?php + if (isset($this->request->data['Fiche']['norme_id'])) { + $valueNorme = $this->request->data['Fiche']['norme_id']; + } + ?> + + <div class="row"> + <!-- Colonne de gauche --> + <div class="col-md-6"> + <?php + echo $this->WebcilForm->input('norme_id', [ + 'id' => 'norme_id', + 'label' => [ + 'text' => __d('fiche', 'fiche.champNorme') + ], + 'options' => $options_normes, + 'class' => 'usersDeroulant form-control', + 'empty' => true, + 'placeholder' => false, + 'data-placeholder' => __d('norme', 'norme.placeholderFiltreNorme'), + 'value' => $valueNorme + ]); + ?> + </div> + + <!-- Colonne de droite --> + <div class="col-md-6"> + <?php + echo $this->WebcilForm->input('descriptionNorme', [ + 'id' => 'descriptionNorme', + 'type' => 'textarea', + 'readonly' => true, + 'disabled' => true, + 'placeholder' => false + ]); + ?> + </div> </div> - </div> - <?php + <?php + } } ?> diff --git a/app/View/Elements/Filtres/filtresTraitements.ctp b/app/View/Elements/Filtres/filtresTraitements.ctp index fa48f9006fba97f1eba52f8c8900cf0d6a7b8086..59ae7230e0e897362fe73164f0b391f8e962edc7 100644 --- a/app/View/Elements/Filtres/filtresTraitements.ctp +++ b/app/View/Elements/Filtres/filtresTraitements.ctp @@ -59,25 +59,6 @@ $showForRegistre = isset($showForRegistre) ? $showForRegistre : false; 'before' => '<div class="form-group">', 'after' => '</div>' ]); - - if ($showForRegistre === true) { - // Filtre sur le nombre de traitement à l'affichage - echo $this->Form->input('nbAffichage', [ - 'options' => [ - PHP_INT_MAX => 'Tous les traitements', - 10 => '10', - 20 => '20', - 50 => '50', - 100 => '100' - ], - 'class' => 'usersDeroulant form-control', - 'label' => __d('registre', 'registre.filtreNbAffichageTraitement'), - 'data-placeholder' => __d('registre', 'registre.placeholderSelectionnerNbTraitementAfficher'), - 'empty' => false, - 'before' => '<div class="form-group">', - 'after' => '</div>' - ]); - } ?> </div> @@ -91,7 +72,15 @@ $showForRegistre = isset($showForRegistre) ? $showForRegistre : false; 'before' => '<div class="form-group">', 'after' => '</div>' ]); + ?> + </div> + </div> + <br/> + + <div class="row col-md-12"> + <div class="col-md-6"> + <?php // Filtre sur les normes echo $this->Form->input('norme', [ 'options' => $options_normes, @@ -102,7 +91,53 @@ $showForRegistre = isset($showForRegistre) ? $showForRegistre : false; 'before' => '<div class="form-group">', 'after' => '</div>' ]); + ?> + </div> + + <div class="col-md-6"> + <?php + // Filtre sur les référentiels + echo $this->Form->input('referentiel', [ + 'options' => $options_referentiels, + 'class' => 'usersDeroulant form-control', + 'label' => __d('registre', 'registre.filtreReferentiel'), + 'data-placeholder' => __d('registre', 'registre.placeholderSelectionnerReferentiel'), + 'empty' => true, + 'before' => '<div class="form-group">', + 'after' => '</div>' + ]); + ?> + </div> + </div> + + <br/> + + <div class="row col-md-12"> + <div class="col-md-6"> + <?php + if ($showForRegistre === true) { + // Filtre sur le nombre de traitement à l'affichage + echo $this->Form->input('nbAffichage', [ + 'options' => [ + PHP_INT_MAX => 'Tous les traitements', + 10 => '10', + 20 => '20', + 50 => '50', + 100 => '100' + ], + 'class' => 'usersDeroulant form-control', + 'label' => __d('registre', 'registre.filtreNbAffichageTraitement'), + 'data-placeholder' => __d('registre', 'registre.placeholderSelectionnerNbTraitementAfficher'), + 'empty' => false, + 'before' => '<div class="form-group">', + 'after' => '</div>' + ]); + } + ?> + </div> + <div class="col-md-6"> + <?php // Filtre par ordre d'affichage if ($showForRegistre === true) { echo $this->Form->input('order', [ diff --git a/app/View/Elements/Formulaires/champDuFormulaire.ctp b/app/View/Elements/Formulaires/champDuFormulaire.ctp index 6b940efabdca8b56ce85b38bbd9b8fcd5b489198..346b4fe73bc797a104404f99716e1ee27e3e0ef3 100644 --- a/app/View/Elements/Formulaires/champDuFormulaire.ctp +++ b/app/View/Elements/Formulaires/champDuFormulaire.ctp @@ -195,12 +195,12 @@ foreach ($champs as $key => $value) { foreach ($details['options'] as $key => $val) { $selected = ""; if (isset($details['default'])) { - if ($details['default'] == $key) { + if ($details['default'] === strval($key)) { $selected = "selected"; } } - echo '<option id="'.$details['name'].$key.'" class="champNomVariableReadonly" type="deroulant" '.$selected.' name ="'.$details['name'].'" value="'.$key.'">'.$val.'</option></div>'; + echo '<option id="'.$details['name'].$key.'" class="champNomVariableReadonly" type="deroulant" '.$selected.' name ="'.$details['name'].'" value="'.$key.'">'.$val.'</option>'; } echo '</select>' . '</div>' diff --git a/app/View/Elements/Formulaires/tabs/informationGenerale.ctp b/app/View/Elements/Formulaires/tabs/informationGenerale.ctp index 0428dae482fca1def1db58b9413bd92dd76a3841..0c2e23863928f9a380155f72c626053120764419 100644 --- a/app/View/Elements/Formulaires/tabs/informationGenerale.ctp +++ b/app/View/Elements/Formulaires/tabs/informationGenerale.ctp @@ -79,6 +79,83 @@ if (!isset($usefieldsredacteur)) { </div> </div> + <?php + if (!empty($options_referentiels)) { + ?> + <!-- Information sur le référentiel --> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo 'Informations concernant le référentiel à associer au traitement :'; + ?> + </span> + <div class="row row35"></div> + </div> + + <div class="row"> + <div class="col-md-12"> + <?php + echo $this->WebcilForm->input('Fiche.referentiel_id', [ + 'id' => 'referentiel_id', + 'label' => [ + 'text' => __d('fiche', 'fiche.champReferentiel') + ], + 'options' => $options_referentiels, + 'readonly' => true, + 'empty' => true, + 'placeholder' => false, + ]); + ?> + </div> + </div> + <?php + } + + if (!empty($options_normes)) { + ?> + <!-- Information sur la norme --> + <div class="col-md-12"> + <span class='labelFormulaire'> + <?php + echo __d('fiche', 'fiche.textInfoNorme'); + ?> + </span> + <div class="row row35"></div> + </div> + + <div class="row"> + <!-- Colonne de gauche --> + <div class="col-md-6"> + <?php + echo $this->WebcilForm->input('Fiche.norme_id', [ + 'id' => 'norme_id', + 'label' => [ + 'text' => __d('fiche', 'fiche.champNorme') + ], + 'options' => $options_normes, + 'readonly' => true, + 'empty' => true, + 'placeholder' => false, + ]); + ?> + </div> + + <!-- Colonne de droite --> + <div class="col-md-6"> + <?php + echo $this->WebcilForm->input('Fiche.descriptionNorme', [ + 'id' => 'descriptionNorme', + 'type' => 'textarea', + 'readonly' => true, + 'placeholder' => false, + ]); + ?> + </div> + </div> + <?php + } + ?> + <!-- Information concernant le traitement --> <div class="col-md-12"> <span class='labelFormulaire'> diff --git a/app/View/Elements/Pannel/modalAddCommentaire.ctp b/app/View/Elements/Pannel/modalAddCommentaire.ctp new file mode 100644 index 0000000000000000000000000000000000000000..accd55318e38f3ed1d0471a54c5fefc2282cad02 --- /dev/null +++ b/app/View/Elements/Pannel/modalAddCommentaire.ctp @@ -0,0 +1,54 @@ +<?php +$body = $this->WebcilForm->inputs([ + 'EtatFiche.commentaire' => [ + 'label' => [ + 'text' => 'Commentaire', + ], + 'class' => 'form-control reponseStartTinyMCE', + 'required' => true, + 'placeholder' => false, + 'type' => 'textarea' + ], + 'EtatFiche.idUserCommentaire' => [ + 'type' => 'hidden', + 'value' => json_encode($idUserCommentaire) + ], + 'EtatFiche.etat_fiche_id' => [ + 'type' => 'hidden', + 'value' => $id + ], + 'EtatFiche.fiche_id' => [ + 'type' => 'hidden', + 'value' => $fiche_id + ], +]); + +$footer = '<div class="buttons">' + . $this->WebcilForm->button("<i class='fa fa-times-circle fa-lg'></i>" . __d('default', 'default.btnCancel'), [ + 'type' => 'submit', + 'data-dismiss' => 'modal', + 'class' => 'btn btn-outline-primary', + 'escape' => false, + ]) + . ' ' + . $this->WebcilForm->button("<i class='fa fa-paper-plane fa-lg'></i>" . __d('default', 'default.btnSend'), [ + 'type' => 'submit', + 'class' => 'btn btn-outline-success', + 'escape' => false + ]) + .'</div>' +; + +$content = [ + 'title' => __d('formulaire', 'formulaire.modalTitleRepondreCommentaire'), + 'body' => $body, + 'footer' => $footer, +]; + +echo $this->element('modal', [ + 'modalId' => 'AddCommentaire', + 'controller' => 'EtatFiches', + 'action' => 'repondreCommentaire', + 'content' => $content, + 'sizeModal' => 'modal-xl' +]); diff --git a/app/View/Elements/Pannel/modalValidDpo.ctp b/app/View/Elements/Pannel/modalValidDpo.ctp index b901d20e09893f1ddbca62b1f7f0d7c7f23334de..90a2ffa836ecc7e30c38ba44529278fe79319e91 100644 --- a/app/View/Elements/Pannel/modalValidDpo.ctp +++ b/app/View/Elements/Pannel/modalValidDpo.ctp @@ -1,5 +1,6 @@ <?php -if ($this->Autorisation->isDpo() && !empty($options_normes)) { +//if ($this->Autorisation->isDpo() && !empty($options_normes)) { +if ($this->Autorisation->isDpo()) { echo $this->element( 'modal', [ @@ -42,17 +43,6 @@ if ($this->Autorisation->isDpo() && !empty($options_normes)) { ], 'placeholder' => false ]) - . $this->WebcilForm->input('Registre.norme', [ - 'id' => 'norme', - 'label' => [ - 'text' => 'Type de déclaration', - 'class' => 'control-label' - ], - 'options' => $options_normes, - 'data-placeholder' => __d('norme', 'norme.placeholderFiltreNorme'), - 'class' => 'usersDeroulant transformSelect form-control', - 'empty' => true - ]) . $this->WebcilForm->hidden('idfiche', ['id' => 'idFiche']), ['class' => 'col-md-12 form-horizontal'] ), diff --git a/app/View/Elements/parcours.ctp b/app/View/Elements/parcours.ctp index a66a190c7c9f2394c362c31d92beb6a70aee9188..5432a3af5f70c2d76ea3972bf20c0e3a295383f9 100755 --- a/app/View/Elements/parcours.ctp +++ b/app/View/Elements/parcours.ctp @@ -28,7 +28,6 @@ $cle[] = $key; } } - foreach ($cle as $value) { unset($parcours[$value]); } @@ -141,8 +140,8 @@ ?> </div> <?php + $idUserCommentaire = []; if (!empty($value['Commentaire'])) { - $idUserCommentaire = []; ?> <div> <br/> @@ -195,95 +194,17 @@ </button> </div> </div> - - <div class="modal fade" id="AddCommentaire" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">×</span> - </button> - <h4 class="modal-title" id="myModalLabel"> - <?php - echo __d('formulaire', 'formulaire.modalTitleRepondreCommentaire'); - ?> - </h4> - </div> - - <div class="modal-body"> - <?php - //pop-up de création de formulaire - echo $this->Form->create('EtatFiche', [ - 'url' => [ - 'action' => 'repondreCommentaire' - ], - 'class' => 'search-form' - ]); - - echo '<div class="row form-group">'; - //Champ Description - echo $this->Form->input('commentaire', [ - 'type' => 'textarea', - 'class' => 'form-control', - 'placeholder' => __d('formulaire', 'formulaire.popupPlaceholderDescription'), - 'label' => [ - 'text' => "Commentaire" .' '. '<span class="requis">*</span>', - 'class' => 'col-md-4 control-label' - ], - 'between' => '<div class="col-md-8">', - 'after' => '</div>', - 'required' => true - ]); - - echo $this->Form->input('idUserCommentaire', [ - 'type' => 'hidden', - 'value' => json_encode($idUserCommentaire) - ]); - - echo $this->Form->input('etat_fiche_id', [ - 'type' => 'hidden', - 'value' => $value['EtatFiche']['id'] - ]); - - echo $this->Form->input('fiche_id', [ - 'type' => 'hidden', - 'value' => $value['EtatFiche']['fiche_id'] - ]); - - echo '</div>' - ?> - </div> - - <div class="modal-footer"> - <div class="buttons"> - <button type="button" class="btn btn-outline-primary" data-dismiss="modal"> - <i class="fa fa-times-circle fa-lg"></i> - <?php - echo __d('default', 'default.btnCancel'); - ?> - </button> - - <?php - echo $this->Form->button("<i class='fa fa-paper-plane fa-lg'></i>" . __d('default', 'default.btnSend'), [ - 'type' => 'submit', - 'class' => 'btn btn-outline-success', - 'escape' => false - ]); - ?> - </div> - <?php - echo $this->Form->end(); - ?> - </div> - </div> - </div> - </div> </div> <?php } ?> </div> <?php + echo $this->element('Pannel/modalAddCommentaire', [ + 'idUserCommentaire' => $idUserCommentaire, + 'id' => $value['EtatFiche']['id'], + 'fiche_id' => $value['EtatFiche']['fiche_id'] + ]); break; //Rectangle vert Validée diff --git a/app/View/Elements/second_header.ctp b/app/View/Elements/second_header.ctp index c954be0a3271fe0aaf9bd4ab707cd321f97ce5ce..8b4440817adb220a095802e06423bd619e9b2175 100644 --- a/app/View/Elements/second_header.ctp +++ b/app/View/Elements/second_header.ctp @@ -292,6 +292,14 @@ $items = [ 'action' => 'index' ] ], +// __d('default', 'default.sousTitreReferentiels') => [ +// 'disabled' => !($this->Autorisation->authorized(['40', '42', '43'], $this->Session->read('Droit.liste'))), +// 'icon' => 'fas fa-certificate', +// 'url' => [ +// 'controller' => 'referentiels', +// 'action' => 'index' +// ] +// ], __d('default', 'default.titreSousTraitant') => [ 'disabled' => !($this->Autorisation->authorized(['23'], $this->Session->read('Droit.liste'))), __d('default', 'default.sousTitreLesSousTraitants') => [ @@ -344,7 +352,6 @@ $items = [ ] ], ], - __d('default', 'default.sousTitreLesNormes') => [ 'disabled' => !($this->Autorisation->authorized(['20'], $this->Session->read('Droit.liste'))) || ($this->Session->read('Su')), 'icon' => 'fas fa-certificate', @@ -352,6 +359,14 @@ $items = [ 'controller' => 'normes', 'action' => 'index' ] + ], + __d('default', 'default.sousTitreReferentiels') => [ + 'disabled' => !($this->Autorisation->authorized(['40', '41', '42', '43'], $this->Session->read('Droit.liste'))) || ($this->Session->read('Su')), + 'icon' => 'fas fa-certificate', + 'url' => [ + 'controller' => 'referentiels', + 'action' => 'index' + ] ] ]; diff --git a/app/View/Elements/second_header_superadmin.ctp b/app/View/Elements/second_header_superadmin.ctp index 951541a2cd24b8e978295520cd3b9bd92afb3c78..a9f571a3042c6fab27f3746bfebac77b72683ade 100644 --- a/app/View/Elements/second_header_superadmin.ctp +++ b/app/View/Elements/second_header_superadmin.ctp @@ -54,6 +54,13 @@ $items = [ 'action' => 'index' ] ], + __d('default', 'default.sousTitreReferentiels') => [ + 'icon' => 'fas fa-certificate', + 'url' => [ + 'controller' => 'referentiels', + 'action' => 'index' + ] + ], __d('default', 'default.sousTitreGestionPolitiqueConfidentialite') => [ 'icon' => 'fas fa-user-secret', 'url' => [ diff --git a/app/View/Helper/BanettesHelper.php b/app/View/Helper/BanettesHelper.php index 1edb1edab00d91bba6c746812693d6d4739b99b0..aa8ac77b9089400fb4acecf03203fa10a3b8a113 100755 --- a/app/View/Helper/BanettesHelper.php +++ b/app/View/Helper/BanettesHelper.php @@ -1034,6 +1034,12 @@ class BanettesHelper extends AppHelper { $norme = __d('registre', 'registre.textAucuneNormeDefini'); } + if (!empty($result['Referentiel']['id'])) { + $referentiel = $result['Referentiel']['name']; + } else { + $referentiel = __d('registre', 'registre.textAucunReferentielDefini'); + } + if ($result['Fiche']['transfert_hors_ue'] === true) { $etatTransfertHorsUe = $this->Html->tag('i', '', ['class' => 'fas fa-check fa-lg fa-success']); } else { @@ -1189,6 +1195,8 @@ class BanettesHelper extends AppHelper { . '<strong>' . __d('registre', "registre.textTableauServiceDeclarant") . '</strong>'. $declarantServiceTraitement . '<br/>' . '<strong>' . __d('pannel', "pannel.textNorme") . '</strong>' . $norme + . '<br/>' + . '<strong>' . __d('pannel', "pannel.textReferentiel") . '</strong>' . $referentiel . '<br/>', ['class' => 'tdleft'] ], diff --git a/app/View/Modeles/info_variable.ctp b/app/View/Modeles/info_variable.ctp index daeb5e3f0c936a13aca53970487b4eb39ead96e8..0fbf6c5b01f164fc2982e3b820f4f7490e00701d 100755 --- a/app/View/Modeles/info_variable.ctp +++ b/app/View/Modeles/info_variable.ctp @@ -296,43 +296,43 @@ if (!empty($valeurPropreTraitement['traitement'])) { </h4> <thead> - <tr> - <th class="thleft col-md-10"> - <?php - echo __d('modele', 'modele.titreTableauNomChamp'); - ?> - </th> + <tr> + <th class="thleft col-md-10"> + <?php + echo __d('modele', 'modele.titreTableauNomChamp'); + ?> + </th> - <th class="thleft col-md-10"> - <?php - echo __d('modele', 'modele.titreTableauNomVariable'); - ?> - </th> - </tr> + <th class="thleft col-md-10"> + <?php + echo __d('modele', 'modele.titreTableauNomVariable'); + ?> + </th> + </tr> </thead> <tbody> - <tr> - <?php - foreach ($valeurPropreTraitement['traitement'] as $traitement) { - ?> - <tr> - <td class="tdleft"> + <tr> <?php - echo __m('fiche' . '.champ' . Inflector::camelize($traitement)); - ?> - </td> + foreach ($valeurPropreTraitement['traitement'] as $traitement) { + ?> + <tr> + <td class="tdleft"> + <?php + echo __m('fiche' . '.champ' . Inflector::camelize($traitement)); + ?> + </td> - <td class="tdleft"> + <td class="tdleft"> + <?php + echo 'valeur_' . $traitement; + ?> + </td> + </tr> <?php - echo 'valeur_' . $traitement; - ?> - </td> - </tr> - <?php - } - ?> - </tr> + } + ?> + </tr> </tbody> </table> <?php diff --git a/app/View/Normes/add.ctp b/app/View/Normes/add.ctp deleted file mode 100644 index a145cb38c93999e6656768f8be57b65356752172..0000000000000000000000000000000000000000 --- a/app/View/Normes/add.ctp +++ /dev/null @@ -1,156 +0,0 @@ -<?php -$breadcrumbs = [ - __d('norme', 'norme.titreListeNorme') => [ - 'action' => 'index', - 'prepend' => true - ], - $title => [] -]; -$this->Breadcrumbs->breadcrumbs($breadcrumbs, true); - -if (isset($this->validationErrors['Norme']) && !empty($this->validationErrors['Norme'])) { - ?> - <div class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"><!----></span> - <span class="sr-only">Error:</span> - Ces erreurs se sont produites: - <ul> - <?php - foreach ($this->validationErrors as $donnees) { - foreach ($donnees as $champ) { - foreach ($champ as $error) { - echo '<li>' . $error . '</li>'; - } - } - } - ?> - </ul> - </div> - <?php -} - -echo $this->WebcilForm->create('Norme',[ - 'autocomplete' => 'off', - 'inputDefaults' => ['div' => false], - 'class' => 'form-horizontal', - 'novalidate' => 'novalidate', - 'type' => 'file' -]); -?> - -<div class="row col-md-12"> - <div class="col-md-6"> - <?php - echo $this->WebcilForm->input('norme', [ - 'id' => 'norme', - 'options' => $options['Norme']['norme'], - 'class' => 'form-control custom-select', - 'empty' => true, - 'required' => true, - 'placeholder' => false - ]); - ?> - </div> - - <div class="col-md-1 text-center"> - <i style="margin-left:10px; margin-top: 30px" class="fa fa-arrow-right pull-left"></i> - </div> - - <div class="col-md-5"> - <?php - echo $this->WebcilForm->input('prefixNumero', [ - 'id' => 'prefixNumero', - 'label' => [ - 'text' => false, - 'class' => false - ], - 'readonly' => true, - 'placeholder' => false - ]); - ?> - </div> -</div> - -<div class="row col-md-12"> - <div class="col-md-6"> - <?php - echo $this->WebcilForm->inputs([ - 'numero' => [ - 'id' => 'numero', - 'type' => 'text', - 'required' => true, - 'maxlength' => 3 - ], - 'libelle' => [ - 'id' => 'libelle', - 'required' => true - ], - 'description' => [ - 'id' => 'description', - 'type' => 'textarea' - ] - ]); - - // Ajouter le PDF de la norme - echo $this->WebcilForm->input('Norme.fichier', [ - 'id' => 'logo_file', - 'type' => 'file', - 'class' => 'filestyle', - 'data-text' => ' Ajouter le PDF de la norme', - 'data-buttonBefore' => 'true', - 'accept' => 'application/pdf', - 'label' => [ - 'text' => false - ] - ]); - ?> - </div> -</div> - -<?php -echo $this->WebcilForm->buttons(['Cancel', 'Save']); - -echo $this->WebcilForm->end(); -?> - -<script type="text/javascript"> - - $(document).ready(function () { - - $('#numero').mask("000", { - placeholder: "___" - }); - - let prefixNorme = "", - numeroNorme = "", - libelleNorme = ""; - - // Lors d'action sur le menu déroulant - $('#norme').change(function () { - prefixNorme = $(this).val(); - $('#prefixNumero').val(prefixNorme + numeroNorme + libelleNorme); - }); - - $('#numero').change(function () { - - if ($(this).val() === '') { - numeroNorme = ""; - } else { - numeroNorme = '-' + $(this).val(); - } - - $('#prefixNumero').val(prefixNorme + numeroNorme + libelleNorme); - }); - - $('#libelle').change(function () { - if ($(this).val() === '') { - libelleNorme = ""; - } else { - libelleNorme = ' : ' + $(this).val(); - } - - $('#prefixNumero').val(prefixNorme + numeroNorme + libelleNorme); - }); - - }); -</script> diff --git a/app/View/Referentiels/edit.ctp b/app/View/Referentiels/edit.ctp new file mode 100644 index 0000000000000000000000000000000000000000..44c2f7dc25e4e7ad47c6f0cb0d0716d99e081a0f --- /dev/null +++ b/app/View/Referentiels/edit.ctp @@ -0,0 +1,136 @@ +<?php + +$breadcrumbs = [ + __d('referentiel', 'referentiel.titreIndex') => [ + 'action' => 'index', + 'prepend' => true + ], + $title => [] +]; +$this->Breadcrumbs->breadcrumbs($breadcrumbs, true); + +if (isset($this->validationErrors['Referentiel']) && !empty($this->validationErrors['Referentiel'])) { + ?> + <div class="alert alert-danger" role="alert"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"><!----></span> + <span class="sr-only">Error:</span> + Ces erreurs se sont produites: + <ul> + <?php + foreach ($this->validationErrors as $donnees) { + foreach ($donnees as $champ) { + foreach ($champ as $error) { + echo '<li>' . $error . '</li>'; + } + } + } + ?> + </ul> + </div> + <?php +} + +echo $this->WebcilForm->create('Referentiel',[ + 'autocomplete' => 'off', + 'inputDefaults' => ['div' => false], + 'class' => 'form-horizontal', + 'novalidate' => 'novalidate', + 'type' => 'file' +]); +?> + +<div class="row"> + <div class="col-md-12"> + <?php + echo $this->WebcilForm->inputs([ + 'Referentiel.name' => [ + 'id' => 'name', + 'required' => true + ], + 'Referentiel.description' => [ + 'id' => 'description', + 'class' => 'referentiel_description', + 'type' => 'textarea', + 'required' => true + ] + ]); + + echo $this->TinyMCE->load('referentiel_description'); + + if (empty($this->request->data('Referentiel.fichier'))) { + // Ajouter le PDF + echo $this->WebcilForm->input('Referentiel.fichier', [ + 'id' => 'logo_file', + 'type' => 'file', + 'class' => 'filestyle', + 'data-text' => ' Ajouter le PDF du référentiel', + 'data-buttonBefore' => 'true', + 'accept' => 'application/pdf', + 'label' => [ + 'text' => false + ] + ]); + } else { + ?> + <table class="table" id="render"> + <thead></thead> + <tbody> + <tr class="d-flex"> + <td class="col-md-1"> + <i class="far fa-file-alt fa-lg"></i> + </td> + + <td class="col-md-9"> + <?php + echo $this->request->data('Referentiel.name_fichier'); + ?> + </td> + + <td class="col-md-2"> + <?php + echo $this->Html->link('<i class="fa fa-download fa-lg"></i>', [ + 'controller' => 'referentiels', + 'action' => 'download', + $referentiel['Referentiel']['fichier'], + $referentiel['Referentiel']['name_fichier'] + ], [ + 'class' => 'btn btn-outline-dark borderless boutonShow btn-sm my-tooltip', + 'title' => 'Télécharger le référentiel', + 'escapeTitle' => false + ]); + + echo $this->Html->link('<i class="fa fa-trash fa-lg"></i>', [ + 'controller' => 'referentiels', + 'action' => 'deleteFileSave', + $referentiel['Referentiel']['id'], + $referentiel['Referentiel']['fichier'], + ], [ + 'class' => 'btn btn-outline-danger borderless boutonShow btn-sm my-tooltip', + 'title' => __d('norme','norme.btnSupprimerFichierNorme'), + 'escapeTitle' => false + ]); + ?> + </td> + </tr> + </tbody> + </table> + <?php + } + ?> + </div> +</div> + +<div class="row"> + <!-- Groupe bouton --> + <div class="col-md-12 top17 text-center"> + <div class="buttons"> + <?php + // Groupe de boutons + echo $this->WebcilForm->buttons(['Cancel', 'Save']); + ?> + </div> + </div> +</div> + +<?php +echo $this->WebcilForm->end(); diff --git a/app/View/Referentiels/index.ctp b/app/View/Referentiels/index.ctp new file mode 100644 index 0000000000000000000000000000000000000000..5cfaace4049bade1389478928048a1024d82d850 --- /dev/null +++ b/app/View/Referentiels/index.ctp @@ -0,0 +1,165 @@ +<?php +echo $this->Html->script('filtre.js'); +echo $this->Html->css('filtre.css'); + +$breadcrumbs = [ + $title => [] +]; +$this->Breadcrumbs->breadcrumbs($breadcrumbs, true); +?> + +<div class="text-left"> + <?php + // Si les droits de l'utilisateur le permet, affichage du bouton "+ Ajouter un profil" + if ($this->Autorisation->authorized(40, $droits)) { + echo $this->element('Buttons/add', [ + 'controller' => 'referentiels', + 'labelBtn' => __d('referentiel', 'referentiel.btnAjouterReferentiel'), + 'before' => '<div class="text-left">', + ]); + } + ?> +</div> + +<?php +if (!empty($referentiels)) { + $this->Paginator->options([ + 'url' => Hash::flatten( (array)$this->request->data, '.' ) + ]); + $pagination = $this->element('pagination'); + + echo $pagination; + ?> + + <table class="table table-striped table-hover"> + <thead> + <tr class="d-flex"> + <!-- Abroger --> + <th class="col-md-1"> + <?php + echo __d('referentiel', 'referentiel.titreTableauEtat'); + ?> + </th> + + <!-- Libelle --> + <th class="col-md-8"> + <?php + echo __d('referentiel', 'referentiel.titreTableauLibelle'); + ?> + </th> + + <!-- Actions --> + <th class='col-md-2'> + <?php + echo __d('referentiel', 'referentiel.titreTableauAction'); + ?> + </th> + </tr> + </thead> + + <tbody> + <?php + foreach ($referentiels as $referentiel) { + ?> + <tr class="d-flex"> + <!-- Status du formulaire --> + <td class="tdleft col-md-1"> + <?php + if ($referentiel['Referentiel']['abroger'] === true) { + ?> + <div class="text-center"> + <span class="badge badge-danger"> + <?php + echo __d('referentiel', 'referentiel.titreTableauAbroger'); + ?> + </span> + </div> + <?php + } + ?> + </td> + + <!-- Libelle --> + <td class="tdleft col-md-8"> + <?php + echo $referentiel['Referentiel']['name']; + ?> + </td> + + <!-- Bouton --> + <td class="tdleft col-md-2"> + <div class="buttons"> + <?php + if (!empty($referentiel['Referentiel']['fichier'])) { + echo $this->element('Buttons/download', [ + 'controller' => 'referentiels', + 'fichier' => $referentiel['Referentiel']['fichier'], + 'name_modele' => $referentiel['Referentiel']['name_fichier'], + 'titleBtn' => 'Télécharger le référentiel' + ]); + } + + if ($this->Autorisation->authorized(41, $droits)) { + echo $this->element('Buttons/show', [ + 'controller' => 'referentiels', + 'id' => $referentiel['Referentiel']['id'], + 'titleBtn' => __d('referentiel', 'referentiel.commentaireBtnVisualiserReferentiel') + ]); + } + + if ($this->Autorisation->authorized(42, $droits) && + $referentiel['Referentiel']['abroger'] == false + ) { + // Bouton de modification + echo $this->element('Buttons/edit', [ + 'controller' => 'referentiels', + 'id' => $referentiel['Referentiel']['id'], + 'titleBtn' => __d('referentiel', 'referentiel.commentaitreModifierReferentiel') + ]); + } + + if ($this->Autorisation->authorized(43, $droits)) { + if ($referentiel['Referentiel']['abroger'] == false) { + $titleBtnAbroger = __d('referentiel', 'referentiel.commentaireBtnAbrogerReferentiel'); + } else { + $titleBtnAbroger = __d('referentiel', 'referentiel.commentaireBtnRevoquerAbrogerReferentiel'); + } + echo $this->element('Buttons/abroger', [ + 'controller' => 'referentiels', + 'id' => $referentiel['Referentiel']['id'], + 'active' => $referentiel['Referentiel']['abroger'], + 'titleBtn' => $titleBtnAbroger + ]); + } + ?> + </div> + </td> + </tr> + <?php + } + ?> + </tbody> + </table> + <?php + echo $pagination; +} else { + ?> + <div class='text-center'> + <h3> + <?php + echo [] === Hash::filter($filters) + ? __d('referentiel', 'referentiel.AucunReferentiel') + : __d('referentiel', 'referentiel.filtreAucunReferentiel'); + ?> + </h3> + </div> + <?php +} + +//Si les droits de l'utilisateur le permet, affichage du bouton "+ Ajouter un profil" +if ($this->Autorisation->authorized(40, $droits)) { + echo $this->element('Buttons/add', [ + 'controller' => 'referentiels', + 'labelBtn' => __d('referentiel', 'referentiel.btnAjouterReferentiel'), + ]); +} diff --git a/app/View/Referentiels/show.ctp b/app/View/Referentiels/show.ctp new file mode 100644 index 0000000000000000000000000000000000000000..5877c3eb9feffc4328fab3fc99f16145964d9e74 --- /dev/null +++ b/app/View/Referentiels/show.ctp @@ -0,0 +1,65 @@ +<?php +$this->Breadcrumbs->breadcrumbs([ + __d('referentiel', 'referentiel.titreIndex') => [ + 'action' => 'index', + 'prepend' => true + ], + $title => [] +]); + +echo $this->WebcilForm->create('Article', [ + 'autocomplete' => 'off', + 'inputDefaults' => ['div' => false], + 'class' => 'form-horizontal', + 'novalidate' => 'novalidate' +]); + +echo $this->request->data('Referentiel.description'); + +if (!empty($this->request->data('Referentiel.fichier'))) { + ?> + <hr/> + <div class="col-md-12 top30"> + <h4> + <?php echo __d('article', 'article.textInfoPieceJointe'); ?> + </h4> + <table> + <tbody> + <tr> + <td class="col-md-1"> + <i class="far fa-file-alt fa-fw"><!----></i> + </td> + <td class="col-md-9 tdleft"> + <?php echo $this->request->data('Referentiel.name_fichier'); ?> + </td> + <td class="col-md-2"> + <?php + echo $this->Html->link('<span class="fa fa-download fa-lg"><!----></span>', [ + 'controller' => 'referentiels', + 'action' => 'download', + $this->request->data('Referentiel.fichier'), + $this->request->data('Referentiel.name_fichier'), + ], [ + 'class' => 'btn btn-outline-dark boutonShow btn-sm my-tooltip', + 'title' => 'Télécharger le fichier', + 'escapeTitle' => false + ]); + ?> + </td> + </tr> + </tbody> + </table> + </div> + <?php +} +?> + +<div style="clear: both"> + <?php + echo $this->WebcilForm->buttons(['Back']); + ?> +</div> + +<?php +echo $this->WebcilForm->end(); +?> diff --git a/app/View/Registres/index.ctp b/app/View/Registres/index.ctp index ff622f13e1bb3820b1b1403cc3e03dd33a910df9..93fa5af7f55a421a58ebc39d6aa5ef025de03890 100755 --- a/app/View/Registres/index.ctp +++ b/app/View/Registres/index.ctp @@ -449,6 +449,21 @@ if (!empty($fichesValid)) { </div> </div> + <div class="row"> + <div class="col-md-12"> + <strong> + <?php echo __d('registre', 'registre.textTableauReferentiel'); ?> + </strong> + <?php + if (isset($value['Fiche']['Referentiel']['name'])) { + echo $value['Fiche']['Referentiel']['name']; + } else { + echo __d('registre', 'registre.textAucunReferentielDefini'); + } + ?> + </div> + </div> + <!-- Annexe(s) --> <div class="row"> <div class="col-md-12"> diff --git a/app/files/referentiels/1635145836.pdf b/app/files/referentiels/1635145836.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cf8465a094de72f541297ad4dcbc1c160c535e78 Binary files /dev/null and b/app/files/referentiels/1635145836.pdf differ diff --git a/app/files/referentiels/1635145900.pdf b/app/files/referentiels/1635145900.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0ffd1d266a062a255d30a64c1575a2d437585913 Binary files /dev/null and b/app/files/referentiels/1635145900.pdf differ diff --git a/app/files/referentiels/1635145939.pdf b/app/files/referentiels/1635145939.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1333e333ad2c0b07845d916fc1cfb49aad2a7daa Binary files /dev/null and b/app/files/referentiels/1635145939.pdf differ diff --git a/app/files/referentiels/1635145996.pdf b/app/files/referentiels/1635145996.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2e15b5d59d7416654b3102a00c63e77d24e5e1a9 Binary files /dev/null and b/app/files/referentiels/1635145996.pdf differ diff --git a/app/files/referentiels/1635146060.pdf b/app/files/referentiels/1635146060.pdf new file mode 100644 index 0000000000000000000000000000000000000000..621484267f610605b89cbf23d08123002285f07f Binary files /dev/null and b/app/files/referentiels/1635146060.pdf differ diff --git a/app/files/referentiels/1635146149.pdf b/app/files/referentiels/1635146149.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8d7a04261e0505e5719f86f3a269df86c386e4d4 Binary files /dev/null and b/app/files/referentiels/1635146149.pdf differ diff --git a/app/files/referentiels/1635146223.pdf b/app/files/referentiels/1635146223.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed772af9035360e6c91d75891fdcf0980f4c3f1f Binary files /dev/null and b/app/files/referentiels/1635146223.pdf differ diff --git a/app/files/referentiels/1635146344.pdf b/app/files/referentiels/1635146344.pdf new file mode 100644 index 0000000000000000000000000000000000000000..305161fe848d65d8b7c5f64b8ae35a019b056df4 Binary files /dev/null and b/app/files/referentiels/1635146344.pdf differ diff --git a/app/files/referentiels/1635146435.pdf b/app/files/referentiels/1635146435.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a4d213415ab5605ee1d5ec125f930e93ca1ca2a5 Binary files /dev/null and b/app/files/referentiels/1635146435.pdf differ diff --git a/app/webroot/js/Fiches/infoComplementaire.js b/app/webroot/js/Fiches/infoComplementaire.js index 5d700e856a705555f752c4624c3b0d8df85d4fd6..2474228b85cea74925eb88c6c1fc765f4c1ce1f2 100644 --- a/app/webroot/js/Fiches/infoComplementaire.js +++ b/app/webroot/js/Fiches/infoComplementaire.js @@ -82,7 +82,9 @@ let addHorsUE = function(idHorsUE) { let i = intIdInputDeleteHorsUE + 1; // On supprime de groupe de champ - $('#HorsUe_'+intIdInputDeleteHorsUE).remove(); + let groupeHorsUe = $('#HorsUe_'+intIdInputDeleteHorsUE); + $(groupeHorsUe).prev('hr').remove(); + $(groupeHorsUe).remove(); while (i < idHorsUE) { let newValue = (i - 1); @@ -91,7 +93,10 @@ let addHorsUE = function(idHorsUE) { let typeGarantieHorsUe = $('#FicheHorsue'+i+'TypeGarantieHorsUe').val(); let paysDestinataireHorsUe = $('#FicheHorsue'+i+'PaysDestinataireHorsUe').val(); - $('#HorsUe_'+i).remove(); + let horsUe = $('#HorsUe_'+i); + + $(horsUe).prev('hr').remove(); + $(horsUe).remove(); createInputsInfoSupHorsUe(newValue); @@ -143,7 +148,9 @@ let addDonneeSensible = function(idDonneesSensibles) { let i = intIdInputDeleteDonneeSensible + 1; // On supprime de groupe de champ - $('#DonneeSensible_' + intIdInputDeleteDonneeSensible).remove(); + let groupeDonneeSensible = $('#DonneeSensible_' + intIdInputDeleteDonneeSensible); + $(groupeDonneeSensible).prev('hr').remove(); + $(groupeDonneeSensible).remove(); while (i < idDonneesSensibles) { let newValue = (i - 1); @@ -152,7 +159,9 @@ let addDonneeSensible = function(idDonneesSensibles) { let dureeConservationDonneeSensible = $('#FicheDonneessensibles' + i + 'DescriptionDonneeSensible').val(); let descriptionDonneeSensible = $('#FicheDonneessensibles' + i + 'DureeConservationDonneeSensible').val(); - $('#DonneeSensible_' + i).remove(); + let donneeSensible = $('#DonneeSensible_' + i); + $(donneeSensible).prev('hr').remove(); + $(donneeSensible).remove(); createInputsInfoSupDonneeSensible(newValue); diff --git a/app/webroot/js/FormulaireGenerator/createFormulaire.js b/app/webroot/js/FormulaireGenerator/createFormulaire.js index fa624a0282f92f06a949872bdf6fae63852c19df..4f76c1aa434ab576a21300c46df8949ec67d3b08 100644 --- a/app/webroot/js/FormulaireGenerator/createFormulaire.js +++ b/app/webroot/js/FormulaireGenerator/createFormulaire.js @@ -237,8 +237,6 @@ let createForm = function(typeCreateForm) { 'Menu déroulant' + '</span>' + '</label>' + - '</div>' + - '<div class="col-md-12">' + '<select class="transformSelect form-control contentDeroulant" data-placeholder=" ">' + '<option value="">Aucune option sélectionnée</option>' + '</select>' + @@ -1239,7 +1237,7 @@ let createForm = function(typeCreateForm) { objet = objet + '<option name="'+newNameField+'" value=""></option>'; $.each(newOptionsField, function (index, value) { - objet = objet + '<option id="'+newNameField+index+'" name="'+newNameField+'" value="'+index+'">' + + objet = objet + '<option id="'+newNameField+index+'" type="deroulant" name="'+newNameField+'" value="'+index+'">' + value + '</option>'; }); diff --git a/app/webroot/js/package-lock.json b/app/webroot/js/package-lock.json index 9f682432025b954949e2e6f754f3eccca5191d6f..821e69f3d1a83217e361e149293d6d842f57f7a2 100644 --- a/app/webroot/js/package-lock.json +++ b/app/webroot/js/package-lock.json @@ -86,14 +86,14 @@ } }, "@popperjs/core": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz", - "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==" + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", + "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==" }, "bootstrap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", - "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==" + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.1.tgz", + "integrity": "sha512-0dj+VgI9Ecom+rvvpNZ4MUZJz8dcX7WCX+eTID9+/8HgOkv3dsRzi8BGeZJCQU6flWQVYxwTQnEZFrmJSEO7og==" }, "components-font-awesome": { "version": "5.9.0", @@ -111,9 +111,12 @@ "integrity": "sha512-reywdHlYEkPbzWjTpcc1fk9XQ3PLvO5dzEAVqy8zI7NTF22tB1HbeU3iboZTLdkBEPaWAqeI2HtEjsGQ4roZKw==" }, "jquery-ui": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", - "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.0.tgz", + "integrity": "sha512-Osf7ECXNTYHtKBkn9xzbIf9kifNrBhfywFEKxOeB/OVctVmLlouV9mfc2qXCp6uyO4Pn72PXKOnj09qXetopCw==", + "requires": { + "jquery": ">=1.8.0 <4.0.0" + } }, "jquery-ui-dist": { "version": "1.12.1", @@ -131,9 +134,9 @@ "integrity": "sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw==" }, "tinymce": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.8.1.tgz", - "integrity": "sha512-1zGXdZplWQafstlC7sri0ttCgMagsiXDc9N3I8JNrPOsWAeTfq4AAJWZoxsQBYn8gYcuPu/WzMKG5SoJjxI1VA==" + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.10.0.tgz", + "integrity": "sha512-SaqBK8GtTKYSsTfhKdN0+NrZRgmVWO+j3fvgzLjt0t/g0osNzRH5os8icm2Rv5HvaeTd4TpxetUuLE+R9yg/yg==" }, "tinymce-i18n": { "version": "20.12.25", diff --git a/app/webroot/js/package.json b/app/webroot/js/package.json index fd904a7272654cecf5d0ae8b2f9d6dd432829397..58c6534885f987dfb7cb79200da3ec6f2bdb978e 100644 --- a/app/webroot/js/package.json +++ b/app/webroot/js/package.json @@ -10,15 +10,15 @@ "dependencies": { "@libriciel/ls-bootstrap-4": "0.0.187552", "@libriciel/ls-composants": "10.5.0", - "@popperjs/core": "^2.6.0", - "bootstrap": "^4.5.3", + "@popperjs/core": "^2.10.2", + "bootstrap": "^4.6.1", "components-font-awesome": "^5.9.0", "jquery": "^3.5.1", "jquery-mask-plugin": "^1.14.16", - "jquery-ui": "^1.12.1", + "jquery-ui": "^1.13.0", "jquery-ui-dist": "^1.12.1", "select2": "^4.0.13", - "tinymce": "^5.6.2", + "tinymce": "^5.10.0", "tinymce-i18n": "^20.4.4" } } diff --git a/bower.json b/bower.json index f15c388c63ba14ace316a32fdbfa4194be580500..aaae8c7158f07fbaef107cc32647e6f0d50525ee 100755 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "webdpo", "description": "Gestion de vos traitements dans le cadre de la réglementation relative à la protection des données personnelles (RGPD)", - "version": "2.1.0", + "version": "2.1.1", "directory": "app/webroot/js/", "authors": [ "Théo GUILLON <theo.guillon@libriciel.coop>" diff --git a/composer.json b/composer.json index 43986776f2b47aa495dee5ad2e64364a42d3df43..2ca1ea957b3ccc5df6eb2ea775433a7fe7285a43 100755 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "web-dpo/web-dpo", "description": "Gestion de vos traitements dans le cadre de la réglementation relative à la protection des données personnelles (RGPD)", - "version": "2.1.0", + "version": "2.1.1", "authors": [ { "name": "Théo GUILLON", diff --git a/composer.lock b/composer.lock index 2981164b9ec5f18cefc8f540a690fadb5fb20b13..17314de791719f59b6a445132517f243ac8a57e8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a91e099eb891ae44fa80d60f4d407d82", + "content-hash": "e2160747689598a624cbe6b7cb1838e6", "packages": [ { "name": "cakephp/AuthManager", @@ -401,16 +401,16 @@ }, { "name": "composer/installers", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/composer/installers.git", - "reference": "ae03311f45dfe194412081526be2e003960df74b" + "reference": "d20a64ed3c94748397ff5973488761b22f6d3f19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/ae03311f45dfe194412081526be2e003960df74b", - "reference": "ae03311f45dfe194412081526be2e003960df74b", + "url": "https://api.github.com/repos/composer/installers/zipball/d20a64ed3c94748397ff5973488761b22f6d3f19", + "reference": "d20a64ed3c94748397ff5973488761b22f6d3f19", "shasum": "" }, "require": { @@ -509,6 +509,7 @@ "modx", "moodle", "osclass", + "pantheon", "phpbb", "piwik", "ppi", @@ -531,7 +532,7 @@ ], "support": { "issues": "https://github.com/composer/installers/issues", - "source": "https://github.com/composer/installers/tree/v1.11.0" + "source": "https://github.com/composer/installers/tree/v1.12.0" }, "funding": [ { @@ -547,7 +548,7 @@ "type": "tidelift" } ], - "time": "2021-04-28T06:42:17+00:00" + "time": "2021-09-13T08:19:44+00:00" }, { "name": "jasig/phpcas", @@ -872,25 +873,25 @@ }, { "name": "symfony/http-client", - "version": "v5.3.0", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "ef85ca5fa7a4f9c57592fab49faeccdf22b13136" + "reference": "710b69ed4bc9469900ec5ae5c3807b0509bee0dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/ef85ca5fa7a4f9c57592fab49faeccdf22b13136", - "reference": "ef85ca5fa7a4f9c57592fab49faeccdf22b13136", + "url": "https://api.github.com/repos/symfony/http-client/zipball/710b69ed4bc9469900ec5ae5c3807b0509bee0dc", + "reference": "710b69ed4bc9469900ec5ae5c3807b0509bee0dc", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/log": "^1.0", + "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.1", "symfony/http-client-contracts": "^2.4", "symfony/polyfill-php73": "^1.11", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.0|^2" }, "provide": { @@ -939,7 +940,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v5.3.0" + "source": "https://github.com/symfony/http-client/tree/v5.3.10" }, "funding": [ { @@ -955,7 +956,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-10-19T08:32:53+00:00" }, { "name": "symfony/http-client-contracts", @@ -1037,16 +1038,16 @@ }, { "name": "symfony/mime", - "version": "v5.3.0", + "version": "v5.3.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852" + "reference": "a756033d0a7e53db389618653ae991eba5a19a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/ed710d297b181f6a7194d8172c9c2423d58e4852", - "reference": "ed710d297b181f6a7194d8172c9c2423d58e4852", + "url": "https://api.github.com/repos/symfony/mime/zipball/a756033d0a7e53db389618653ae991eba5a19a11", + "reference": "a756033d0a7e53db389618653ae991eba5a19a11", "shasum": "" }, "require": { @@ -1054,7 +1055,7 @@ "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "conflict": { "egulias/email-validator": "~3.0.0", @@ -1100,7 +1101,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.3.0" + "source": "https://github.com/symfony/mime/tree/v5.3.8" }, "funding": [ { @@ -1116,7 +1117,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-09-10T12:30:38+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -1291,16 +1292,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1" + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1", - "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", "shasum": "" }, "require": { @@ -1351,7 +1352,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" }, "funding": [ { @@ -1367,7 +1368,7 @@ "type": "tidelift" } ], - "time": "2021-05-27T09:27:20+00:00" + "time": "2021-05-27T12:26:48+00:00" }, { "name": "symfony/polyfill-php72", @@ -1526,16 +1527,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", "shasum": "" }, "require": { @@ -1589,7 +1590,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" }, "funding": [ { @@ -1605,7 +1606,7 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2021-07-28T13:41:28+00:00" }, { "name": "symfony/service-contracts", diff --git a/docker/app/usr/bin/docker-entrypoint.sh b/docker/app/usr/bin/docker-entrypoint.sh index 9a8d6a79a4aa24eeb97cfe2cf8376863b5d8bae4..bdafb88103ae53781c72c8a7f7d9c3d2f5388214 100755 --- a/docker/app/usr/bin/docker-entrypoint.sh +++ b/docker/app/usr/bin/docker-entrypoint.sh @@ -206,6 +206,7 @@ init_data_db() files+=(${__APP_DIR__}/app/Config/Schema/CreationBase/patchs/2.0.0_to_2.0.1.sql) files+=(${__APP_DIR__}/app/Config/Schema/CreationBase/patchs/2.0.1_to_2.1.0.sql) + files+=(${__APP_DIR__}/app/Config/Schema/CreationBase/patchs/2.1.0_to_2.1.1.sql) for file in ${files[*]}; do echo "Installation de ${file}"