diff --git a/CHANGELOG.md b/CHANGELOG.md index 37fc895a4805816d412f3e45df285796478ddad5..28a8d662d217a086f1a479f2cc8bb8af42b69b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ CHANGELOG ========= ## [2.4.9] - 2025-XX-XX ### Ajout -- [Global] Ajout des champs absents dans les documents Word générés depuis la liste des différents modules. - [Formulaire] Ajout d'un label aux champs type et liste des structures dans la gestion des droits des modèles d'AIPD et dans les référentiels, ainsi que dans la duplication. - [Accessibilité] Ajout du plan d'actions 2025. - [Preuves] Ajout de la possibilité de déposer des documents ayant comme extension .txt, .log, .csv et .md. @@ -10,22 +9,36 @@ CHANGELOG - [Référentiels] Ajout du nom de l'élément modifié dans la gestion des droits des référentiels. - [AIPD] Ajout du nom de l'élément modifié dans la gestion des droits des modèles d'AIPD. - [AIPD] Ajout du modèle XML sur la vidéoprotection mis en oeuvre par les autorités publiques. +- [AIPD] Ajout d'un bouton pour retourner à la liste et un bouton pour générer un PDF depuis l'étape 5 d'évaluation d'une AIPD. +- [AIPD] Ajout d'un changement dynamique de l'impact potentiel selon le choix de la vraisemblance et de la gravité dans l'étape 3 d'instruction d'une AIPD. ### Changement - [Global] Divers renommages et traductions. - [Documentation] Mise à jour de la documentation technique. - [Documentation] Mise à jour de la documentation utilisateur. - [Accessibilité] Mise à jour du schéma pluriannuel et du plan d'actions 2024. - [Plan du site] Mise à jour des pages liées à l'accessibilité. +- [Traitements] Déplacement des champs finalités et état. +- [Traitements] Modification du champ finalités en sélecteur. - [Traitements] Déplacement du consentement demandé et du format du bloc détails au bloc informations générales. -- [Traitements] Repositionnement des mesures de sécurité et confidentialité par ordre alphabétique. +- [Traitements] Déplacement des critères spécifiques par ordre alphabétique. +- [Traitements] Le critère « Croisement de données » est renommé en « Croisement d’ensemble de données ». +- [Traitements] Le critère « Décisions automatisées avec effet » est renommé en « Décision automatique avec effet juridique ». +- [Traitements] Le critère « Exclusion automatique d'un service » est renommé en « Exclusion du bénéfice d’un droit, d’un service ou contrat ». +- [Traitements] Déplacement des mesures de sécurité et confidentialité par ordre alphabétique. +- [Sous-traitants] Inversion de la case à cocher de l'envoi de données hors UE en dans l'UE. - [Indice de maturité] Modification du bouton de modification pour s'afficher que s'il y a des préconisations dans la synthèse d'un indice de maturité. - [Bilan] Modification de l'affichage des données du dernier indice de maturité dans le bilan. +- [AIPD] Amélioration globale dans le PDF d'une AIPD. +- [AIPD] Modification de l'image sur la gravité et la vraisemblance dans le PDF d'une AIPD. - [AIPD] Modification des dates des avis des acteurs pour ne rien afficher par défaut dans le PDF d'une AIPD. +### Suppression +- [AIPD] Suppression du bouton pour enregistrer un brouillon dans l'étape 5 d'évaluation d'une AIPD. ### Fix -- [Traitements] Fix de certains champs manquants dans le document Word généré depuis la liste des traitements. +- [Global] Fix de certains champs manquants dans les documents PDF et Word générés depuis les différents modules. - [Indice de maturité] Fix de l'affichage du graphique dans le bilan et la synthèse d'un indice de maturité. - [Bilan] Fix de l'affichage de la date dans le tableau des actions de protection mises en place. - [Bilan] Fix de certaines données présentes dans le tableau annexe du registre des traitements. +- [Bilan] Fix de certaines données calculées dans le paragraphe du registre des sous-traitants. - [Registre public] Fix affichage des durées de conservation. - [Migration] Fix d'une migration qui cause une erreur lors du déploiement. diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js index e0238e822f38f857dbec32ed8b56a072d6f6eef1..19f29c82f33a26666ad945dd961ac5d7f39c5cca 100644 --- a/assets/js/dashboard.js +++ b/assets/js/dashboard.js @@ -186,7 +186,7 @@ $(document).ready(function() { 'contractor-sending-data-outside-eu', labelYesNo, contractorSendingDataOutsideEuData, - [colorRed, colorBlue] + [colorGreen, colorRed] ); } diff --git a/config/domain/registry/translations/messages.fr.yaml b/config/domain/registry/translations/messages.fr.yaml index 97aa564286a4b2ebbab0057e8863c3e4b9d55975..e786e89e9d2f22356e906b28e88ec737827cdd65 100644 --- a/config/domain/registry/translations/messages.fr.yaml +++ b/config/domain/registry/translations/messages.fr.yaml @@ -49,13 +49,13 @@ registry: data_category_other: Autres catégories recipient_category: Catégorie de destinataires exempt_AIPD: Est exempté d'AIPD - systematic_monitoring: Surveillance systématique large_scale_collection: Collecte à large échelle - vulnerable_people: Personnes vulnérables - data_crossing: Croisement de données + data_crossing: Croisement d’ensemble de données + automated_decisions_with_legal_effect: Décision automatique avec effet juridique evaluation_or_rating: Évaluation ou notation - automated_decisions_with_legal_effect: Décisions automatisées avec effet - automatic_exclusion_service : Exclusion automatique d'un service + automatic_exclusion_service : Exclusion du bénéfice d’un droit, d’un service ou contrat + vulnerable_people: Personnes vulnérables + systematic_monitoring: Surveillance systématique innovative_use: Usage innovant concerned_people: Personnes concernées concerned_people_particular: Particuliers @@ -150,7 +150,7 @@ registry: contractual_clauses_verified: Clauses contractuelles vérifiées adopted_security_features: Adopte les éléments de sécurité nécessaires maintains_treatment_register: Tient à jour un registre des traitements - sending_data_outside_eu: Envoi des données hors UE + sending_data_outside_eu: Les données restent dans l'Union européenne other_informations: Autres informations has_dpo: Le sous-traitant a désigné un DPD delete_confirm: Souhaitez-vous vraiment supprimer le sous-traitant "%object%" ? @@ -161,7 +161,7 @@ registry: security: Sécurité maintains_treatment_register: Registre des traitements register: Registre - sending_data_outside_eu: Données hors UE + sending_data_outside_eu: Données dans l'UE tab: coordinates: Coordonnées dpo: Délégué à la protection des données diff --git a/config/domain/registry/translations/validators.fr.yaml b/config/domain/registry/translations/validators.fr.yaml index bcee076260c5ef7075d3958768e2048e18864e86..739707d3fd4cdcf7ecc77b51bdfee6ed74a4ff8f 100644 --- a/config/domain/registry/translations/validators.fr.yaml +++ b/config/domain/registry/translations/validators.fr.yaml @@ -23,7 +23,7 @@ registry_contractor: name: not_blank: Vous devez renseigner un nom sending_data_outside_eu: - not_null: Envoi des données hors UE doit être renseignée + not_null: Les données restent dans l'Union européenne doit être renseignée registry_proof: document_file: diff --git a/docs/docutilisateur.md b/docs/docutilisateur.md index c817466b820e2cb3faec3e2a1a9cdabc5287d9b0..162879be36cac2ffe759748ad6b5e7014a92e036 100644 --- a/docs/docutilisateur.md +++ b/docs/docutilisateur.md @@ -32,7 +32,7 @@ Le tableau de bord permet de visualiser en un coup d’œil l’état d’avance  Il est possible de visualiser différents indicateurs : -* Des graphiques synthétisant le nombre de sous-traitants conformes et non conformes pour les clauses contractuelles, les éléments de sécurité adoptés, le registre des traitements, ainsi que les données hors UE ; +* Des graphiques synthétisant le nombre de sous-traitants conformes et non conformes pour les clauses contractuelles, les éléments de sécurité adoptés, le registre des traitements, ainsi que les données dans l'UE ; * Des graphiques synthétisant le nombre de demandes non archivées réparties par types de demandes, ainsi que par statut. * Des statistiques et un accès rapide à certains modules : * Le nombre total de demandes non archivées à traiter. Une demande sera considérée comme « **À traiter** » si elle n'a pas de statut « **Demande traitée et clôturée** » ou « **Demande refusée** » et qu'elle n'a pas de date de traitement ; @@ -226,13 +226,13 @@ Dans la destination, il est possible de renseigner les éléments suivants : Un ou plusieurs traitements spécifiques vont peut-être conditionner une analyse d’impact, notamment s'ils sont croisés avec des données sensibles. Il est possible de renseigner les éléments suivants : * **Est exempté d'AIPD** : Si le traitement est exempté, il n'y aura pas d'indication alertant de la nécessité de réaliser une AIPD. Il est cependant toujours possible d'en réaliser une si souhaité ; -* **Surveillance systématique de personnes** : Par exemple, télésurveillance... ; * **Collecte à large échelle** : Vise à traiter un volume considérable de données à caractère personnel, par exemple au niveau régional... ; -* **Personnes vulnérables** : Personnes âgées, enfant de moins de 15 ans, personne en situation de handicap, patients, employés... ; -* **Croisement de données** : Croisement ou combinaison d’ensemble de données ; +* **Croisement d’ensemble de données** : Croisement ou combinaison d’ensemble de données ; +* **Décision automatique avec effet juridique** : Décision automatique sans supervision humaine pouvant par exemple, exclure ou discriminer une personne d'un droit ; * **Évaluation ou notation** : Possibilité d'utiliser des données pour évaluer, noter, prédire ou établir le profil d'une personne sur des aspects concernant le rendement au travail, la santé, la situation économique, les préférences, le comportement... ; -* **Décisions automatisées avec effet** : Décision automatique sans supervision humaine pouvant par exemple, exclure ou discriminer une personne d'un droit ; -* **Exclusion automatique d'un service** : Décision automatique sans supervision humaine excluant l'accès à un service ou à un contrat ; +* **Exclusion du bénéfice d’un droit, d’un service ou contrat** : Décision automatique sans supervision humaine excluant l'accès à un service ou à un contrat ; +* **Personnes vulnérables** : Personnes âgées, enfant de moins de 15 ans, personne en situation de handicap, patients, employés... ; +* **Surveillance systématique de personnes** : Par exemple, télésurveillance... ; * **Usage innovant** : Les conséquences de l'utilisation de cette nouvelle technologie ne sont pas toutes connues et peuvent à l'avenir devenir une nouvelle source de collecte de données personnelles pouvant porter atteinte aux droits et libertés individuelles. #### Détails @@ -312,7 +312,7 @@ Dans les informations générales, il est possible de renseigner les éléments * **Clauses contractuelles vérifiées** : Les clauses contractuelles de ce contrat ont été vérifiées et sont conformes au RGPD ; * **Adopte les éléments de sécurité nécessaires** : Suite à une demande ou à une vérification, le sous-traitant a adopté les mesures de sécurité jugées suffisantes ; * **Tient à jour un registre des traitements** : Le registre de traitement du sous-traitant a été communiqué et est tenu à jour ; -* **Envoi des données hors UE** : Les données sont envoyées en dehors de l'Union Européenne. +* **Les données restent dans l'Union européenne** : Les données ne sont pas envoyées en dehors de l'Union Européenne. #### Délégué à la protection des données diff --git a/migrations/Version20250213144200.php b/migrations/Version20250213144200.php new file mode 100644 index 0000000000000000000000000000000000000000..45246a15edac34b651e6e8af9dd746d791e730cf --- /dev/null +++ b/migrations/Version20250213144200.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +namespace DoctrineMigrations; + +use Doctrine\DBAL\Schema\Schema; +use Doctrine\Migrations\AbstractMigration; + +/** + * Auto-generated Migration: Please modify to your needs! + */ +final class Version20250213144200 extends AbstractMigration +{ + public function getDescription(): string + { + return ''; + } + + public function up(Schema $schema): void + { + // this up() migration is auto-generated, please modify it to your needs + $this->abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('UPDATE registry_contractor SET sending_data_outside_eu = NOT sending_data_outside_eu'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('UPDATE registry_contractor SET sending_data_outside_eu = NOT sending_data_outside_eu'); + } +} diff --git a/public/images/NiveauRisque.png b/public/images/NiveauRisque.png index 1aa50b4a1f05af425671b972f01d77996797aca2..5913d6cb5b3c893ab5dec7bc147729dbc8740921 100644 Binary files a/public/images/NiveauRisque.png and b/public/images/NiveauRisque.png differ diff --git a/src/Domain/Admin/Cloner/TreatmentCloner.php b/src/Domain/Admin/Cloner/TreatmentCloner.php index 2f1ba108b03bdf9626f0ebf88086c65ad46688a2..482dc1ef0825e242a392294eb7ed46ec19cce5ab 100644 --- a/src/Domain/Admin/Cloner/TreatmentCloner.php +++ b/src/Domain/Admin/Cloner/TreatmentCloner.php @@ -101,14 +101,14 @@ class TreatmentCloner extends AbstractCloner if (null !== $referent->getSecurityOther()) { $treatment->setSecurityOther($referent->getSecurityOther()); } - $treatment->setSystematicMonitoring($referent->isSystematicMonitoring()); $treatment->setStatut($referent->getStatut()); $treatment->setLargeScaleCollection($referent->isLargeScaleCollection()); - $treatment->setVulnerablePeople($referent->isVulnerablePeople()); $treatment->setDataCrossing($referent->isDataCrossing()); - $treatment->setEvaluationOrRating($referent->isEvaluationOrRating()); $treatment->setAutomatedDecisionsWithLegalEffect($referent->isAutomatedDecisionsWithLegalEffect()); + $treatment->setEvaluationOrRating($referent->isEvaluationOrRating()); $treatment->setAutomaticExclusionService($referent->isAutomaticExclusionService()); + $treatment->setVulnerablePeople($referent->isVulnerablePeople()); + $treatment->setSystematicMonitoring($referent->isSystematicMonitoring()); $treatment->setActive($referent->isActive()); $treatment->setSecurityEntitledPersons($referent->isSecurityEntitledPersons()); $treatment->setSecurityOpenAccounts($referent->isSecurityOpenAccounts()); diff --git a/src/Domain/Notification/Command/NotificationsGenerateCommand.php b/src/Domain/Notification/Command/NotificationsGenerateCommand.php index 310b5de674e8cd7f86cf9dcbe202e7c172470d3b..783f1364839066e820db645250d4867a7d3210d8 100644 --- a/src/Domain/Notification/Command/NotificationsGenerateCommand.php +++ b/src/Domain/Notification/Command/NotificationsGenerateCommand.php @@ -176,25 +176,25 @@ class NotificationsGenerateCommand extends Command $t = $conformite->getTraitement(); - if ($t && $t->isSystematicMonitoring()) { - ++$counter; - } if ($t && $t->isLargeScaleCollection()) { ++$counter; } - if ($t && $t->isVulnerablePeople()) { + if ($t && $t->isDataCrossing()) { ++$counter; } - if ($t && $t->isDataCrossing()) { + if ($t && $t->isAutomatedDecisionsWithLegalEffect()) { ++$counter; } if ($t && $t->isEvaluationOrRating()) { ++$counter; } - if ($t && $t->isAutomatedDecisionsWithLegalEffect()) { + if ($t && $t->isAutomaticExclusionService()) { ++$counter; } - if ($t && $t->isAutomaticExclusionService()) { + if ($t && $t->isVulnerablePeople()) { + ++$counter; + } + if ($t && $t->isSystematicMonitoring()) { ++$counter; } if ($t && $t->isInnovativeUse()) { diff --git a/src/Domain/Registry/Controller/ContractorController.php b/src/Domain/Registry/Controller/ContractorController.php index 1a227bf7926f066c3ac6d6d12f6338fb9217c82d..face4ffcb99fd4c6928546247a95a934a29e69b2 100644 --- a/src/Domain/Registry/Controller/ContractorController.php +++ b/src/Domain/Registry/Controller/ContractorController.php @@ -213,8 +213,8 @@ class ContractorController extends CRUDController 'element_securite' => $contractor->isAdoptedSecurityFeatures() ? $yes : $no, 'registre_traitements' => $contractor->isMaintainsTreatmentRegister() ? $yes : $no, 'donnees_hors_eu' => $contractor->isSendingDataOutsideEu() ? - '<span class="badge bg-red">' . $this->translator->trans('global.label.yes') . '</span>' : - '<span class="badge bg-green">' . $this->translator->trans('global.label.no') . '</span>', + '<span class="badge bg-green">' . $this->translator->trans('global.label.yes') . '</span>' : + '<span class="badge bg-red">' . $this->translator->trans('global.label.no') . '</span>', 'createdAt' => date_format($contractor->getCreatedAt(), 'd-m-Y H:i'), 'updatedAt' => date_format($contractor->getUpdatedAt(), 'd-m-Y H:i'), 'actions' => $this->getActionCellsContent($contractor), diff --git a/src/Domain/Registry/Controller/TreatmentController.php b/src/Domain/Registry/Controller/TreatmentController.php index 0d7723165d6c8b02f90a0d8ff3b07d52c4e860ff..212f1dee66f309594b058721af5d3e8d59672fd0 100644 --- a/src/Domain/Registry/Controller/TreatmentController.php +++ b/src/Domain/Registry/Controller/TreatmentController.php @@ -480,27 +480,27 @@ class TreatmentController extends CRUDController { $user = $this->userProvider->getAuthenticatedUser(); $values = []; - if ($treatment->isSystematicMonitoring()) { - array_push($values, $this->translator->trans('registry.treatment.label.systematic_monitoring')); - } if ($treatment->isLargeScaleCollection()) { array_push($values, $this->translator->trans('registry.treatment.label.large_scale_collection')); } - if ($treatment->isVulnerablePeople()) { - array_push($values, $this->translator->trans('registry.treatment.label.vulnerable_people')); - } if ($treatment->isDataCrossing()) { array_push($values, $this->translator->trans('registry.treatment.label.data_crossing')); } - if ($treatment->isEvaluationOrRating()) { - array_push($values, $this->translator->trans('registry.treatment.label.evaluation_or_rating')); - } if ($treatment->isAutomatedDecisionsWithLegalEffect()) { array_push($values, $this->translator->trans('registry.treatment.label.automated_decisions_with_legal_effect')); } + if ($treatment->isEvaluationOrRating()) { + array_push($values, $this->translator->trans('registry.treatment.label.evaluation_or_rating')); + } if ($treatment->isAutomaticExclusionService()) { array_push($values, $this->translator->trans('registry.treatment.label.automatic_exclusion_service')); } + if ($treatment->isVulnerablePeople()) { + array_push($values, $this->translator->trans('registry.treatment.label.vulnerable_people')); + } + if ($treatment->isSystematicMonitoring()) { + array_push($values, $this->translator->trans('registry.treatment.label.systematic_monitoring')); + } if ($treatment->isInnovativeUse()) { array_push($values, $this->translator->trans('registry.treatment.label.innovative_use')); } diff --git a/src/Domain/Registry/Dictionary/TreatmentSpecificDictionary.php b/src/Domain/Registry/Dictionary/TreatmentSpecificDictionary.php index ea848c575de49819e584c6173c505f7d372edd06..4160c317db6c27640a0770c88ecd21634bc9ead0 100644 --- a/src/Domain/Registry/Dictionary/TreatmentSpecificDictionary.php +++ b/src/Domain/Registry/Dictionary/TreatmentSpecificDictionary.php @@ -27,13 +27,13 @@ use App\Application\Dictionary\SimpleDictionary; class TreatmentSpecificDictionary extends SimpleDictionary { - public const SYSTEMATIC_MONITORING = 'systematic_monitoring'; public const LARGE_SCALE_COLLECTION = 'large_scale_collection'; - public const VULNERABLE_PEOPLE = 'vulnerable_people'; public const DATA_CROSSING = 'data_crossing'; - public const EVALUATION_OR_RATING = 'evaluation_or_rating'; public const AUTOMATED_DECISION_WITH_LEGAL_EFFECT = 'automated_decisions_with_legal_effect'; + public const EVALUATION_OR_RATING = 'evaluation_or_rating'; public const AUTOMATIC_EXCLUSION_SERVICE = 'automatic_exclusion_service'; + public const VULNERABLE_PEOPLE = 'vulnerable_people'; + public const SYSTEMATIC_MONITORING = 'systematic_monitoring'; public const INNOVATE_USE = 'innovative_use'; public function __construct() @@ -49,13 +49,13 @@ class TreatmentSpecificDictionary extends SimpleDictionary public static function getSpecificTreatment() { return [ - self::SYSTEMATIC_MONITORING => 'Surveillance systématique', self::LARGE_SCALE_COLLECTION => 'Collecte à large échelle', - self::VULNERABLE_PEOPLE => 'Personnes vulnérables', - self::DATA_CROSSING => 'Croisement de données', + self::DATA_CROSSING => 'Croisement d\'ensemble de données', + self::AUTOMATED_DECISION_WITH_LEGAL_EFFECT => 'Décision automatique avec effet juridique', self::EVALUATION_OR_RATING => 'Évaluation ou notation', - self::AUTOMATED_DECISION_WITH_LEGAL_EFFECT => 'Décisions automatisées avec effet', - self::AUTOMATIC_EXCLUSION_SERVICE => 'Exclusion automatique d\'un service', + self::AUTOMATIC_EXCLUSION_SERVICE => 'Exclusion du bénéfice d\'un droit, d’un service ou contrat', + self::VULNERABLE_PEOPLE => 'Personnes vulnérables', + self::SYSTEMATIC_MONITORING => 'Surveillance systématique', self::INNOVATE_USE => 'Usage innovant', ]; } diff --git a/src/Domain/Registry/Form/Type/TreatmentType.php b/src/Domain/Registry/Form/Type/TreatmentType.php index 833a6a9969996ee2d1704f02b7c55f556533bf73..82e65bc74b6c9fce89288637bac51a8554f36aae 100644 --- a/src/Domain/Registry/Form/Type/TreatmentType.php +++ b/src/Domain/Registry/Form/Type/TreatmentType.php @@ -127,8 +127,6 @@ class TreatmentType extends LinkableType 'label' => 'registry.treatment.label.legal_basis', 'name' => 'registry_treatment_legal_basis', 'required' => true, - 'expanded' => true, - 'multiple' => false, ]) ->add('legalBasisJustification', TextareaType::class, [ 'label' => 'registry.treatment.label.legal_basis_justification', diff --git a/src/Domain/Registry/Model/ConformiteTraitement/ConformiteTraitement.php b/src/Domain/Registry/Model/ConformiteTraitement/ConformiteTraitement.php index ed779966ed83afc2039e36e18d4b2a484547e428..94501aff4efcd422a12cf30a7ae9cd0f3e94834a 100644 --- a/src/Domain/Registry/Model/ConformiteTraitement/ConformiteTraitement.php +++ b/src/Domain/Registry/Model/ConformiteTraitement/ConformiteTraitement.php @@ -229,36 +229,36 @@ class ConformiteTraitement implements LoggableSubject return false; } if ( - $treatment->isSystematicMonitoring() - || $treatment->isLargeScaleCollection() - || $treatment->isVulnerablePeople() + $treatment->isLargeScaleCollection() || $treatment->isDataCrossing() - || $treatment->isEvaluationOrRating() || $treatment->isAutomatedDecisionsWithLegalEffect() + || $treatment->isEvaluationOrRating() || $treatment->isAutomaticExclusionService() + || $treatment->isVulnerablePeople() + || $treatment->isSystematicMonitoring() || $treatment->isInnovativeUse() ) { $sensitiveCount = 0; $specificCount = 0; - if ($treatment->isSystematicMonitoring()) { - ++$specificCount; - } if ($treatment->isLargeScaleCollection()) { ++$specificCount; } - if ($treatment->isVulnerablePeople()) { + if ($treatment->isDataCrossing()) { ++$specificCount; } - if ($treatment->isDataCrossing()) { + if ($treatment->isAutomatedDecisionsWithLegalEffect()) { ++$specificCount; } if ($treatment->isEvaluationOrRating()) { ++$specificCount; } - if ($treatment->isAutomatedDecisionsWithLegalEffect()) { + if ($treatment->isAutomaticExclusionService()) { ++$specificCount; } - if ($treatment->isAutomaticExclusionService()) { + if ($treatment->isVulnerablePeople()) { + ++$specificCount; + } + if ($treatment->isSystematicMonitoring()) { ++$specificCount; } if ($treatment->isInnovativeUse()) { diff --git a/src/Domain/Registry/Model/Contractor.php b/src/Domain/Registry/Model/Contractor.php index f834f0bf86c2ddbc6abea31b37664bb28dee8c2b..f45bfa4ad7aa5ebae642c395173045e21216cf9a 100644 --- a/src/Domain/Registry/Model/Contractor.php +++ b/src/Domain/Registry/Model/Contractor.php @@ -101,7 +101,7 @@ class Contractor implements LoggableSubject, CollectivityRelated private $maintainsTreatmentRegister; /** - * Données hors UE. + * Données dans l'UE. * * @var bool */ diff --git a/src/Domain/Registry/Model/Treatment.php b/src/Domain/Registry/Model/Treatment.php index 49052fead9543a43261ff39fd5eb9b358473f3d9..8c31504e93e0a676be7b1656b1fdb68f76f079df 100644 --- a/src/Domain/Registry/Model/Treatment.php +++ b/src/Domain/Registry/Model/Treatment.php @@ -198,53 +198,53 @@ class Treatment implements LoggableSubject, CollectivityRelated private $securitySpecificitiesDelivered; /** - * FR: Surveillance systématique (traitement spécifique). + * FR: Collecte à large échelle (traitement spécifique). * * @var bool */ - private $systematicMonitoring; + private $largeScaleCollection; /** - * FR: Collecte à grande échelle (traitement spécifique). + * FR: Croisement d’ensemble de données (traitement spécifique). * * @var bool */ - private $largeScaleCollection; + private $dataCrossing; /** - * FR: Personnes vulnérables (traitement spécifique). + * FR: Décisions automatisées avec effet juridique (traitement spécifique). * * @var bool */ - private $vulnerablePeople; + private $automatedDecisionsWithLegalEffect; /** - * FR: Croisement de données (traitement spécifique). + * FR: Évaluation ou notation (traitement spécifique). * * @var bool */ - private $dataCrossing; + private $evaluationOrRating; /** - * FR: Évaluation ou notation (traitement spécifique). + * FR: Exclusion du bénéfice d’un droit, d’un service ou contrat (traitement spécifique). * * @var bool */ - private $evaluationOrRating; + private $automaticExclusionService; /** - * FR: Décisions automatisées avec effet juridique (traitement spécifique). + * FR: Personnes vulnérables (traitement spécifique). * * @var bool */ - private $automatedDecisionsWithLegalEffect; + private $vulnerablePeople; /** - * FR: Exclusion automatique d'un service (traitement spécifique). + * FR: Surveillance systématique (traitement spécifique). * * @var bool */ - private $automaticExclusionService; + private $systematicMonitoring; /** * FR: Usage innovant (traitement spécifique). @@ -737,24 +737,54 @@ class Treatment implements LoggableSubject, CollectivityRelated $this->securityOther = $securityOther; } - public function isSystematicMonitoring(): bool + public function isLargeScaleCollection(): bool { - return $this->systematicMonitoring; + return $this->largeScaleCollection; } - public function setSystematicMonitoring(bool $systematicMonitoring): void + public function setLargeScaleCollection(bool $largeScaleCollection): void { - $this->systematicMonitoring = $systematicMonitoring; + $this->largeScaleCollection = $largeScaleCollection; } - public function isLargeScaleCollection(): bool + public function isDataCrossing(): bool { - return $this->largeScaleCollection; + return $this->dataCrossing; } - public function setLargeScaleCollection(bool $largeScaleCollection): void + public function setDataCrossing(bool $dataCrossing): void { - $this->largeScaleCollection = $largeScaleCollection; + $this->dataCrossing = $dataCrossing; + } + + public function isAutomatedDecisionsWithLegalEffect(): bool + { + return $this->automatedDecisionsWithLegalEffect; + } + + public function setAutomatedDecisionsWithLegalEffect(bool $automatedDecisionsWithLegalEffect): void + { + $this->automatedDecisionsWithLegalEffect = $automatedDecisionsWithLegalEffect; + } + + public function isEvaluationOrRating(): bool + { + return $this->evaluationOrRating; + } + + public function setEvaluationOrRating(bool $evaluationOrRating): void + { + $this->evaluationOrRating = $evaluationOrRating; + } + + public function isAutomaticExclusionService(): bool + { + return $this->automaticExclusionService; + } + + public function setAutomaticExclusionService(bool $automaticExclusionService): void + { + $this->automaticExclusionService = $automaticExclusionService; } public function isVulnerablePeople(): bool @@ -767,14 +797,24 @@ class Treatment implements LoggableSubject, CollectivityRelated $this->vulnerablePeople = $vulnerablePeople; } - public function isDataCrossing(): bool + public function isSystematicMonitoring(): bool { - return $this->dataCrossing; + return $this->systematicMonitoring; } - public function setDataCrossing(bool $dataCrossing): void + public function setSystematicMonitoring(bool $systematicMonitoring): void { - $this->dataCrossing = $dataCrossing; + $this->systematicMonitoring = $systematicMonitoring; + } + + public function isInnovativeUse(): bool + { + return $this->innovativeUse; + } + + public function setInnovativeUse(bool $innovativeUse): void + { + $this->innovativeUse = $innovativeUse; } public function isActive(): bool @@ -827,26 +867,6 @@ class Treatment implements LoggableSubject, CollectivityRelated $this->clonedFrom = $clonedFrom; } - public function isEvaluationOrRating(): bool - { - return $this->evaluationOrRating; - } - - public function setEvaluationOrRating(bool $evaluationOrRating): void - { - $this->evaluationOrRating = $evaluationOrRating; - } - - public function isAutomatedDecisionsWithLegalEffect(): bool - { - return $this->automatedDecisionsWithLegalEffect; - } - - public function setAutomatedDecisionsWithLegalEffect(bool $automatedDecisionsWithLegalEffect): void - { - $this->automatedDecisionsWithLegalEffect = $automatedDecisionsWithLegalEffect; - } - public function getSoftware(): ?string { return $this->software; @@ -857,16 +877,6 @@ class Treatment implements LoggableSubject, CollectivityRelated $this->software = $software; } - public function isAutomaticExclusionService(): bool - { - return $this->automaticExclusionService; - } - - public function setAutomaticExclusionService(bool $automaticExclusionService): void - { - $this->automaticExclusionService = $automaticExclusionService; - } - public function getConcernedPeopleParticular(): ComplexChoice { return $this->concernedPeopleParticular; @@ -1017,16 +1027,6 @@ class Treatment implements LoggableSubject, CollectivityRelated $this->securitySpecificitiesDelivered = $securitySpecificitiesDelivered; } - public function isInnovativeUse(): bool - { - return $this->innovativeUse; - } - - public function setInnovativeUse(bool $innovativeUse): void - { - $this->innovativeUse = $innovativeUse; - } - public function getConformiteTraitement(): ?ConformiteTraitement { return $this->conformiteTraitement; diff --git a/src/Domain/Reporting/Generator/Csv/TreatmentGenerator.php b/src/Domain/Reporting/Generator/Csv/TreatmentGenerator.php index 75169e99bfae794deefa84260f699d85ab5eb535..04724a5c0662217c89f080b3e12d63c2abaa5580 100644 --- a/src/Domain/Reporting/Generator/Csv/TreatmentGenerator.php +++ b/src/Domain/Reporting/Generator/Csv/TreatmentGenerator.php @@ -378,13 +378,13 @@ class TreatmentGenerator extends AbstractGenerator $specificTrans = $this->translator->trans('registry.treatment.tab.specific'); return [ - $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.systematic_monitoring'), $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.large_scale_collection'), - $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.vulnerable_people'), $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.data_crossing'), - $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.evaluation_or_rating'), $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.automated_decisions_with_legal_effect'), + $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.evaluation_or_rating'), $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.automatic_exclusion_service'), + $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.vulnerable_people'), + $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.systematic_monitoring'), $specificTrans . ' - ' . $this->translator->trans('registry.treatment.label.innovative_use'), ]; } @@ -395,13 +395,13 @@ class TreatmentGenerator extends AbstractGenerator $no = $this->translator->trans('global.label.no'); return [ - $treatment->isSystematicMonitoring() ? $yes : $no, $treatment->isLargeScaleCollection() ? $yes : $no, - $treatment->isVulnerablePeople() ? $yes : $no, $treatment->isDataCrossing() ? $yes : $no, - $treatment->isEvaluationOrRating() ? $yes : $no, $treatment->isAutomatedDecisionsWithLegalEffect() ? $yes : $no, + $treatment->isEvaluationOrRating() ? $yes : $no, $treatment->isAutomaticExclusionService() ? $yes : $no, + $treatment->isVulnerablePeople() ? $yes : $no, + $treatment->isSystematicMonitoring() ? $yes : $no, $treatment->isInnovativeUse() ? $yes : $no, ]; } diff --git a/src/Domain/Reporting/Generator/Word/ConformiteTraitementGenerator.php b/src/Domain/Reporting/Generator/Word/ConformiteTraitementGenerator.php index 1a375e8e779b5f2a5090bd62b7b73313779565b4..9f9139be89ce0fe51866a899f0db668085975c00 100644 --- a/src/Domain/Reporting/Generator/Word/ConformiteTraitementGenerator.php +++ b/src/Domain/Reporting/Generator/Word/ConformiteTraitementGenerator.php @@ -214,13 +214,13 @@ class ConformiteTraitementGenerator extends AbstractGenerator implements Impress $cnt_sensible = 0; $sensibleDatas = []; $specificTreatments = []; - $treatment->isSystematicMonitoring() ? $specificTreatments[] = 'Surveillance systématique' : null; $treatment->isLargeScaleCollection() ? $specificTreatments[] = 'Collecte à large échelle' : null; - $treatment->isVulnerablePeople() ? $specificTreatments[] = 'Personnes vulnérables' : null; - $treatment->isDataCrossing() ? $specificTreatments[] = 'Croisement de données' : null; + $treatment->isDataCrossing() ? $specificTreatments[] = 'Croisement d\'ensemble de données' : null; + $treatment->isAutomatedDecisionsWithLegalEffect() ? $specificTreatments[] = 'Décision automatique avec effet juridique' : null; $treatment->isEvaluationOrRating() ? $specificTreatments[] = 'Évaluation ou notation' : null; - $treatment->isAutomatedDecisionsWithLegalEffect() ? $specificTreatments[] = 'Décisions automatisées avec effet' : null; - $treatment->isAutomaticExclusionService() ? $specificTreatments[] = "Exclusion automatique d'un service" : null; + $treatment->isAutomaticExclusionService() ? $specificTreatments[] = 'Exclusion du bénéfice d\'un droit, d’un service ou contrat' : null; + $treatment->isVulnerablePeople() ? $specificTreatments[] = 'Personnes vulnérables' : null; + $treatment->isSystematicMonitoring() ? $specificTreatments[] = 'Surveillance systématique' : null; $treatment->isInnovativeUse() ? $specificTreatments[] = 'Usage innovant' : null; foreach ($treatment->getDataCategories() as $category) { diff --git a/src/Domain/Reporting/Generator/Word/ContractorGenerator.php b/src/Domain/Reporting/Generator/Word/ContractorGenerator.php index 548c8d69cee765d92a3b20309f6d978130cd288a..873603cc0fc9863cb85c8a6cb003538d4070251e 100644 --- a/src/Domain/Reporting/Generator/Word/ContractorGenerator.php +++ b/src/Domain/Reporting/Generator/Word/ContractorGenerator.php @@ -48,7 +48,7 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat 'Clauses contractuelles vérifiées', 'A adopté les éléments de sécurité nécessaires', 'Tient à jour un registre des traitements', - 'Envoi des données hors UE', + 'Les données restent dans l\'Union européenne', ]; $nbContractors = \count($data); $nbVerifiedContractualClauses = 0; @@ -56,6 +56,25 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat $nbMaintainsTreatmentRegister = 0; $nbSendingDataOutsideEu = 0; + foreach ($data as $contractor) { + // Verified contractual clauses + if ($contractor->isContractualClausesVerified()) { + ++$nbVerifiedContractualClauses; + } + // Adopted security features + if ($contractor->isAdoptedSecurityFeatures()) { + ++$nbAdoptedSecurityFeatures; + } + // Maintains treatment register + if ($contractor->isMaintainsTreatmentRegister()) { + ++$nbMaintainsTreatmentRegister; + } + // Sending data outside EU + if (!$contractor->isSendingDataOutsideEu()) { + ++$nbSendingDataOutsideEu; + } + } + $section->addTitle('Registre des sous-traitants', 2); if (empty($data)) { @@ -65,7 +84,27 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat } $section->addText("Un recensement des sous-traitants gérants des données à caractère personnel de {$collectivity} a été effectué."); - $section->addText("Il y a {$nbContractors} sous-traitants identifiés, les clauses contractuelles de {$nbVerifiedContractualClauses} d’entre eux ont été vérifiées. {$nbAdoptedSecurityFeatures} sous-traitants ont adopté les éléments de sécurité nécessaires. {$nbMaintainsTreatmentRegister} sous-traitants tiennent à jour un registre des traitements. {$nbSendingDataOutsideEu} sous-traitants envois des données hors UE."); + $section->addText('Il y a ' . (1 == $nbContractors ? ' un sous-traitant identifié.' : "{$nbContractors} sous-traitants identifiés.")); + $section->addListItem( + 0 == $nbVerifiedContractualClauses ? 'Aucune clause contractuelle n’a été vérifiée ;' : + (1 == $nbVerifiedContractualClauses ? '1 clause contractuelle a été vérifiée ;' : + "{$nbVerifiedContractualClauses} clauses contractuelles vérifiées ;") + ); + $section->addListItem( + 0 == $nbAdoptedSecurityFeatures ? 'Aucun sous-traitant n’a adopté les éléments de sécurité nécessaires ;' : + (1 == $nbAdoptedSecurityFeatures ? '1 sous-traitant a adopté les éléments de sécurité nécessaires ;' : + "{$nbAdoptedSecurityFeatures} sous-traitants ont adopté les éléments de sécurité nécessaires ;") + ); + $section->addListItem( + 0 == $nbMaintainsTreatmentRegister ? 'Aucun sous-traitant ne tient à jour un registre des traitements ;' : + (1 == $nbMaintainsTreatmentRegister ? '1 sous-traitant tient à jour un registre des traitements ;' : + "{$nbMaintainsTreatmentRegister} sous-traitants tiennent à jour un registre des traitements ;") + ); + $section->addListItem( + 0 == $nbSendingDataOutsideEu ? "Aucun sous-traitant n'envoie des données hors Union européenne." : + (1 == $nbSendingDataOutsideEu ? '1 sous-traitant envoie des données hors Union européenne.' : + "{$nbSendingDataOutsideEu} sous-traitants envoient des données hors Union européenne.") + ); $ContractorsListTable = $section->addTable($this->tableStyle); $ContractorsListTable->addRow(null, ['tblHeader' => true, 'cantsplit' => true]); @@ -89,23 +128,6 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat $cell->addText($contractor->isMaintainsTreatmentRegister() ? 'Oui' : 'Non'); $cell = $ContractorsListTable->addCell(1500); $cell->addText($contractor->isSendingDataOutsideEu() ? 'Oui' : 'Non'); - - // Verified contractual clauses - if ($contractor->isContractualClausesVerified()) { - ++$nbVerifiedContractualClauses; - } - // Adopted security features - if ($contractor->isAdoptedSecurityFeatures()) { - ++$nbAdoptedSecurityFeatures; - } - // Maintains treatment register - if ($contractor->isMaintainsTreatmentRegister()) { - ++$nbMaintainsTreatmentRegister; - } - // Sending data outside EU - if ($contractor->isSendingDataOutsideEu()) { - ++$nbSendingDataOutsideEu; - } } } @@ -122,7 +144,7 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat 'Clauses contractuelles vérifiées', 'Adopte les éléments de sécurité nécessaires', 'Tient à jour un registre des traitements', - 'Envoi des données hors UE', + 'Les données restent dans l\'Union européenne', ], ]; // Add content @@ -185,7 +207,7 @@ class ContractorGenerator extends AbstractGenerator implements ImpressionGenerat $contractor->isMaintainsTreatmentRegister() ? 'Oui' : 'Non', ], [ - 'Envoi des données hors UE', + 'Les données restent dans l\'Union européenne', $contractor->isSendingDataOutsideEu() ? 'Oui' : 'Non', ], [ diff --git a/src/Domain/Reporting/Generator/Word/TreatmentGenerator.php b/src/Domain/Reporting/Generator/Word/TreatmentGenerator.php index e2f7bb821f7f74526f75cf2418967649e8314b80..35fa660c0d00835d261cd4cdf9a255c74883f631 100644 --- a/src/Domain/Reporting/Generator/Word/TreatmentGenerator.php +++ b/src/Domain/Reporting/Generator/Word/TreatmentGenerator.php @@ -470,33 +470,33 @@ class TreatmentGenerator extends AbstractGenerator implements ImpressionGenerato 'Est exempté d\'AIPD', $treatment->isExemptAIPD() ? 'Oui' : 'Non', ], - [ - 'Surveillance systématique', - $treatment->isSystematicMonitoring() ? 'Oui' : 'Non', - ], [ 'Collecte à large échelle', $treatment->isLargeScaleCollection() ? 'Oui' : 'Non', ], [ - 'Personnes vulnérables', - $treatment->isVulnerablePeople() ? 'Oui' : 'Non', + 'Croisement d\'ensemble de données', + $treatment->isDataCrossing() ? 'Oui' : 'Non', ], [ - 'Croisement de données', - $treatment->isDataCrossing() ? 'Oui' : 'Non', + 'Décision automatique avec effet juridique', + $treatment->isAutomatedDecisionsWithLegalEffect() ? 'Oui' : 'Non', ], [ 'Évaluation ou notation', $treatment->isEvaluationOrRating() ? 'Oui' : 'Non', ], [ - 'Décisions automatisées avec effet', - $treatment->isAutomatedDecisionsWithLegalEffect() ? 'Oui' : 'Non', + 'Exclusion du bénéfice d\'un droit, d’un service ou contrat', + $treatment->isAutomaticExclusionService() ? 'Oui' : 'Non', ], [ - 'Exclusion automatique d\'un service', - $treatment->isAutomaticExclusionService() ? 'Oui' : 'Non', + 'Personnes vulnérables', + $treatment->isVulnerablePeople() ? 'Oui' : 'Non', + ], + [ + 'Surveillance systématique', + $treatment->isSystematicMonitoring() ? 'Oui' : 'Non', ], [ 'Usage innovant', @@ -614,13 +614,13 @@ class TreatmentGenerator extends AbstractGenerator implements ImpressionGenerato $cell->addText('Type de données', $this->textHeadStyle); $titles = ['Données sensibles', - 'Surveillance systématique', 'Collecte à large échelle', - 'Personnes vulnérables', - 'Croisement de données', + 'Croisement d\'ensemble de données', + 'Décision automatique avec effet juridique', 'Évaluation ou notation', - 'Décisions automatisées avec effet', - 'Exclusion automatique d\'un service', + 'Exclusion du bénéfice d\'un droit, d’un service ou contrat', + 'Personnes vulnérables', + 'Surveillance systématique', 'Usage innovant', 'CNIL AIPD exemptée', '', @@ -645,13 +645,13 @@ class TreatmentGenerator extends AbstractGenerator implements ImpressionGenerato $cnt_sensible = 0; $sensibleDatas = []; $specificTreatments = []; - $item->isSystematicMonitoring() ? $specificTreatments[] = 'Surveillance systématique' : null; $item->isLargeScaleCollection() ? $specificTreatments[] = 'Collecte à large échelle' : null; - $item->isVulnerablePeople() ? $specificTreatments[] = 'Personnes vulnérables' : null; - $item->isDataCrossing() ? $specificTreatments[] = 'Croisement de données' : null; + $item->isDataCrossing() ? $specificTreatments[] = 'Croisement d’ensemble de données' : null; + $item->isAutomatedDecisionsWithLegalEffect() ? $specificTreatments[] = 'Décision automatique avec effet juridique' : null; $item->isEvaluationOrRating() ? $specificTreatments[] = 'Évaluation ou notation' : null; - $item->isAutomatedDecisionsWithLegalEffect() ? $specificTreatments[] = 'Décisions automatisées avec effet' : null; - $item->isAutomaticExclusionService() ? $specificTreatments[] = "Exclusion automatique d'un service" : null; + $item->isAutomaticExclusionService() ? $specificTreatments[] = 'Exclusion du bénéfice d\'un droit, d’un service ou contrat' : null; + $item->isVulnerablePeople() ? $specificTreatments[] = 'Personnes vulnérables' : null; + $item->isSystematicMonitoring() ? $specificTreatments[] = 'Surveillance systématique' : null; $item->isInnovativeUse() ? $specificTreatments[] = 'Usage innovant' : null; $cnt_categories = count(array_filter($specificTreatments)); @@ -677,20 +677,20 @@ class TreatmentGenerator extends AbstractGenerator implements ImpressionGenerato } $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $cnt_sensible > 0 ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($cnt_sensible > 0 ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); - $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isSystematicMonitoring() ? 'ffa7a7' : null, 'valign' => 'center']); - $cell->addText($item->isSystematicMonitoring() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isLargeScaleCollection() ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($item->isLargeScaleCollection() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); - $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isVulnerablePeople() ? 'ffa7a7' : null, 'valign' => 'center']); - $cell->addText($item->isVulnerablePeople() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isDataCrossing() ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($item->isDataCrossing() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); - $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isEvaluationOrRating() ? 'ffa7a7' : null, 'valign' => 'center']); - $cell->addText($item->isEvaluationOrRating() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isAutomatedDecisionsWithLegalEffect() ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($item->isAutomatedDecisionsWithLegalEffect() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); + $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isEvaluationOrRating() ? 'ffa7a7' : null, 'valign' => 'center']); + $cell->addText($item->isEvaluationOrRating() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isAutomaticExclusionService() ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($item->isAutomaticExclusionService() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); + $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isVulnerablePeople() ? 'ffa7a7' : null, 'valign' => 'center']); + $cell->addText($item->isVulnerablePeople() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); + $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isSystematicMonitoring() ? 'ffa7a7' : null, 'valign' => 'center']); + $cell->addText($item->isSystematicMonitoring() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isInnovativeUse() ? 'ffa7a7' : null, 'valign' => 'center']); $cell->addText($item->isInnovativeUse() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isExemptAIPD() ? 'bce292' : 'ffa7a7', 'valign' => 'center']); diff --git a/templates/Aipd/Analyse_impact/_form_step_3.html.twig b/templates/Aipd/Analyse_impact/_form_step_3.html.twig index 89c60a1efd384e9463a84622e12cf43fae7d4e7a..0563aa1d87f08b7b58bac30ed4707cbd8032de06 100644 --- a/templates/Aipd/Analyse_impact/_form_step_3.html.twig +++ b/templates/Aipd/Analyse_impact/_form_step_3.html.twig @@ -47,7 +47,7 @@ {% endif %} </td> <th scope="row">{{ scenario.vars.value.nom }}</th> - <td> + <td class="vraisemblance"> {% if scenario.vars.value.canVraisemblanceBeModified %} {{ form_widget(scenario.vraisemblance) }} {% else %} @@ -57,7 +57,7 @@ </div> {% endif %} </td> - <td> + <td class="gravite"> {% if scenario.vars.value.canGraviteBeModified %} {{ form_widget(scenario.gravite) }} {% else %} @@ -66,11 +66,10 @@ {{ form_widget(scenario.gravite) }} </div> {% endif %} + </td> <td class="impact-potentiel"> {% if scenario.vars.value.gravite is not null and scenario.vars.value.gravite != 'vide' and scenario.vars.value.vraisemblance is not null and scenario.vars.value.vraisemblance != 'vide' %} - <span> - {{ getScenarioMenaceImpactPotentielLabel(scenario.vars.value)|raw }} - </span> + {{ getScenarioMenaceImpactPotentielLabel(scenario.vars.value)|raw }} {% endif %} </td> <td>{{ form_widget(scenario.precisions) }}</td> @@ -78,3 +77,73 @@ {% endfor %} </tbody> </table> + +{% block javascripts %} + <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script> + + <script> + $(document).ready(function() { + // Fonction pour récupérer le texte ou la valeur d'un sélecteur d'une cellule + function getCellData($cell) { + var $select = $cell.find('select'); + if ($select.length) { + return $select.find('option:selected').text(); // Retourne le texte de l'option sélectionnée + } else { + return $cell.text().trim(); // Si c'est du texte, retourner le contenu texte + } + } + + // Fonction pour calculer le résultat dans la colonne "impact-potentiel" + function calculateImpact(vraisemblance, gravite) { + // Matrice d'évaluation de l'impact + if ((vraisemblance === "Négligeable" && gravite === "Négligeable") || + (vraisemblance === "Limitée" && gravite === "Négligeable") || + (vraisemblance === "Négligeable" && gravite === "Limitée") || + (vraisemblance === "Limitée" && gravite === "Limitée")) { + return '<span class="label label-success" style="min-width: 100%; display: inline-block;">Négligeable</span>'; + } else if ((vraisemblance === "Négligeable" && gravite === "Importante") || + (vraisemblance === "Limitée" && gravite === "Importante") || + (vraisemblance === "Négligeable" && gravite === "Maximale") || + (vraisemblance === "Limitée" && gravite === "Maximale")) { + return '<span class="label label-default" style="min-width: 100%; display: inline-block !important;background:#605CA8; color:white;">Important</span>'; + } else if ((vraisemblance === "Importante" && gravite === "Importante") || + (vraisemblance === "Maximale" && gravite === "Importante") || + (vraisemblance === "Importante" && gravite === "Maximale") || + (vraisemblance === "Maximale" && gravite === "Maximale")) { + return '<span class="label label-danger" style="min-width: 100%; display: inline-block;">Maximal</span>'; + } else { + return '<span class="label label-warning" style="min-width: 100%; display: inline-block;">Limité</span>'; + } + } + + // Mettre à jour la cellule dans la colonne "impact-potentiel" + function updateImpactPotentiel(index) { + var $vraisemblanceCell = $('td.vraisemblance').eq(index); + var $graviteCell = $('td.gravite').eq(index); + + var vraisemblanceData = getCellData($vraisemblanceCell); + var graviteData = getCellData($graviteCell); + + var impactData = calculateImpact(vraisemblanceData, graviteData); + + var $impactCell = $('td.impact-potentiel').eq(index); + + // Si la cellule "impact-potentiel" existe, met à jour son contenu + if ($impactCell.length) { + $impactCell.html(impactData); + } + } + + // Initialiser les cellules "impact-potentiel" lors du chargement de la page + $('td.vraisemblance').each(function(index) { + updateImpactPotentiel(index); + }); + + // Mettre à jour la cellule "impact-potentiel" quand un sélecteur est modifié + $('select.vraisemblance-dropdown, select.gravite-dropdown').on('change', function() { + var index = $(this).closest('td').parent().index(); + updateImpactPotentiel(index); + }); + }); + </script> +{% endblock %} diff --git a/templates/Aipd/Analyse_impact/edit.html.twig b/templates/Aipd/Analyse_impact/edit.html.twig index 13c2c0d550b1af7265a76d053e9ff6562af0be98..f85c6e8cb683350d5d83d733900ef59e459c8212 100644 --- a/templates/Aipd/Analyse_impact/edit.html.twig +++ b/templates/Aipd/Analyse_impact/edit.html.twig @@ -101,19 +101,3 @@ {{ form_end(form) }} {% endblock %} -{% block javascripts %} - <script> - $(document).ready(function() { - const $table=$('#step3-table'); - function hideLabel(ev) { - const $t = $(ev.target); - const $row = $t.parents('tr') - const $label = $row.find('.impact-potentiel > span') - $label.hide(); - } - $table.find('.vraisemblance-dropdown').on('change', hideLabel) - $table.find('.gravite-dropdown').on('change', hideLabel) - }) - - </script> -{% endblock %} diff --git a/templates/Aipd/Analyse_impact/evaluation.html.twig b/templates/Aipd/Analyse_impact/evaluation.html.twig index a80d3ae0443e9f37d12b33d0dc0d35b00133a724..1fe046ccccddba8592d5588b77db6b7df15165b4 100644 --- a/templates/Aipd/Analyse_impact/evaluation.html.twig +++ b/templates/Aipd/Analyse_impact/evaluation.html.twig @@ -26,6 +26,22 @@ {% endblock %} {% block body %} + {% if is_granted('ROLE_PREVIEW') %} + <div class="row"> + <div class="col-xs-12"> + <div class="mb-1"> + <a href="{{ path('aipd_analyse_impact_list') }}" class="btn btn-default"> + <i aria-hidden="true" class="fa fa-arrow-left"></i> + {{ 'global.action.back_to_list'|trans }} + </a> + <a href="{{ path('aipd_analyse_impact_print', {'id': analyseImpact.id}) }}" class="btn btn-default"> + <i aria-hidden="true" class="fa fa-print"></i> + {{ 'global.action.print'|trans }} + </a> + </div> + </div> + </div> + {% endif %} <div class="row"> {# LEFT #} @@ -130,7 +146,6 @@ <div class="box-body text-center"> <a href="{{ path('aipd_analyse_impact_list') }}" class="btn btn-default">{{ 'global.action.back_to_list'|trans }}</a> <a href="{{ path('aipd_analyse_impact_validation', {'id': analyseImpact.id}) }}" class="btn btn-primary">{{ 'aipd.analyse_impact.action.validation'|trans }}</a> - <a href="{{ path('aipd_analyse_impact_list') }}" class="btn btn-info">{{ 'global.action.draft'|trans }}</a> </div> </div> </div> @@ -222,6 +237,4 @@ {{ encore_entry_script_tags('js/evaluation') }} - - {% endblock %} diff --git a/templates/Aipd/Analyse_impact/pdf.html.twig b/templates/Aipd/Analyse_impact/pdf.html.twig index 88455be6a0ee74faa1177e49edd7a275436dbb60..94b482c373acd636553331ce5a3f2568f8013014 100644 --- a/templates/Aipd/Analyse_impact/pdf.html.twig +++ b/templates/Aipd/Analyse_impact/pdf.html.twig @@ -1,1798 +1,1808 @@ <!DOCTYPE html> <html lang="fr-FR"> -<head> - <title>{% block title %}{% endblock %}</title> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> - - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css"> - <link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.5.2/css/all.css" crossorigin="anonymous" referrerpolicy="no-referrer"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.17/css/AdminLTE.min.css"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.17/css/skins/_all-skins.min.css"> - <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/css/bootstrap-select.min.css"> - - <!-- Google Font --> - <link rel="stylesheet" - href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> - <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script> - <style> - .content-wrapper { - background-color: white !important; - z-index: 800; - } - - h1 { - text-align: center; - font-size: 55px; - } - - h1, h2, h3, h4 { - color: #3674b6; - } - table { - border: 1px solid black; - } - - .table-bluecell { - background: #3674b6; - color: white; - width: 45%; - } - .separator { - height: 25px; - } - - .annexe-head { - color: #3674b6; - font-size: 1.2em; - margin-top: 20px; - } - .annexe-prelink { - margin-left: 25px; - } - .annexe-link { - color: #3674b6; - } - - .table-indicateur-head { - background: #808080; - color: white; - text-align: center; - } - .table-indicateur-maximale { - background: #c00000; - color: white; - text-align: center; - } - .table-indicateur-importante { - background: #ed7d31; - text-align: center; - } - .table-indicateur-limitee { - background: #ffc000; - text-align: center; - } - .table-indicateur-negligeable { - background: #6fad47; - text-align: center; - } - .reportGraph { - width:900px - } - </style> -</head> - -<body class="hold-transition skin-blue sidebar-mini"> -<div class="content-wrapper"> - <section class="content-header"> - <h1 style="font-size: 55px">Analyse d'Impact relative à la Protection des Données</h1> - <div class="separator"></div> - <div style="text-align: center; font-size: 2em"> Instruction du dossier</div> - </section> - - <div class="content container-fluid"> - - <div class="row" style="text-align: center"><h2>{{ object.conformiteTraitement.traitement.name }}</h2></div> - <div class="row" style="text-align: center"><h2>{{ object.conformiteTraitement.traitement.collectivity.name }}</h2></div> - - <div class="separator"></div> - <div class="separator"></div> - <div class="row"> - <div><strong style="font-size: 1.6em; margin-left:30px;">Responsable du traitement</strong></div> - <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.legalManager.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.legalManager.firstName }} {{ object.conformiteTraitement.traitement.collectivity.legalManager.lastName }}</span> - </div> - <div class="separator"></div> - <div class="row"> - <div><strong style="font-size: 1.6em; margin-left:30px;">Référent RGPD</strong></div> - <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.referent.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.referent.firstName }} {{ object.conformiteTraitement.traitement.collectivity.referent.lastName }}</span> - </div> - <div class="separator"></div> - <div class="row"> - <div><strong style="font-size: 1.6em; margin-left:30px;">Délégué à la Protection des Données</strong></div> - {% if object.conformiteTraitement.traitement.collectivity.differentDpo %} - <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.dpo.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.dpo.firstName }} {{ object.conformiteTraitement.traitement.collectivity.dpo.lastName }}</span> - {% else %} - <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_civility|dictionary('user_contact_civility') }} {{ default_dpo_firstName }} {{ default_dpo_lastName }}<br/></span> - <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_address_street }}<br/></span> - <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_address_zip_code }} {{ default_dpo_address_city}}</span> - {% endif %} - </div> - <div class="separator"></div> - <div class="row"> - <div> - <strong style="font-size: 1.6em; margin-left:30px;">Date de validation de l’AIPD : </strong> - <strong style="font-size: 1.6em; margin-left:150px;">Signature du Responsable du Traitement</strong> - </div> - <span style="font-size: 1.2em; margin-left:45px;">{{ (object.conformiteTraitement.analyseImpacts|first).dateValidation|date('d/m/Y') }}</span> - </div> - - <div style="page-break-before: always;"></div> - <div class="separator"></div> - <h2 style="text-align: center;">Sommaire</h2> - <div class="separator"></div> - <div class="separator"></div> - <ul> - <li>1. Préambule - <ul> - <li>1.1 Méthode d'une Analyse d'Impact relative à la Protection des Données</li> - <li>1.2 Conformité d’une Analyse d’Impact relative à la Protection des Données</li> - </ul> - </li> - <li>2. Étude du contexte</li> - <li>3. Études des principes fondamentaux</li> - <li>4. Études des risques liés à la sécurité des données - <ul> - <li>4.1 Évaluation des risques sur les droits et les libertés des personnes concernées</li> - <li>4.2 Évaluation de l'impact et matrice de décision</li> - <li>4.3 Mesure(s) de réduction des risques envisagée(s)</li> - <li>4.4 Risques résiduels</li> - </ul> - </li> - <li>5. Validation de l'AIPD - <ul> - <li>Avis des personnes consultées</li> - </ul> - </li> - <li>6. Annexes - <ul> - <li>6.1 Glossaire</li> - <li>6.2 Références</li> - <li>6.3 Fiche de traitement</li> - </ul> - </li> - </ul> + <head> + <title>{% block title %}{% endblock %}</title> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css"> + <link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.5.2/css/all.css" crossorigin="anonymous" referrerpolicy="no-referrer"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.17/css/AdminLTE.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.17/css/skins/_all-skins.min.css"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/css/bootstrap-select.min.css"> + <!-- Google Font --> + <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script> + <style> + h1 { + text-align: center; + font-size: 55px !important; + } + h1, h2, h3, h4, .h2 { + color: #3674b6; + } + dt { + color: #3674b6; + font-size: 1.2em; + margin-top: 20px; + } + .txt-center { + text-align: center; + } + .fs-2 { + font-size: 2em; + } + .fs-3 { + font-size: 2.5em; + } + .table-bluecell { + background: #3674b6; + color: white; + width: 45%; + } + .separator { + height: 25px; + } + .table-indicateur-head { + background: #808080; + color: white; + text-align: center; + } + .table-indicateur-maximale { + background: #c00000; + color: white; + text-align: center; + } + .table-indicateur-importante { + background: #ed7d31; + text-align: center; + } + .table-indicateur-limitee { + background: #ffc000; + text-align: center; + } + .table-indicateur-negligeable { + background: #6fad47; + text-align: center; + } + .reportGraph { + width:850px; + } + </style> + </head> - <div style="page-break-before: always;"> - <h2>1. Préambule</h2> - </div> - <div>Le présent document contient tous les éléments nécessaires pour le Responsable de Traitement (RT), le Référent RGPD (RR) et le Délégué à la Protection des Données (DPD) pour mener à bien une Analyse d'Impact relative à la Protection des Données (le sigle AIPD sera utilisé dans la suite de ce document) conforme aux attentes de la CNIL.</div> - <div>Il est possible de retrouver l'ensemble des éléments produits dans ce document dans le logiciel Madis.</div> - - <h3>1.1 Méthode d'une Analyse d'Impact relative à la Protection des Données</h3> - <div>La démarche pour réaliser une analyse d'impact comprend quatre étapes :</div> - <div style="margin-left:50px;">1- Délimiter et décrire le contexte du(des) traitement(s) considéré(s);</div> - <div style="margin-left:50px;">2- Analyser les mesures garantissant le respect des principes fondamentaux : la proportionnalité et la nécessité du traitement, et la protection des droits des personnes concernées;</div> - <div style="margin-left:50px;">3- Apprécier les risques sur la vie privée liés à la sécurité des données et vérifier qu’ils sont convenablement traités ;</div> - <div style="margin-left:50px;">4- Formaliser la validation de l’AIPD au regard des éléments précédents ou bien décider de réviser les étapes précédentes.</div> - - <div style="text-align: center"><img src="{{ base_dir ~ asset("images/cycleAIPD.jpg") }}" height="300" alt="CycleAIPD"></div> - - <div>Il s'agit d'un <strong>processus d'amélioration continue</strong>. Il requiert donc parfois plusieurs itérations pour parvenir à un dispositif de protection de la vie privée acceptable. Il requiert en outre une surveillance des évolutions dans le temps (du contexte, des mesures, des risques, etc.), par exemple tous les ans, et des mises à jour dès qu'une évolution significative a lieu.</div> - <div>La démarche devrait être employée <strong>dès la conception d'un nouveau traitement de données à caractère personnel</strong>. En effet, une application en amont permet de déterminer les mesures nécessaires et suffisantes, et donc d'optimiser les coûts. A contrario, une application tardive, alors que le système est déjà créé et les mesures en place, peut remettre en question les choix effectués.</div> - - <h3>1.2 Conformité d’une Analyse d’Impact relative à la Protection des Données</h3> - <div>L’objectif est d’obtenir la conformité du traitement grâce à l’AIPD</div> - <div class="separator"></div> - <div style="text-align: center"><img src="{{ base_dir ~ asset("images/ConformiteAIPD.png") }}" width="800" alt="ConformitéAIPD"></div> - - <div style="page-break-before: always;"></div> - <h2>2. Étude du contexte</h2> - <div>Ce chapitre a pour objectif de fournir une vision claire de la structure et du traitement de données personnelles considéré</div> - <div class="separator"></div> - <div class="col-md-6"> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Nature du traitement</td> - <td>{{ object.conformiteTraitement.traitement.name }}</td> - </tr> - </table> - <div class="separator"></div> - {% set critere = object.criterePrincipeFondamentalByCode('contexte_traitement') %} - {% if critere and critere.reponse != 'non_renseigne' %} - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">{{ critere.labelLivrable }}</td> - <td> - La conformité : - {% if critere.reponse == 'conforme' %} - <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> - {% elseif critere.reponse == 'non_conforme' %} - <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> - {% elseif critere.reponse == 'non_applicable' %} - <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> - {% endif %} - <br/> - {% if critere.justification is not null %} - <i>Justification : </i>{{ critere.justification }}<br /> - {% endif %} - </td> - </tr> - {% if critere.fichier %} - <tr> - <td colspan="2" style="text-align: center"> - <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> - </td> - </tr> - {% endif %} - </table> + <body> + <div> + <section> + <h1>Analyse d'Impact relative à la Protection des Données</h1> <div class="separator"></div> - {% endif %} + <p class="txt-center fs-2">Instruction du dossier</p> + </section> + + <section> + <p class="h2 txt-center fs-3">{{ object.conformiteTraitement.traitement.name }}</p> + <p class="h2 txt-center fs-3">{{ object.conformiteTraitement.traitement.collectivity.name }}</p> - {% set critere = object.criterePrincipeFondamentalByCode('portee_traitement') %} - {% if critere and critere.reponse != 'non_renseigne' %} - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">{{ critere.labelLivrable }}</td> - <td> - La conformité : - {% if critere.reponse == 'conforme' %} - <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> - {% elseif critere.reponse == 'non_conforme' %} - <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> - {% elseif critere.reponse == 'non_applicable' %} - <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> - {% endif %} - <br/> - {% if critere.justification is not null %} - <i>Justification : </i>{{ critere.justification }}<br /> - {% endif %} - </td> - </tr> - {% if critere.fichier %} - <tr> - <td colspan="2" style="text-align: center"> - <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> - </td> - </tr> - {% endif %} - </table> <div class="separator"></div> - {% endif %} - - - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Finalité(s) du traitement</td> - <td> - {{ object.conformiteTraitement.traitement.goal }}</td> - </tr> - </table> - <div class="separator"></div> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Données à caractère personnel</td> - <td> - {% for category in object.conformiteTraitement.traitement.dataCategories %} - {{ category }}<br/> - {% endfor %} - {{ object.conformiteTraitement.traitement.dataCategoryOther }} - </td> - </tr> - </table> - <div class="separator"></div> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Destinataires</td> - <td> - {{ object.conformiteTraitement.traitement.recipientCategory }} - {% for contractor in object.conformiteTraitement.traitement.contractors %} - <br/>{{ contractor }} - {% endfor %} - </td> - </tr> - </table> - <div class="separator"></div> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Durée de conservation</td> - <td> - {% for duration in object.conformiteTraitement.traitement.shelfLifes %} - {{ duration.name }} - {{ duration.duration }} - {{ duration.ultimateFate }} <br/> - {% endfor %} - </td> - </tr> - </table> - <div class="separator"></div> - {% set critere = object.criterePrincipeFondamentalByCode('identification_biens') %} - {% if critere and critere.reponse != 'non_renseigne' %} - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">{{ critere.labelLivrable }}</td> - <td> - La conformité : - {% if critere.reponse == 'conforme' %} - <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> - {% elseif critere.reponse == 'non_conforme' %} - <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> - {% elseif critere.reponse == 'non_applicable' %} - <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> - {% endif %} - <br/> - {% if critere.justification is not null %} - <i>Justification : </i>{{ critere.justification }}<br /> - {% endif %} - </td> - </tr> - {% if critere.fichier %} - <tr> - <td colspan="2" style="text-align: center"> - <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> - </td> - </tr> - {% endif %} - </table> <div class="separator"></div> - {% endif %} - {% set critere = object.criterePrincipeFondamentalByCode('description_fonctionnelle') %} - {% if critere and critere.reponse != 'non_renseigne' %} - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">{{ critere.labelLivrable }}</td> - <td> - La conformité : - {% if critere.reponse == 'conforme' %} - <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> - {% elseif critere.reponse == 'non_conforme' %} - <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> - {% elseif critere.reponse == 'non_applicable' %} - <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> - {% endif %} - <br/> - {% if critere.justification is not null %} - <i>Justification : </i>{{ critere.justification }}<br /> - {% endif %} - </td> - </tr> - {% if critere.fichier %} - <tr> - <td colspan="2" style="text-align: center"> - <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> - </td> - </tr> - {% endif %} - </table> + <div class="row"> + <div><strong style="font-size: 1.6em; margin-left:30px;">Responsable du traitement</strong></div> + <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.legalManager.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.legalManager.firstName }} {{ object.conformiteTraitement.traitement.collectivity.legalManager.lastName }}</span> + </div> <div class="separator"></div> - {% endif %} - {% set critere = object.criterePrincipeFondamentalByCode('conformite_code') %} - {% if critere and critere.reponse != 'non_renseigne' %} - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">{{ critere.labelLivrable }}</td> - <td> - La conformité : - {% if critere.reponse == 'conforme' %} - <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> - {% elseif critere.reponse == 'non_conforme' %} - <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> - {% elseif critere.reponse == 'non_applicable' %} - <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> - {% endif %} - <br/> - {% if critere.justification is not null %} - <i>Justification : </i>{{ critere.justification }}<br /> - {% endif %} - </td> - </tr> - {% if critere.fichier %} - <tr> - <td colspan="2" style="text-align: center"> - <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> - </td> - </tr> + <div class="row"> + <div><strong style="font-size: 1.6em; margin-left:30px;">Référent RGPD</strong></div> + <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.referent.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.referent.firstName }} {{ object.conformiteTraitement.traitement.collectivity.referent.lastName }}</span> + </div> + <div class="separator"></div> + <div class="row"> + <div><strong style="font-size: 1.6em; margin-left:30px;">Délégué à la Protection des Données</strong></div> + {% if object.conformiteTraitement.traitement.collectivity.differentDpo %} + <span style="font-size: 1.2em; margin-left:45px;">{{ object.conformiteTraitement.traitement.collectivity.dpo.civility|dictionary('user_contact_civility') }} {{ object.conformiteTraitement.traitement.collectivity.dpo.firstName }} {{ object.conformiteTraitement.traitement.collectivity.dpo.lastName }}</span> + {% else %} + <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_civility|dictionary('user_contact_civility') }} {{ default_dpo_firstName }} {{ default_dpo_lastName }}<br/></span> + <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_address_street }}<br/></span> + <span style="font-size: 1.2em; margin-left:45px;">{{ default_dpo_address_zip_code }} {{ default_dpo_address_city}}</span> {% endif %} - </table> + </div> <div class="separator"></div> - {% endif %} - </div> + <div class="row"> + <div> + <strong style="font-size: 1.6em; margin-left:30px;">Date de validation de l’AIPD : </strong> + <strong style="font-size: 1.6em; margin-left:150px;">Signature du Responsable du Traitement</strong> + </div> + <span style="font-size: 1.2em; margin-left:45px;">{{ (object.conformiteTraitement.analyseImpacts|first).dateValidation|date('d/m/Y') }}</span> + </div> - <div style="page-break-before: always;"></div> - <h2>3. Études des principes fondamentaux</h2> - <div>Ce chapitre a pour objectif de s’assurer que le dispositif relatif aux principes de protection de la vie privée est conforme.</div> - <div class="separator"></div> - <table class="table table-bordered"> - <thead> - <tr> - <th>Description</th> - <th>Conformité</th> - </tr> - </thead> - {% for critere in object.criterePrincipeFondamentaux %} - <tr> - <td>{{ critere.labelLivrable }}</td> - <td>{{ getCritereLabel(critere)|raw }}</td> - </tr> - {% endfor %} - </table> - <table class="table table-bordered"> - <thead> - <tr> - <th>Principes fondamentaux</th> - <th>Conformité</th> - </tr> - </thead> - <tbody> - {% for questionConformite in object.questionConformites|sort((a, b) => a.position >= b.position) %} - <tr> - {% set reponse = object.conformiteTraitement.getReponseOfName(questionConformite.question) %} - <td>{{ questionConformite.question }} - {% if questionConformite.justificatif is not null %} - <div style="margin-left: 20px;font-size:12px;"> - <span>Justification : {{ questionConformite.justificatif }}</span> - </div> - {% endif %} + <div style="page-break-before: always;"></div> - {% if reponse and (reponse.actionProtections is not null) and (reponse.actionProtections|length > 0) %} - <div style="margin-left: 20px;font-size:12px;"> - <span>Actions associées : </span> - </div> - <ul> - {% for action in reponse.actionProtections %} - <li style="margin-left: 20px;font-size:12px;">{{action.name}}</li> - {% endfor %} - </ul> - {% endif %} - </td> - {% if reponse and reponse.conforme %} - <td><span class="label label-success" style="min-width: 100%; display: inline-block;"> Conforme</span></td> - {% else %} - {% if reponse and reponse.actionProtections|length > 0 %} - <td><span class="label label-warning" style="min-width: 100%; display: inline-block;"> Non-conforme mineure</span></td> - {% else%} - <td><span class="label label-danger" style="min-width: 100%; display: inline-block;"> Non-conforme majeure</span></td> - {% endif %} - {% endif %} - </tr> - {% endfor %} - </tbody> - </table> - <div>Le graphique ci-dessous indique les points d’amélioration nécessaires au respect des principes fondamentaux du règlement.</div> - <div class="separator"></div> - <div class="reportGraph"><canvas id="grandsDomaines-chart"></canvas></div> - <div style="page-break-before: always;"></div> - <h2>4. Études des risques liés à la sécurité des données</h2> - <div>Ce chapitre a pour objectifs d'obtenir une bonne connaissance des mesures contribuant à la sécurité et d'apprécier les risques.</div> - <h3>4.1 Évaluation des risques sur les droits et les libertés des personnes concernées</h3> - <div style="text-align: center"><img src="{{ base_dir ~ asset("images/NiveauRisque.png") }}" height="300" alt="Niveau risque"></div> - <table class="table table-bordered"> - <tr class="table-indicateur-head"> - <td>Niveaux</td> - <td>Descriptions génériques de l'échelle de gravité</td> - </tr> - <tr> - <td class="table-indicateur-maximale">Maximale</td> - <td>Les personnes concernées pourraient connaître des conséquences significatives, voire irrémédiables, qu'elles pourraient ne pas surmonter</td> - </tr> - <tr> - <td class="table-indicateur-importante">Importante</td> - <td>Les personnes concernées pourraient connaître des conséquences significatives, qu'elles devraient pouvoir surmonter, mais avec des difficultés réelles et significatives</td> - </tr> - <tr> - <td class="table-indicateur-limitee">Limitée</td> - <td>Les personnes concernées pourraient connaître des désagréments significatifs, qu'elles pourront surmonter malgré quelques difficultés</td> - </tr> - <tr> - <td class="table-indicateur-negligeable">Négligeable</td> - <td>Les personnes concernées ne seront pas impactés ou pourraient connaître quelques désagréments, qu'elles surmonteront sans difficulté</td> - </tr> - </table> - - <table class="table table-bordered"> - <tr class="table-indicateur-head"> - <td>Niveaux</td> - <td>Descriptions génériques de l'échelle de vraisemblance</td> - </tr> - <tr> - <td class="table-indicateur-maximale">Maximale</td> - <td>Il semble extrêmement facile pour les sources des risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papier stockés dans le hall public de la structure).</td> - </tr> - <tr> - <td class="table-indicateur-importante">Importante</td> - <td>Il semble possible pour les sources de risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans les bureaux d'une structure dont l'accès est contrôlé par une personne à l'accueil).</td> - </tr> - <tr> - <td class="table-indicateur-limitee">Limitée</td> - <td>Il semble difficile pour les sources de risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans un local de la structure dont l'accès est contrôlé par badge).</td> - </tr> - <tr> - <td class="table-indicateur-negligeable">Négligeable</td> - <td>Il ne semble pas possible que les sources de risques retenues puissent réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans un local de la structure dont l'accès est contrôlé par badge et code d'accès).</td> - </tr> - </table> - <div style="text-align: center"><img src="{{ base_dir ~ asset("images/matriceAIPD.png") }}" height="300" alt="MatriceAIPD"></div> - - <div style="page-break-before: always;"></div> - <h3>4.2 Évaluation de l'impact et matrice de décision</h3> - <div>Le tableau ci-dessous identifie des scénarios de menaces pour lesquels une évaluation est réalisée sur la vraisemblance (risques d’occurrence) et la gravité (conséquences en cas d’évènement). D, I et C représentent les critères de classification de l'information : <b>D</b>isponibilité, <b>I</b>ntégrité, <b>C</b>onfidentialité.</div> - <div class="separator"></div> - <table class="table table-bordered"> - <tr> - <th>D</th> - <th>I</th> - <th>C</th> - <th>Scénario de menace</th> - <th>Vraisemblance</th> - <th>Gravité</th> - <th>Impact potentiel</th> - </tr> - {% for scenario in object.scenarioMenaces|sort((a,b) => a.nom <=> b.nom) %} - <tr> - <td>{% if scenario.isDisponibilite %}X{% endif %}</td> - <td>{% if scenario.isIntegrite %}X{% endif %}</td> - <td>{% if scenario.isConfidentialite %}X{% endif %}</td> - <td>{{ scenario.nom }}</td> - <td>{{ scenario.vraisemblance|dictionary('vraisemblance_gravite') }}</td> - <td>{{ scenario.gravite|dictionary('vraisemblance_gravite') }}</td> - <td>{{ getScenarioMenaceImpactPotentielLabel(scenario)|raw }}</td> - </tr> - {% endfor %} - </table> - <div>La CNIL préconise d’accepter les risques uniquement lorsque l’impact est négligeable. Dans les autres cas, il faudra apporter des mesures de protection supplémentaires pour venir corriger les anomalies identifiées. Dans le cas où le risque est maximal et que les mesures ne sont pas jugées suffisantes, il conviendra de solliciter l’avis de la CNIL.</div> - <div>La matrice de décision ci-dessous vous informe du comportement attendu par la CNIL selon le niveau d'impact identifié :</div> - <div style="text-align: center"><img src="{{ base_dir ~ asset("images/MatriceDecision.png") }}" height="300" alt="MatriceDecision"></div> - <br/> - <h3 style="page-break-before: always">4.3 Mesure(s) de réduction des risques mise(s) en place</h3> - <div>Le radar ci-dessous présente les mesures déjà mises en place dans la structure pour réduire l’ensemble des risques identifiés.</div> - <div class="separator"></div> - <div class="reportGraph"><canvas id="mesuresSecurite-chart"></canvas></div> - <div class="separator"></div> - <div class="box box-solid box-primary"> - <div class="box-header with-border">Mesures de protection</div> - <table class="table table-bordered"> - <tr> - <th>Mesure</th> - <th>Avis sur les mesures existantes</th> - <th>Évaluation</th> - <th>Préconisations</th> - </tr> - - {% set mesures = [] %} - {% for scenario in object.scenarioMenaces %} - {% for mesure in scenario.mesuresProtections %} - {% if mesure not in mesures %} - {% set mesures = mesures|merge([mesure])%} - {% endif%} - {% endfor %} - {% endfor %} - {% for element in mesures|sort((a, b) => a.labelLivrable >= b.labelLivrable) %} - <tr> - <td>{{ element.labelLivrable }}</td> - <td>{{ element.detail }}</td> - <td>{% if element.reponse in reponsedictionary(object)|keys %} - {{ element.reponse|reponsedictionary(object) }} - {% else %} - {{ element.reponse }} - {% endif %} - </td> - {% if element.reponse is same as "satisfaisant" %} - <td></td> - {% else %} - <td>{{ element.phrasePreconisation }}</td> - {% endif %} - </tr> - {% endfor %} - </table> - </div> + <h2 class="txt-center">Sommaire</h2> + <ul> + <li>1. Préambule + <ul> + <li>1.1 Méthode d'une Analyse d'Impact relative à la Protection des Données</li> + <li>1.2 Conformité d’une Analyse d’Impact relative à la Protection des Données</li> + </ul> + </li> + <li>2. Étude du contexte</li> + <li>3. Études des principes fondamentaux</li> + <li>4. Études des risques liés à la sécurité des données + <ul> + <li>4.1 Évaluation des risques sur les droits et les libertés des personnes concernées</li> + <li>4.2 Évaluation de l'impact et matrice de décision</li> + <li>4.3 Mesure(s) de réduction des risques envisagée(s)</li> + <li>4.4 Risques résiduels</li> + </ul> + </li> + <li>5. Validation de l'AIPD + <ul> + <li>Avis des personnes consultées</li> + </ul> + </li> + <li>6. Annexes + <ul> + <li>6.1 Glossaire</li> + <li>6.2 Références</li> + <li>6.3 Fiche de traitement</li> + </ul> + </li> + </ul> - <div style="page-break-before: always;"></div> - <h3>4.4 Risques résiduels</h3> - <div>Les risques résiduels correspondent aux risques non traités à ce jour ou pour lesquels des préconisations ont été formulées (voir actions conseillées par le DPD).</div> - <div class="reportGraph"><canvas id="risquesResiduels-chart"></canvas></div> - <br/> - <div class="box box-solid box-primary"> - <div class="box-header with-border">{{ 'aipd.analyse_impact.tab.gestion_risques'|trans }}</div> - <div class="box-body"> - <table class="table table-bordered"> - <tr> - <th>{{ 'aipd.modele_analyse.label.scenario'|trans }}</th> - <th style="width: 20%;">{{ 'aipd.analyse_impact.label.impact_potentiel'|trans }}</th> - <th style="width: 20%;">{{ 'aipd.analyse_impact.label.impact_residuel'|trans }}</th> - </tr> - {% set mesureProtectionNotNegligeable = [] %} - {% for scenario in object.scenarioMenaces|sort((a, b) => a.nom >= b.nom) %} - {% if isScenarioMenaceImpactResiduelImpactNotNegligeable(scenario) %} - {% for mesure in scenario.mesuresProtections %} - {% if mesure not in mesureProtectionNotNegligeable %} - {% set mesureProtectionNotNegligeable = mesureProtectionNotNegligeable|merge([mesure]) %} - {% endif %} - {% endfor %} - <tr> - <td>{{ scenario.nom }}</td> - <td>{{ getScenarioMenaceImpactPotentielLabel(scenario)|raw }}</td> - <td>{{ getScenarioMenaceImpactResiduelLabel(scenario)|raw }}</td> - </tr> - {% endif %} - {% endfor %} - </table> - </div> - </div> - <p>Le graphique ci dessous représente les risques résiduels sur la disponibilité, l'intégrité et la confidentialité des données à caractère personnel</p> - <div class="reportGraph"><canvas id="dicResiduels-chart"></canvas></div> - <div class="separator"></div> - <div>Le plan d’actions ci-après présente les mesures de sécurité liées aux seuls scénarios de menaces dont l’impact est refusé.</div> - <div class="separator"></div> - <div class="box box-solid box-primary"> - <div class="box-header with-border">Plan d'actions</div> - <div class="box-body"> + <div style="page-break-before: always;"></div> + + <h2>1. Préambule</h2> + <p>Le présent document contient tous les éléments nécessaires pour le Responsable de Traitement (RT), le Référent RGPD (RR) et le Délégué à la Protection des Données (DPD) pour mener à bien une Analyse d'Impact relative à la Protection des Données (le sigle AIPD sera utilisé dans la suite de ce document) conforme aux attentes de la CNIL.</p> + <p>Il est possible de retrouver l'ensemble des éléments produits dans ce document dans le logiciel Madis.</p> + + <h3>1.1 Méthode d'une Analyse d'Impact relative à la Protection des Données</h3> + <p>La démarche pour réaliser une analyse d'impact comprend quatre étapes :</p> + <ol> + <li>Délimiter et décrire le contexte du ou des traitements considérés ;</li> + <li>Analyser les mesures garantissant le respect des principes fondamentaux : la proportionnalité et la nécessité du traitement, et la protection des droits des personnes concernées ;</li> + <li>Apprécier les risques sur la vie privée liés à la sécurité des données et vérifier qu’ils sont convenablement traités ;</li> + <li>Formaliser la validation de l’AIPD au regard des éléments précédents ou bien décider de réviser les étapes précédentes.</li> + </ol> + + <div style="text-align: center"><img src="{{ base_dir ~ asset("images/cycleAIPD.jpg") }}" height="300" alt="Cycle d'une AIPD : 1 contexte, 2 principes fondamentaux, 3 risques, 4 validation"></div> + + <p>Il s'agit d'un <strong>processus d'amélioration continue</strong>. Il requiert donc parfois plusieurs itérations pour parvenir à un dispositif de protection de la vie privée acceptable. Il requiert en outre une surveillance des évolutions dans le temps (du contexte, des mesures, des risques, etc.), par exemple tous les ans, et des mises à jour dès qu'une évolution significative a lieu.</p> + <p>La démarche devrait être employée <strong>dès la conception d'un nouveau traitement de données à caractère personnel</strong>. En effet, une application en amont permet de déterminer les mesures nécessaires et suffisantes, et donc d'optimiser les coûts. A contrario, une application tardive, alors que le système est déjà créé et les mesures en place, peut remettre en question les choix effectués.</p> + + <h3>1.2 Conformité d’une Analyse d’Impact relative à la Protection des Données</h3> + <p>L’objectif est d’obtenir la conformité du traitement grâce à l’AIPD.</p> + + <div style="text-align: center"><img src="{{ base_dir ~ asset("images/ConformiteAIPD.png") }}" width="800" alt="Respect des principes et droits fondamentaux + Gestion des risques liés à la sécurité des données = Conformité"></div> + + <div style="page-break-before: always;"></div> + + <h2>2. Étude du contexte</h2> + <p>Ce chapitre a pour objectif de fournir une vision claire de la structure et du traitement de données personnelles considéré.</p> <table class="table table-bordered"> - <tr> - <th>Mesure</th> - <th>Préconisations</th> - </tr> - {% for mesure in mesureProtectionNotNegligeable|sort((a, b) => a.labelLivrable >= b.labelLivrable) %} - <tr> - <td>{{ mesure.labelLivrable }}</td> - <td>{{ mesure.phrasePreconisation }}</td> - </tr> - {% endfor %} - </table> - </div> - </div> - <div style="page-break-before: always;"></div> - <h2>5. Validation de l'AIPD</h2> - <div>Ce chapitre a pour objectifs de permettre la prise de décision visant à accepter ou non l'AIPD au regard des résultats de l'étude.</div> - - <h3>Avis des personnes consultées</h3> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Avis du référent RGPD</td> - <td>{{ object.avisReferent.reponse|dictionary('reponse_avis') }}</td> - </tr> - {% if object.avisReferent.date is not null %} - <tr> - <td colspan="2">{{ object.avisReferent.date|date('d/m/Y') }}</td> - </tr> - {% endif %} - {% if object.avisReferent.detail is not null %} - <tr> - <td colspan="2">{{ object.avisReferent.detail }}</td> - </tr> - {% endif %} - <tr style="height: 80px"><td colspan="2">Signature :</td></tr> - </table> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Avis du délégué à la protection des données</td> - <td>{{ object.avisDpd.reponse|dictionary('reponse_avis') }}</td> - </tr> - {% if object.avisDpd.date is not null %} - <tr> - <td colspan="2">{{ object.avisDpd.date|date('d/m/Y') }}</td> XXX - </tr> - {% endif %} - {% if object.avisDpd.detail is not null %} - <tr> - <td colspan="2">{{ object.avisDpd.detail }}</td> - </tr> - {% endif %} - <tr style="height: 80px"><td colspan="2">Signature :</td></tr> - </table> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Avis des représentants des personnes concernées</td> - <td>{{ object.avisRepresentant.reponse|dictionary('reponse_avis') }}</td> - </tr> - {% if object.avisRepresentant.date is not null %} - <tr> - <td colspan="2">{{ object.avisRepresentant.date|date('d/m/Y') }}</td> - </tr> - {% endif %} - {% if object.avisRepresentant.detail is not null %} - <tr> - <td colspan="2">{{ object.avisRepresentant.detail }}</td> - </tr> - {% endif %} - <tr style="height: 80px"><td colspan="2">Signature :</td></tr> - </table> - <table class="table table-bordered"> - <tr> - <td class="table-bluecell">Décision du responsable de traitement</td> - <td>{{ object.avisResponsable.reponse|dictionary('reponse_avis') }}</td> - </tr> - {% if object.avisResponsable.date is not null %} - <tr> - <td colspan="2">{{ object.avisResponsable.date|date('d/m/Y') }}</td> - </tr> - {% endif %} - {% if object.avisResponsable.detail is not null %} - <tr> - <td colspan="2">{{ object.avisResponsable.detail }}</td> - </tr> - {% endif %} - <tr style="height: 80px"><td colspan="2">Signature :</td></tr> - </table> - -{# //////////////////////////////////////#} -{# /////////////// Annexes //////////////#} -{# //////////////////////////////////////#} - <div style="page-break-before: always;"></div> - <h2>6. Annexes</h2> - <h3>6.1 Glossaire</h3> - <div class="annexe-head">Donnée à caractère personnel</div> - <div>Toute information se rapportant à une personne physique identifiée ou identifiable (ci-après dénommée "personne concernée"); est réputée pour être une "personne physique identifiable" une personne physique qui peut être identifiée, directement ou indirectement, notamment par référence à un identifiant, tel qu'un nom, un numéro d'identification, des données de localisation, un identifiant en ligne, ou à un ou plusieurs éléments spécifiques propres à son identité physique, physiologique, génétique, psychique, économique, culturelle ou sociale.</div> - <div class="annexe-head">Événement redouté</div> - <div>Violation potentielle de données pouvant mener à des impacts sur la vie privée des personnes concernées.</div> - <div class="annexe-head">Gravité</div> - <div>Estimation de l'ampleur des impacts potentiels sur la vie privée des personnes concernées.</div> - <div class="annexe-head">Menace</div> - <div>Mode opératoire composé d'une ou plusieurs actions unitaires sur des supports de données.</div> - <div class="annexe-head">Mesure</div> - <div>Action à entreprendre.</div> - <div class="annexe-head">Personnes concernées</div> - <div>Personnes auxquelles se rapportent les données qui font l'objet du traitement.</div> - <div class="annexe-head">Responsable de traitement</div> - <div>La personne physique ou morale, l'autorité publique, le service ou une autre structure qui, seul ou conjointement avec d'autres, détermine les finalités et les moyens du traitement ; lorsque les finalités et les moyens de ce traitement sont déterminés par le droit de l'Union ou le droit d'un État membre, le responsable du traitement peut être désigné ou les traitements spécifiques applicables à sa désignation peuvent être prévus par le droit de l'Union ou par le droit d'un État membre.</div> - <div class="annexe-head">Traitement de données à caractère personnel (traitement)</div> - <div>Tout opération ou tout ensemble d'opérations effectuées ou non à l'aide de procédés automatisés et appliqués à des données ou des ensembles de données à caractère personnel, tel que la collecte, l'enregistrement, la structure, la structuration, la conservation, l'adaptation ou la modification, l'extraction, la consultation, l'utilisation, la communication par transmission, la diffusion ou tout autre forme de mise à disposition, le rapprochement ou l'interconnexion, la limitation, l'effacement ou la destruction.</div> - <div class="annexe-head">Vraisemblance</div> - <div>Estimation de la possibilité qu'un risque se réalise.</div> - - <h3>6.2 Références</h3> - <div class="annexe-head">CNIL / CEPD</div> - <div class="annexe-link">https://www.cnil.fr/fr/ce-quil-faut-savoir-sur-lanalyse-dimpact-relative-la-protection-des-donnees-aipd</div> - <div class="annexe-link">https://www.cnil.fr/fr/nouveautes-sur-le-pia-guides-outil-piaf-etude-de-cas</div> - <div class="annexe-link">https://www.cnil.fr/fr/collectivites-territoriales</div> - <div class="annexe-link">https://www.edpb.europa.eu/our-work-tools/our-documents/publication-type/guidelines_fr</div> - - <div class="annexe-head">ANSSI</div> - <div class="annexe-prelink">- EBIOS RM : Méthode d'analyse des risques</div> - <div class="annexe-link">https://www.ssi.gouv.fr/guide/la-methode-ebios-risk-manager-le-guide</div> - <div class="annexe-prelink">- Lien RGS / RGPD</div> - <div class="annexe-link">https://www.ssi.gouv.fr/administration/reglementation/rgpd-renforcer-la-securite-des-donnees-a-caractere-personnel</div> - - <div class="annexe-head">CLUSIF</div> - <div class="annexe-prelink">- Méhari</div> - <div class="annexe-link">https://clusif.fr/services/management-des-risques/les-fondamentaux-de-mehari/</div> - - <div class="annexe-head">ISO</div> - <div class="annexe-prelink">- ISO/IEC 27701:2019 -Technique de sécurité - Extension d'ISO/IEC 27001 et ISO/IEC 27002 au management de la protection de la vie privée - Exigences et lignes directrices</div> - <div class="annexe-link">https://www.iso.org/fr/standard/71670.html</div> - - <div style="page-break-before: always;"></div> - <h3>6.3 Fiche de traitement</h3> - {% set traitement = object.conformiteTraitement.traitement %} - - {# DPO Statut #} - <div class="box box-solid box-default"> - <div class="box-header with-border"> - <h3 class="box-title">{{ 'registry.treatment.tab.statut_dpo'|trans }}</h3> - </div> - <div class="box-body no-padding"> - <table role="presentation" class="table"> <tbody> <tr> - <td><strong>{{ 'registry.treatment.label.statut'|trans }}</strong></td> - <td> - {% if traitement.statut is defined and traitement.statut %} - {{ traitement.statut|dictionary('treatment_statut') }} - {% endif %} - </td> + <td class="table-bluecell">Nature du traitement</td> + <td>{{ object.conformiteTraitement.traitement.name }}</td> </tr> - {% if traitement.dpoMessage is not null %} + {% set critere = object.criterePrincipeFondamentalByCode('contexte_traitement') %} + {% if critere and critere.reponse != 'non_renseigne' %} <tr> - <td><strong>{{ 'registry.treatment.label.dpoMessage'|trans }}</strong></td> - <td>{{ traitement.dpoMessage }}</td> + <td class="table-bluecell">{{ critere.labelLivrable }}</td> + <td> + <i>Conformité : </i> + {% if critere.reponse == 'conforme' %} + <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> + {% elseif critere.reponse == 'non_conforme' %} + <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> + {% elseif critere.reponse == 'non_applicable' %} + <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> + {% endif %} + <br/> + {% if critere.justification is not null %} + <i>Justification : </i>{{ critere.justification }}<br /> + {% endif %} + </td> </tr> + {% if critere.fichier %} + <tr> + <td colspan="2" style="text-align: center"> + <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> + </td> + </tr> + {% endif %} {% endif %} - </tbody> - </table> - </div> - </div> - - {# GENERAL #} - <div class="box box-solid box-info"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'global.tab.general'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - <tr> - <td><strong>{{ 'registry.treatment.label.name'|trans }}</strong></td> - <td>{{ traitement.name }}</td> - </tr> - {% if traitement.collectivity.isServicesEnabled %} + {% set critere = object.criterePrincipeFondamentalByCode('portee_traitement') %} + {% if critere and critere.reponse != 'non_renseigne' %} <tr> - <td><strong>{{ 'registry.label.service'|trans }}</strong></td> - <td>{{ traitement.service }}</td> + <td class="table-bluecell">{{ critere.labelLivrable }}</td> + <td> + <i>Conformité : </i> + {% if critere.reponse == 'conforme' %} + <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> + {% elseif critere.reponse == 'non_conforme' %} + <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> + {% elseif critere.reponse == 'non_applicable' %} + <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> + {% endif %} + <br/> + {% if critere.justification is not null %} + <i>Justification : </i>{{ critere.justification }}<br /> + {% endif %} + </td> </tr> + {% if critere.fichier %} + <tr> + <td colspan="2" style="text-align: center"> + <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> + </td> + </tr> + {% endif %} {% endif %} <tr> - <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> - <td>{{ traitement.goal|nl2br }}</td> + <td class="table-bluecell">Finalité(s) du traitement</td> + <td>{{ object.conformiteTraitement.traitement.goal }}</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.author'|trans }}</strong></td> + <td class="table-bluecell">Données à caractère personnel</td> <td> - {% if traitement.author is not null %} - {{ traitement.author|dictionary('registry_treatment_author') }} - {% endif %} + {% for category in object.conformiteTraitement.traitement.dataCategories %} + {{ category }}<br/> + {% endfor %} + {{ object.conformiteTraitement.traitement.dataCategoryOther }} </td> </tr> - {% if traitement.author != "processing_manager" %} - <tr> - <td><strong>{{ 'registry.treatment.label.coordonnees_responsable_traitement'|trans }}</strong></td> - <td>{{ traitement.coordonneesResponsableTraitement|nl2br }}</td> - </tr> - {% endif %} - <tr> - <td><strong>{{ 'registry.treatment.label.manager'|trans }}</strong></td> - <td>{{ traitement.manager }}</td> - </tr> <tr> - <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> + <td class="table-bluecell">Destinataires</td> <td> - {% if traitement.active %} - <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> - {% else %} - <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> - {% endif %} + {{ object.conformiteTraitement.traitement.recipientCategory }} + {% for contractor in object.conformiteTraitement.traitement.contractors %} + <br/>{{ contractor }} + {% endfor %} </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.legal_basis'|trans }}</strong></td> - <td>{{ traitement.legalBasis|dictionary('registry_treatment_legal_basis') }}</td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.legal_basis_justification'|trans }}</strong></td> - <td>{{ traitement.legalBasisJustification|nl2br }}</td> + <td class="table-bluecell">Durée de conservation</td> + <td> + {% for duration in object.conformiteTraitement.traitement.shelfLifes %} + {{ duration.name }} - {{ duration.duration }} - {{ duration.ultimateFate|dictionary('registry_treatment_ultimate_fate') }} <br/> + {% endfor %} + </td> </tr> - {% if traitement.legalBasis == 'consent' %} + {% set critere = object.criterePrincipeFondamentalByCode('identification_biens') %} + {% if critere and critere.reponse != 'non_renseigne' %} <tr> - <td><strong>{{ 'registry.treatment.label.consent_request'|trans }}</strong></td> + <td class="table-bluecell">{{ critere.labelLivrable }}</td> <td> - {% if traitement.consentRequest %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + <i>Conformité : </i> + {% if critere.reponse == 'conforme' %} + <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> + {% elseif critere.reponse == 'non_conforme' %} + <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> + {% elseif critere.reponse == 'non_applicable' %} + <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> + {% endif %} + <br/> + {% if critere.justification is not null %} + <i>Justification : </i>{{ critere.justification }}<br /> + {% endif %} + </td> + </tr> + {% if critere.fichier %} + <tr> + <td colspan="2" style="text-align: center"> + <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> + </td> + </tr> + {% endif %} + {% endif %} + {% set critere = object.criterePrincipeFondamentalByCode('description_fonctionnelle') %} + {% if critere and critere.reponse != 'non_renseigne' %} + <tr> + <td class="table-bluecell">{{ critere.labelLivrable }}</td> + <td> + <i>Conformité : </i> + {% if critere.reponse == 'conforme' %} + <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> + {% elseif critere.reponse == 'non_conforme' %} + <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> + {% elseif critere.reponse == 'non_applicable' %} + <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> + {% endif %} + <br/> + {% if critere.justification is not null %} + <i>Justification : </i>{{ critere.justification }}<br /> {% endif %} </td> </tr> + {% if critere.fichier %} + <tr> + <td colspan="2" style="text-align: center"> + <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> + </td> + </tr> + {% endif %} + {% endif %} + {% set critere = object.criterePrincipeFondamentalByCode('conformite_code') %} + {% if critere and critere.reponse != 'non_renseigne' %} <tr> - <td><strong>{{ 'registry.treatment.label.consent_request_format'|trans }}</strong></td> - <td>{{ traitement.consentRequestFormat }}</td> + <td class="table-bluecell">{{ critere.labelLivrable }}</td> + <td> + <i>Conformité : </i> + {% if critere.reponse == 'conforme' %} + <span class="label label-success" style="min-width: 50px; display: inline-block;">{{ critere.texteConformite }}</span> + {% elseif critere.reponse == 'non_conforme' %} + <span class="label label-danger" style="min-width: 50px; display: inline-block;">{{ critere.texteNonConformite }}</span> + {% elseif critere.reponse == 'non_applicable' %} + <span class="label label-default" style="min-width: 50px; display: inline-block;">{{ critere.texteNonApplicable }}</span> + {% endif %} + <br/> + {% if critere.justification is not null %} + <i>Justification : </i>{{ critere.justification }}<br /> + {% endif %} + </td> </tr> + {% if critere.fichier %} + <tr> + <td colspan="2" style="text-align: center"> + <img src="{{ base_dir ~ asset('/uploads/aipd/critere_principe_fondamentaux/fichier/' ~ critere.fichier)}}" style="max-width:800px" alt="Contexte du traitement {{ critere.label }} - {{ critere.reponse|dictionary('reponse_critere_fondamental') }}"> + </td> + </tr> + {% endif %} {% endif %} + </tbody> + </table> + + <div style="page-break-before: always;"></div> + + <h2>3. Études des principes fondamentaux</h2> + <p>Ce chapitre a pour objectif de s’assurer que le dispositif relatif aux principes de protection de la vie privée est conforme.</p> + <table class="table table-bordered"> + <thead> <tr> - <td><strong>{{ 'registry.treatment.label.observation'|trans }}</strong></td> - <td>{{ traitement.observation|nl2br }}</td> + <th>Description</th> + <th>Conformité</th> </tr> + </thead> + <tbody> + {% for critere in object.criterePrincipeFondamentaux %} + <tr> + <td>{{ critere.labelLivrable }}</td> + <td>{{ getCritereLabel(critere)|raw }}</td> + </tr> + {% endfor %} + </tbody> + </table> + <table class="table table-bordered"> + <thead> <tr> - <td><strong>{{ 'registry.treatment.label.public_registry'|trans }}</strong></td> - <td> - {% if traitement.public == true %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + <th>Principes fondamentaux</th> + <th>Conformité</th> + </tr> + </thead> + <tbody> + {% for questionConformite in object.questionConformites|sort((a, b) => a.position >= b.position) %} + <tr> + {% set reponse = object.conformiteTraitement.getReponseOfName(questionConformite.question) %} + <td>{{ questionConformite.question }} + {% if questionConformite.justificatif is not null %} + <div style="margin-left: 20px;font-size:12px;"> + <span><i>Justification : </i> {{ questionConformite.justificatif }}</span> + </div> + {% endif %} + + {% if reponse and (reponse.actionProtections is not null) and (reponse.actionProtections|length > 0) %} + <div style="margin-left: 20px;font-size:12px;"> + <span><i>Actions associées : </i> </span> + </div> + <ul> + {% for action in reponse.actionProtections %} + <li style="margin-left: 20px;font-size:12px;">{{action.name}}</li> + {% endfor %} + </ul> + {% endif %} + </td> + {% if reponse and reponse.conforme %} + <td><span class="label label-success" style="min-width: 100%; display: inline-block;"> Conforme</span></td> {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% if reponse and reponse.actionProtections|length > 0 %} + <td><span class="label label-warning" style="min-width: 100%; display: inline-block;"> Non-conforme mineure</span></td> + {% else%} + <td><span class="label label-danger" style="min-width: 100%; display: inline-block;"> Non-conforme majeure</span></td> + {% endif %} {% endif %} - </td> - </tr> + </tr> + {% endfor %} </tbody> </table> - </div> - </div> + <p>Le graphique ci-dessous indique les points d’amélioration nécessaires au respect des principes fondamentaux du règlement.</p> + + <div class="reportGraph"><canvas id="grandsDomaines-chart"></canvas></div> - {# DATA CATEGORY #} - <div class="box box-solid box-warning"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.data_category'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> + <div style="page-break-before: always;"></div> + + <h2>4. Études des risques liés à la sécurité des données</h2> + <p>Ce chapitre a pour objectifs d'obtenir une bonne connaissance des mesures contribuant à la sécurité et d'apprécier les risques.</p> + + <h3>4.1 Évaluation des risques sur les droits et les libertés des personnes concernées</h3> + <p>Le niveau d'un risque est estimé en termes de gravité et de vraisemblance :</p> + <ul> + <li>La <strong>gravité</strong> représente l'ampleur d'un risque. Elle dépend essentiellement du caractère préjudiciable des imapcts potentiels ;</li> + <li>La <strong>vraisemblance</strong> traduit la possibilité qu'un risque se réalise. Elle dépend essentiellement des vulnérabilités des supports face aux menaces et des capacités des sources de risques à les exploiter.</li> + </ul> + + <div style="text-align: center"><img src="{{ base_dir ~ asset("images/NiveauRisque.png") }}" width="600" alt="Gravité + Vraisemblance = Niveau de risque"></div> + + <div class="separator"></div> + + <table class="table table-bordered"> + <thead> + <tr class="table-indicateur-head"> + <th>Niveaux</th> + <th>Descriptions génériques de l'échelle de gravité</th> + </tr> + </thead> <tbody> <tr> - <td><strong>{{ 'registry.treatment.label.data_category'|trans }}</strong></td> - <td> - <ul class="ps-1"> - {% for category in traitement.dataCategories %} - <li> - {% if category.sensible %}<strong>{% endif %} - {{ category.name }} - {% if category.sensible %}</strong>{% endif %} - </li> - {% endfor %} - </ul> - </td> + <td class="table-indicateur-maximale">Maximale</td> + <td>Les personnes concernées pourraient connaître des conséquences significatives, voire irrémédiables, qu'elles pourraient ne pas surmonter</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.data_category_other'|trans }}</strong></td> - <td>{{ traitement.dataCategoryOther|nl2br }}</td> + <td class="table-indicateur-importante">Importante</td> + <td>Les personnes concernées pourraient connaître des conséquences significatives, qu'elles devraient pouvoir surmonter, mais avec des difficultés réelles et significatives</td> </tr> - </tbody> - </table> - </div> - </div> - - {# RECIPIENTS #} - <div class="box box-solid box-primary"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.recipients'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> <tr> - <td><strong>{{ 'registry.treatment.label.recipient_category'|trans }}</strong></td> - <td>{{ traitement.recipientCategory|nl2br }}</td> + <td class="table-indicateur-limitee">Limitée</td> + <td>Les personnes concernées pourraient connaître des désagréments significatifs, qu'elles pourront surmonter malgré quelques difficultés</td> </tr> <tr> - <td><strong>{{ 'global.label.linked_contractor'|trans }}</strong></td> - <td> - <ul class="ps-1"> - {% for contractor in traitement.contractors %} - <li>{{ contractor }}</li> - {% endfor %} - </ul> - </td> + <td class="table-indicateur-negligeable">Négligeable</td> + <td>Les personnes concernées ne seront pas impactés ou pourraient connaître quelques désagréments, qu'elles surmonteront sans difficulté</td> </tr> </tbody> </table> - </div> - </div> - {# SPECIFIC #} - <div class="box box-solid box-info"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.specific'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - <tr> - <td><strong>{{ 'registry.treatment.label.exempt_AIPD'|trans }}</strong></td> - <td> - {% if traitement.ExemptAIPD %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <table class="table table-bordered"> + <thead> + <tr class="table-indicateur-head"> + <th>Niveaux</th> + <th>Descriptions génériques de l'échelle de vraisemblance</th> </tr> + </thead> + <tbody> <tr> - <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> - <td> - {% if traitement.systematicMonitoring %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-indicateur-maximale">Maximale</td> + <td>Il semble extrêmement facile pour les sources des risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papier stockés dans le hall public de la structure).</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> - <td> - {% if traitement.largeScaleCollection %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-indicateur-importante">Importante</td> + <td>Il semble possible pour les sources de risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans les bureaux d'une structure dont l'accès est contrôlé par une personne à l'accueil).</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> - <td> - {% if traitement.vulnerablePeople %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-indicateur-limitee">Limitée</td> + <td>Il semble difficile pour les sources de risques retenues de réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans un local de la structure dont l'accès est contrôlé par badge).</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> - <td> - {% if traitement.dataCrossing %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> - <td> - {% if traitement.evaluationOrRating %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> - <td> - {% if traitement.automatedDecisionsWithLegalEffect %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> - <td> - {% if traitement.automaticExclusionService %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.innovative_use'|trans }}</strong></td> - <td> - {% if traitement.innovativeUse %} - <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-indicateur-negligeable">Négligeable</td> + <td>Il ne semble pas possible que les sources de risques retenues puissent réaliser la menace en s'appuyant sur les caractéristiques des supports (ex: vol de supports papiers stockés dans un local de la structure dont l'accès est contrôlé par badge et code d'accès).</td> </tr> </tbody> </table> - </div> - </div> - {# DETAILS #} - <div class="box box-solid box-primary"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.details'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> + <div style="text-align: center"><img src="{{ base_dir ~ asset("images/matriceAIPD.png") }}" height="300" alt=""></div> + + <div style="page-break-before: always;"></div> + + <h3>4.2 Évaluation de l'impact et matrice de décision</h3> + <p>Le tableau ci-dessous identifie des scénarios de menaces pour lesquels une évaluation est réalisée sur la vraisemblance (risques d’occurrence) et la gravité (conséquences en cas d’évènement). D, I et C représentent les critères de classification de l'information : <b>D</b>isponibilité, <b>I</b>ntégrité, <b>C</b>onfidentialité.</p> + <table class="table table-bordered"> + <thead> + <tr> + <th>D</th> + <th>I</th> + <th>C</th> + <th>Scénario de menace</th> + <th>Vraisemblance</th> + <th>Gravité</th> + <th>Impact potentiel</th> + </tr> + </thead> <tbody> - <tr> - <td><strong>{{ 'registry.treatment.label.concerned_people'|trans }}</strong></td> - </tr> - <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_particular'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleParticular.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleParticular.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleParticular.comment }}</p> + {% for scenario in object.scenarioMenaces|sort((a,b) => a.nom <=> b.nom) %} + <tr> + <td>{% if scenario.isDisponibilite %}X{% endif %}</td> + <td>{% if scenario.isIntegrite %}X{% endif %}</td> + <td>{% if scenario.isConfidentialite %}X{% endif %}</td> + <td>{{ scenario.nom }} + {% if scenario.precisions is not null %} + <div style="margin-left: 20px;font-size:12px;"> + <span><i>Précision : </i> {{ scenario.precisions }}</span> + </div> {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_user'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleUser.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleUser.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleUser.comment }}</p> + </td> + <td>{{ scenario.vraisemblance|dictionary('vraisemblance_gravite') }}</td> + <td>{{ scenario.gravite|dictionary('vraisemblance_gravite') }}</td> + <td>{{ getScenarioMenaceImpactPotentielLabel(scenario)|raw }}</td> + </tr> + {% endfor %} + </tbody> + </table> + <p>La CNIL préconise d’accepter les risques uniquement lorsque l’impact est négligeable. Dans les autres cas, il faudra apporter des mesures de protection supplémentaires pour venir corriger les anomalies identifiées. Dans le cas où le risque est maximal et que les mesures ne sont pas jugées suffisantes, il conviendra de solliciter l’avis de la CNIL.</p> + <p>La matrice de décision ci-dessous vous informe du comportement attendu par la CNIL selon le niveau d'impact identifié :</p> + + <div style="text-align: center"><img src="{{ base_dir ~ asset("images/MatriceDecision.png") }}" height="300" alt=""></div> + + <div style="page-break-before: always;"></div> + + <h3>4.3 Mesure(s) de réduction des risques mise(s) en place</h3> + <p>Le radar ci-dessous présente les mesures déjà mises en place dans la structure pour réduire l’ensemble des risques identifiés.</p> + + <div class="reportGraph"><canvas id="mesuresSecurite-chart"></canvas></div> + + <div class="separator"></div> + + <div class="box box-solid box-primary"> + <div class="box-header with-border">Mesures de protection</div> + <table class="table table-bordered"> + <thead> + <tr> + <th>Mesure</th> + <th>Avis sur les mesures existantes</th> + <th>Évaluation</th> + <th>Préconisations</th> + </tr> + </thead> + <tbody> + {% set mesures = [] %} + {% for scenario in object.scenarioMenaces %} + {% for mesure in scenario.mesuresProtections %} + {% if mesure not in mesures %} + {% set mesures = mesures|merge([mesure])%} + {% endif%} + {% endfor %} + {% endfor %} + {% for element in mesures|sort((a, b) => a.labelLivrable >= b.labelLivrable) %} + <tr> + <td>{{ element.labelLivrable }}</td> + <td>{{ element.detail }}</td> + <td>{% if element.reponse in reponsedictionary(object)|keys %} + {{ element.reponse|reponsedictionary(object) }} + {% else %} + {{ element.reponse }} + {% endif %} + </td> + {% if element.reponse is same as "satisfaisant" %} + <td></td> + {% else %} + <td>{{ element.phrasePreconisation }}</td> {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + </tr> + {% endfor %} + </tbody> + </table> + </div> + + <div style="page-break-before: always;"></div> + + <h3>4.4 Risques résiduels</h3> + <p>Les risques résiduels correspondent aux risques non traités à ce jour ou pour lesquels des préconisations ont été formulées (voir actions conseillées par le DPD).</p> + + <div class="reportGraph"><canvas id="risquesResiduels-chart"></canvas></div> + + <div class="separator"></div> + + <div class="box box-solid box-primary"> + <div class="box-header with-border">{{ 'aipd.analyse_impact.tab.gestion_risques'|trans }}</div> + <div class="box-body no-padding"> + <table class="table table-bordered"> + <tr> + <th>{{ 'aipd.modele_analyse.label.scenario'|trans }}</th> + <th style="width: 20%;">{{ 'aipd.analyse_impact.label.impact_potentiel'|trans }}</th> + <th style="width: 20%;">{{ 'aipd.analyse_impact.label.impact_residuel'|trans }}</th> + </tr> + {% set mesureProtectionNotNegligeable = [] %} + {% for scenario in object.scenarioMenaces|sort((a, b) => a.nom >= b.nom) %} + {% if isScenarioMenaceImpactResiduelImpactNotNegligeable(scenario) %} + {% for mesure in scenario.mesuresProtections %} + {% if mesure not in mesureProtectionNotNegligeable %} + {% set mesureProtectionNotNegligeable = mesureProtectionNotNegligeable|merge([mesure]) %} + {% endif %} + {% endfor %} + <tr> + <td>{{ scenario.nom }}</td> + <td>{{ getScenarioMenaceImpactPotentielLabel(scenario)|raw }}</td> + <td>{{ getScenarioMenaceImpactResiduelLabel(scenario)|raw }}</td> + </tr> {% endif %} - </td> - </tr> + {% endfor %} + </table> + </div> + </div> + + <div style="page-break-before: always;"></div> + + <p>Le graphique ci-dessous représente les risques résiduels sur la disponibilité, l'intégrité et la confidentialité des données à caractère personnel.</p> + + <div class="reportGraph"><canvas id="dicResiduels-chart"></canvas></div> + + <div class="separator"></div> + + <p>Le plan d’actions ci-après présente les mesures de sécurité liées aux seuls scénarios de menaces dont l’impact est refusé.</p> + <div class="box box-solid box-primary"> + <div class="box-header with-border">Plan d'actions</div> + <div class="box-body no-padding"> + <table class="table table-bordered"> + <tr> + <th>Mesure</th> + <th>Préconisations</th> + </tr> + {% for mesure in mesureProtectionNotNegligeable|sort((a, b) => a.labelLivrable >= b.labelLivrable) %} + <tr> + <td>{{ mesure.labelLivrable }}</td> + <td>{{ mesure.phrasePreconisation }}</td> + </tr> + {% endfor %} + </table> + </div> + </div> + + <div style="page-break-before: always;"></div> + + <h2>5. Validation de l'AIPD</h2> + <p>Ce chapitre a pour objectifs de permettre la prise de décision visant à accepter ou non l'AIPD au regard des résultats de l'étude.</p> + + <h3>Avis des personnes consultées</h3> + <table class="table table-bordered"> + <tbody> <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_agent'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleAgent.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleAgent.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleAgent.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-bluecell">Avis du référent RGPD</td> + <td>{{ object.avisReferent.reponse|dictionary('reponse_avis') }}</td> </tr> + {% if object.avisReferent.date is not null %} + <tr> + <td colspan="2">{{ object.avisReferent.date|date('d/m/Y') }}</td> + </tr> + {% endif %} + {% if object.avisReferent.detail is not null %} + <tr> + <td colspan="2">{{ object.avisReferent.detail }}</td> + </tr> + {% endif %} + <tr style="height: 80px"><td colspan="2">Signature :</td></tr> <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_elected'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleElected.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleElected.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleElected.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-bluecell">Avis du délégué à la protection des données</td> + <td>{{ object.avisDpd.reponse|dictionary('reponse_avis') }}</td> </tr> + {% if object.avisDpd.date is not null %} + <tr> + <td colspan="2">{{ object.avisDpd.date|date('d/m/Y') }}</td> + </tr> + {% endif %} + {% if object.avisDpd.detail is not null %} + <tr> + <td colspan="2">{{ object.avisDpd.detail }}</td> + </tr> + {% endif %} + <tr style="height: 80px"><td colspan="2">Signature :</td></tr> <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_company'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleCompany.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleCompany.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleCompany.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-bluecell">Avis des représentants des personnes concernées</td> + <td>{{ object.avisRepresentant.reponse|dictionary('reponse_avis') }}</td> </tr> + {% if object.avisRepresentant.date is not null %} + <tr> + <td colspan="2">{{ object.avisRepresentant.date|date('d/m/Y') }}</td> + </tr> + {% endif %} + {% if object.avisRepresentant.detail is not null %} + <tr> + <td colspan="2">{{ object.avisRepresentant.detail }}</td> + </tr> + {% endif %} + <tr style="height: 80px"><td colspan="2">Signature :</td></tr> <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_partner'|trans }}</strong></td> - <td> - {% if traitement.concernedPeoplePartner.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeoplePartner.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeoplePartner.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> + <td class="table-bluecell">Décision du responsable de traitement</td> + <td>{{ object.avisResponsable.reponse|dictionary('reponse_avis') }}</td> </tr> - <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_usager'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleUsager.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleUsager.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleUsager.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% if object.avisResponsable.date is not null %} + <tr> + <td colspan="2">{{ object.avisResponsable.date|date('d/m/Y') }}</td> + </tr> + {% endif %} + {% if object.avisResponsable.detail is not null %} + <tr> + <td colspan="2">{{ object.avisResponsable.detail }}</td> + </tr> + {% endif %} + <tr style="height: 80px"><td colspan="2">Signature :</td></tr> + </tbody> + </table> + + <div style="page-break-before: always;"></div> + + {#//////////////////////////////////////#} + {#/////////////// Annexes //////////////#} + {#//////////////////////////////////////#} + <h2>6. Annexes</h2> + <h3>6.1 Glossaire</h3> + + <dl> + <dt>Donnée à caractère personnel</dt> + <dd>Toute information se rapportant à une personne physique identifiée ou identifiable (ci-après dénommée "personne concernée"); est réputée pour être une "personne physique identifiable" une personne physique qui peut être identifiée, directement ou indirectement, notamment par référence à un identifiant, tel qu'un nom, un numéro d'identification, des données de localisation, un identifiant en ligne, ou à un ou plusieurs éléments spécifiques propres à son identité physique, physiologique, génétique, psychique, économique, culturelle ou sociale.</dd> + <dt>Événement redouté</dt> + <dd>Violation potentielle de données pouvant mener à des impacts sur la vie privée des personnes concernées.</dd> + <dt>Gravité</dt> + <dd>Estimation de l'ampleur des impacts potentiels sur la vie privée des personnes concernées.</dd> + <dt>Menace</dt> + <dd>Mode opératoire composé d'une ou plusieurs actions unitaires sur des supports de données.</dd> + <dt>Mesure</dt> + <dd>Action à entreprendre.</dd> + <dt>Personnes concernées</dt> + <dd>Personnes auxquelles se rapportent les données qui font l'objet du traitement.</dd> + <dt>Responsable de traitement</dt> + <dd>La personne physique ou morale, l'autorité publique, le service ou une autre structure qui, seul ou conjointement avec d'autres, détermine les finalités et les moyens du traitement ; lorsque les finalités et les moyens de ce traitement sont déterminés par le droit de l'Union ou le droit d'un État membre, le responsable du traitement peut être désigné ou les traitements spécifiques applicables à sa désignation peuvent être prévus par le droit de l'Union ou par le droit d'un État membre.</dd> + <dt>Traitement de données à caractère personnel</dt> + <dd>Tout opération ou tout ensemble d'opérations effectuées ou non à l'aide de procédés automatisés et appliqués à des données ou des ensembles de données à caractère personnel, tel que la collecte, l'enregistrement, la structure, la structuration, la conservation, l'adaptation ou la modification, l'extraction, la consultation, l'utilisation, la communication par transmission, la diffusion ou tout autre forme de mise à disposition, le rapprochement ou l'interconnexion, la limitation, l'effacement ou la destruction.</dd> + <dt>Vraisemblance</dt> + <dd>Estimation de la possibilité qu'un risque se réalise.</dd> + </dl> + + <h3>6.2 Références</h3> + <p>CNIL / CEPD</p> + <ul> + <li><a href="https://www.cnil.fr/fr/ce-quil-faut-savoir-sur-lanalyse-dimpact-relative-la-protection-des-donnees-aipd">Ce qu'il faut savoir sur l’analyse d’impact relative à la protection des données (AIPD)</a></li> + <li><a href="https://www.cnil.fr/fr/nouveautes-sur-le-pia-guides-outil-piaf-etude-de-cas">Outil PIA : téléchargez et installez le logiciel de la CNIL</a></li> + <li><a href="https://www.cnil.fr/fr/collectivites-territoriales">Thématique CNIL : Collectivités territoriales </a></li> + <li><a href="https://www.edpb.europa.eu/our-work-tools/our-documents/publication-type/guidelines_fr">Guides CEPD</a></li> + </ul> + + <p>ANSSI</p> + <ul> + <li><a href="https://www.ssi.gouv.fr/guide/la-methode-ebios-risk-manager-le-guide">EBIOS RM : Méthode d'analyse des risques</a></li> + <li><a href="https://www.ssi.gouv.fr/administration/reglementation/rgpd-renforcer-la-securite-des-donnees-a-caractere-personnel">RGPD : la sécurité est essentielle pour la protection des données à caractère personnel</a></li> + </ul> + + <p>CLUSIF</p> + <ul> + <li><a href="https://clusif.fr/services/management-des-risques/les-fondamentaux-de-mehari/">Les fondamentaux de Méhari</a></li> + </ul> + + <p>ISO</p> + <ul> + <li><a href="https://www.iso.org/fr/standard/71670.html">ISO/IEC 27701:2019 : Techniques de sécurité — Extension d'ISO/IEC 27001 et ISO/IEC 27002 au management de la protection de la vie privée — Exigences et lignes directrices</a></li> + </ul> + + <div style="page-break-before: always;"></div> + + <h3>6.3 Fiche de traitement</h3> + {% set traitement = object.conformiteTraitement.traitement %} + + {# DPO Statut #} + <div class="box box-solid box-default"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.statut_dpo'|trans }}</h4></div> + <div class="box-body no-padding"> + <table role="presentation" class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.statut'|trans }}</strong></td> + <td> + {% if traitement.statut is defined and traitement.statut %} + {{ traitement.statut|dictionary('treatment_statut') }} + {% endif %} + </td> + </tr> + {% if traitement.dpoMessage is not null %} + <tr> + <td><strong>{{ 'registry.treatment.label.dpoMessage'|trans }}</strong></td> + <td>{{ traitement.dpoMessage }}</td> + </tr> {% endif %} - </td> - </tr> - <tr> - <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_other'|trans }}</strong></td> - <td> - {% if traitement.concernedPeopleOther.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.concernedPeopleOther.comment is not empty %} - <p class="mt-2">{{ traitement.concernedPeopleOther.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + </tbody> + </table> + </div> + </div> + + {# GENERAL #} + <div class="box box-solid box-info"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'global.tab.general'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.name'|trans }}</strong></td> + <td>{{ traitement.name }}</td> + </tr> + {% if traitement.collectivity.isServicesEnabled %} + <tr> + <td><strong>{{ 'registry.label.service'|trans }}</strong></td> + <td>{{ traitement.service }}</td> + </tr> {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.estimated_concerned_people'|trans }}</strong></td> - <td>{{ traitement.estimatedConcernedPeople }}</td> - </tr> - <tr> - <td> - <strong> - {% if traitement.collectivity.hasModuleTools %} - {{ 'global.label.linked_tool'|trans }} - {% else %} - {{ 'registry.treatment.label.tools_if_inactif'|trans }} - {% endif %} - </strong> - </td> - <td> - {% if traitement.collectivity.hasModuleTools %} - <ul class="ps-1"> - {% for tool in traitement.tools %} - <li>{{ tool.name }}</li> + <tr> + <td><strong>{{ 'registry.treatment.label.author'|trans }}</strong></td> + <td> + {% if traitement.author is not null %} + {{ traitement.author|dictionary('registry_treatment_author') }} + {% endif %} + </td> + </tr> + {% if traitement.author != "processing_manager" %} + <tr> + <td><strong>{{ 'registry.treatment.label.coordonnees_responsable_traitement'|trans }}</strong></td> + <td>{{ traitement.coordonneesResponsableTraitement|nl2br }}</td> + </tr> + {% endif %} + <tr> + <td><strong>{{ 'registry.treatment.label.manager'|trans }}</strong></td> + <td>{{ traitement.manager }}</td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> + <td>{{ traitement.goal|nl2br }}</td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.legal_basis'|trans }}</strong></td> + <td>{{ traitement.legalBasis|dictionary('registry_treatment_legal_basis') }}</td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.legal_basis_justification'|trans }}</strong></td> + <td>{{ traitement.legalBasisJustification|nl2br }}</td> + </tr> + {% if traitement.legalBasis == 'consent' %} + <tr> + <td><strong>{{ 'registry.treatment.label.consent_request'|trans }}</strong></td> + <td> + {% if traitement.consentRequest %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.consent_request_format'|trans }}</strong></td> + <td>{{ traitement.consentRequestFormat }}</td> + </tr> + {% endif %} + <tr> + <td><strong>{{ 'registry.treatment.label.observation'|trans }}</strong></td> + <td>{{ traitement.observation|nl2br }}</td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> + <td> + {% if traitement.active %} + <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> + {% else %} + <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.public_registry'|trans }}</strong></td> + <td> + {% if traitement.public == true %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + </tbody> + </table> + </div> + </div> + + {# DATA CATEGORY #} + <div class="box box-solid box-warning"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.data_category'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.data_category'|trans }}</strong></td> + <td> + <ul class="ps-1"> + {% for category in traitement.dataCategories %} + <li> + {% if category.sensible %}<strong>{% endif %} + {{ category.name }} + {% if category.sensible %}</strong>{% endif %} + </li> + {% endfor %} + </ul> + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.data_category_other'|trans }}</strong></td> + <td>{{ traitement.dataCategoryOther|nl2br }}</td> + </tr> + </tbody> + </table> + </div> + </div> + + {# RECIPIENTS #} + <div class="box box-solid box-primary"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.recipients'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.recipient_category'|trans }}</strong></td> + <td>{{ traitement.recipientCategory|nl2br }}</td> + </tr> + <tr> + <td><strong>{{ 'global.label.linked_contractor'|trans }}</strong></td> + <td> + <ul class="ps-1"> + {% for contractor in traitement.contractors %} + <li>{{ contractor }}</li> + {% endfor %} + </ul> + </td> + </tr> + </tbody> + </table> + </div> + </div> + + {# SPECIFIC #} + <div class="box box-solid box-info"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.specific'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.exempt_AIPD'|trans }}</strong></td> + <td> + {% if traitement.ExemptAIPD %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> + <td> + {% if traitement.largeScaleCollection %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> + <td> + {% if traitement.dataCrossing %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> + <td> + {% if traitement.automatedDecisionsWithLegalEffect %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> + <td> + {% if traitement.evaluationOrRating %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> + <td> + {% if traitement.automaticExclusionService %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> + <td> + {% if traitement.vulnerablePeople %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> + <td> + {% if traitement.systematicMonitoring %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.innovative_use'|trans }}</strong></td> + <td> + {% if traitement.innovativeUse %} + <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + </tbody> + </table> + </div> + </div> + + {# DETAILS #} + <div class="box box-solid box-primary"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.details'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.concerned_people'|trans }}</strong></td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_particular'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleParticular.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleParticular.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleParticular.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_user'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleUser.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleUser.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleUser.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_agent'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleAgent.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleAgent.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleAgent.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_elected'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleElected.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleElected.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleElected.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_company'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleCompany.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleCompany.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleCompany.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_partner'|trans }}</strong></td> + <td> + {% if traitement.concernedPeoplePartner.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeoplePartner.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeoplePartner.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_usager'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleUsager.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleUsager.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleUsager.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td class="concerned-people-type"><strong>{{ 'registry.treatment.label.concerned_people_other'|trans }}</strong></td> + <td> + {% if traitement.concernedPeopleOther.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.concernedPeopleOther.comment is not empty %} + <p class="mt-2">{{ traitement.concernedPeopleOther.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.estimated_concerned_people'|trans }}</strong></td> + <td>{{ traitement.estimatedConcernedPeople }}</td> + </tr> + <tr> + <td> + <strong> + {% if traitement.collectivity.hasModuleTools %} + {{ 'global.label.linked_tool'|trans }} + {% else %} + {{ 'registry.treatment.label.tools_if_inactif'|trans }} + {% endif %} + </strong> + </td> + <td> + {% if traitement.collectivity.hasModuleTools %} + <ul class="ps-1"> + {% for tool in traitement.tools %} + <li>{{ tool.name }}</li> + {% endfor %} + </ul> + {% else %} + {{ traitement.software }} + {% endif %} + </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.paper_processing'|trans }}</strong></td> + <td> + {% if traitement.paperProcessing %} + <span class="badge bg-gray">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-gray">{{ 'global.label.no'|trans }}</span> + {% endif %} + </td> + </tr> + </tbody> + </table> + <table class="table" style="border-top: #f4f4f4 1px solid"> + <tbody> + <tr> + <td style="vertical-align: top; padding-left: 8px; padding-top: 10px; width: 20%"><strong>{{ 'registry.treatment.label.shelflife'|trans }}</strong></td> + <td style="padding-top: 10px; width: 80%"> + {% for method in traitement.shelfLifes %} + <div class="box box-default"> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + <tr> + <th class="text-bold" style="width: 40%">{{ 'registry.treatment.label.shelflife_name'|trans }}</th> + <td>{{ method.name }}</td> + </tr> + <tr> + <th class="text-bold">{{ 'registry.treatment.label.shelflife_duration'|trans }}</th> + <td>{{ method.duration }}</td> + </tr> + <tr> + <th class="text-bold">{{ 'registry.treatment.label.shelflife_ultimate_fate'|trans }}</th> + <td>{{ method.ultimateFate|dictionary('registry_treatment_ultimate_fate') }}</td> + </tr> + </tbody> + </table> + </div> + </div> {% endfor %} - </ul> - {% else %} - {{ traitement.software }} - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.paper_processing'|trans }}</strong></td> - <td> - {% if traitement.paperProcessing %} - <span class="badge bg-gray">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-gray">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - </tbody> - </table> - <table class="table" style="border-top: #f4f4f4 1px solid"> - <tbody> - <tr> - <td style="vertical-align: top; padding-left: 8px; padding-top: 10px; width: 20%"><strong>{{ 'registry.treatment.label.shelflife'|trans }}</strong></td> - <td style="padding-top: 10px; width: 80%"> - {% for method in traitement.shelfLifes %} - <div class="box box-default"> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - <tr> - <th class="text-bold" style="width: 40%">{{ 'registry.treatment.label.shelflife_name'|trans }}</th> - <td>{{ method.name }}</td> - </tr> - <tr> - <th class="text-bold">{{ 'registry.treatment.label.shelflife_duration'|trans }}</th> - <td>{{ method.duration }}</td> - </tr> - <tr> - <th class="text-bold">{{ 'registry.treatment.label.shelflife_ultimate_fate'|trans }}</th> - <td>{{ method.ultimateFate|dictionary('registry_treatment_ultimate_fate') }}</td> - </tr> - </tbody> - </table> - </div> - </div> - {% endfor %} - </td> - </tr> - </tbody> - </table> - <table class="table"> - <tbody> - <tr> - <td><strong>{{ 'registry.treatment.label.data_origin'|trans }}</strong></td> - <td>{{ traitement.dataOrigin }}</td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.collecting_method'|trans }}</strong></td> - <td> - <ul class="ps-1"> - {% for method in traitement.collectingMethod %} - <li>{{ method|dictionary('registry_treatment_collecting_method') }}</li> - {% endfor %} - </ul> - </td> - </tr> - {% if traitement.otherCollectingMethod is not null %} - <tr> - <td><strong>{{ 'registry.treatment.label.otherCollectingMethod'|trans }}</strong></td> - <td>{{ traitement.otherCollectingMethod }}</td> - </tr> - {% endif %} - </tbody> - </table> - </div> - </div> - - {# SECURITY #} - <div class="box box-solid box-success"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.security'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - <tr> - <td><strong>{{ 'registry.treatment.label.security_access_control'|trans }}</strong></td> - <td> - {% if traitement.securityAccessControl.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.securityAccessControl.comment is not empty %} - <p class="mt-2">{{ traitement.securityAccessControl.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_update'|trans }}</strong></td> - <td> - {% if traitement.securityUpdate.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.securityUpdate.comment is not empty %} - <p class="mt-2">{{ traitement.securityUpdate.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_saving'|trans }}</strong></td> - <td> - {% if traitement.securitySaving.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.securitySaving.comment is not empty %} - <p class="mt-2">{{ traitement.securitySaving.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_tracability'|trans }}</strong></td> - <td> - {% if traitement.securitytracability.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.securitytracability.comment is not empty %} - <p class="mt-2">{{ traitement.securitytracability.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_other'|trans }}</strong></td> - <td> - {% if traitement.securityOther.check %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% if traitement.securityOther.comment is not empty %} - <p class="mt-2">{{ traitement.securityOther.comment }}</p> - {% endif %} - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_entitled_persons'|trans }}</strong></td> - <td> - {% if traitement.securityEntitledPersons %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_open_accounts'|trans }}</strong></td> - <td> - {% if traitement.securityOpenAccounts %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> - {% endif %} - </td> - </tr> - <tr> - <td><strong>{{ 'registry.treatment.label.security_specificities_delivered'|trans }}</strong></td> - <td> - {% if traitement.securitySpecificitiesDelivered %} - <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> - {% else %} - <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + </td> + </tr> + </tbody> + </table> + <table class="table"> + <tbody> + <tr> + <td><strong>{{ 'registry.treatment.label.data_origin'|trans }}</strong></td> + <td>{{ traitement.dataOrigin }}</td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.collecting_method'|trans }}</strong></td> + <td> + <ul class="ps-1"> + {% for method in traitement.collectingMethod %} + <li>{{ method|dictionary('registry_treatment_collecting_method') }}</li> + {% endfor %} + </ul> + </td> + </tr> + {% if traitement.otherCollectingMethod is not null %} + <tr> + <td><strong>{{ 'registry.treatment.label.otherCollectingMethod'|trans }}</strong></td> + <td>{{ traitement.otherCollectingMethod }}</td> + </tr> {% endif %} - </td> - </tr> - </tbody> - </table> - </div> - </div> - - {# LINKED MODULES #} - <div class="box box-solid box-warning"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'global.tab.linked_modules'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - {# TREATMENTS #} - {% include '_Utils/_show_block_treatments.html.twig' with { treatments: traitement.treatments } %} - {# REQUESTS #} - {% include '_Utils/_show_block_requests.html.twig' with { requests: traitement.requests } %} - {# VIOLATIONS #} - {% include '_Utils/_show_block_violations.html.twig' with { violations: traitement.violations } %} - {# PROOFS #} - {% include '_Utils/_show_block_proofs.html.twig' with { proofs: traitement.proofs } %} - {# MESUREMENTS #} - {% include '_Utils/_show_block_mesurements.html.twig' with { mesurements: traitement.mesurements } %} - </tbody> - </table> - </div> - </div> + </tbody> + </table> + </div> + </div> - {# TREATMENT CONFORMITY & AIPD #} - {% if traitement.collectivity.hasModuleConformiteTraitement %} - {# TREATMENT CONFORMITY #} - <div class="box box-solid box-success"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.conformite'|trans }}</h3></div> - <div class="box-body no-padding"> - <table role="presentation" class="table"> - <tbody> - <tr> - <td style="width: 35%"> - <strong>{{ 'registry.treatment.label.last_conformite_traitement'|trans }}</strong> - </td> - <td> - {% if traitement.conformiteTraitement is not null %} - {{ traitement.conformiteTraitement.updatedAt|date('d/m/Y') }} - {% else %} - <i>{{ 'registry.treatment.label.no_conformite_traitement'|trans }}</i> - {% endif %} - </td> - </tr> - {% if traitement.conformiteTraitement is not null %} + {# SECURITY #} + <div class="box box-solid box-success"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.security'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> <tr> + <td><strong>{{ 'registry.treatment.label.security_access_control'|trans }}</strong></td> <td> - <strong>{{ 'registry.conformite_traitement.label.conformite_traitement'|trans }}</strong> + {% if traitement.securityAccessControl.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.securityAccessControl.comment is not empty %} + <p class="mt-2">{{ traitement.securityAccessControl.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.security_update'|trans }}</strong></td> <td> - {{ getConformiteTraitementLabel(traitement.conformiteTraitement)|raw }} + {% if traitement.securityUpdate.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.securityUpdate.comment is not empty %} + <p class="mt-2">{{ traitement.securityUpdate.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> </tr> <tr> + <td><strong>{{ 'registry.treatment.label.security_saving'|trans }}</strong></td> <td> - <strong>{{ 'registry.conformite_traitement.label.conformite_reponse'|trans }}</strong> + {% if traitement.securitySaving.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.securitySaving.comment is not empty %} + <p class="mt-2">{{ traitement.securitySaving.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.security_tracability'|trans }}</strong></td> <td> - {% set nbTotal = traitement.conformiteTraitement.nbConformes + traitement.conformiteTraitement.nbNonConformesMineures + traitement.conformiteTraitement.nbNonConformesMajeures %} - {% set widthNbConforme = ((traitement.conformiteTraitement.nbConformes * 100) / nbTotal)|round %} - {% set widthnbNonConformesMineures = ((traitement.conformiteTraitement.nbNonConformesMineures * 100) / nbTotal)|round %} - {% set widthnbNonConformesMajeures = 100 - (widthNbConforme + widthnbNonConformesMineures) %} - <div class="stacked-bar-graph"> - {% if widthNbConforme %}<span style="width:{{ widthNbConforme }}%" class="bar-conforme tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.conforme'|trans }} {{ traitement.conformiteTraitement.nbConformes }}</span></span>{% endif %} - {% if widthnbNonConformesMineures %}<span style="width:{{ widthnbNonConformesMineures }}%" class="bar-non-conforme-mineure tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.minor_conforme'|trans }} {{ traitement.conformiteTraitement.nbNonConformesMineures }}</span></span>{% endif %} - {% if widthnbNonConformesMajeures %}<span style="width:{{ widthnbNonConformesMajeures }}%" class="bar-non-conforme-majeure tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.major_conforme'|trans }} {{ traitement.conformiteTraitement.nbNonConformesMajeures }}</span></span>{% endif %} - </div> + {% if traitement.securitytracability.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.securitytracability.comment is not empty %} + <p class="mt-2">{{ traitement.securitytracability.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> </tr> - {% endif %} - </tbody> - </table> - </div> - </div> - {# AIPD #} - {% if traitement.conformiteTraitement is not null %} - {% set analyseImpact = traitement.conformiteTraitement.lastAnalyseImpact %} - {% endif %} - <div class="box box-solid box-primary"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'registry.treatment.tab.last_aipd'|trans }}</h3></div> - <div class="box-body no-padding"> - <table role="presentation" class="table"> - <tbody> - <tr> - <td style="width: 35%"> - <strong>{{ 'aipd.treatment.label.last_aipd'|trans }}</strong> - </td> - <td> - {% if traitement.conformiteTraitement is null %} - <i>{{ 'aipd.treatment.label.no_conformite_traitement'|trans }}</i> - {% elseif traitement.conformiteTraitement is not null and analyseImpact is null %} - <i>{{ 'aipd.treatment.label.no_aipd'|trans }}</i> - {% else %} - {{ analyseImpact.createdAt|date('d/m/Y') }} - {% endif %} - </td> - </tr> - {% if traitement.conformiteTraitement is not null and analyseImpact is not null %} <tr> + <td><strong>{{ 'registry.treatment.label.security_other'|trans }}</strong></td> <td> - <strong>{{ 'aipd.treatment.label.avis_aipd'|trans }}</strong> + {% if traitement.securityOther.check %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% if traitement.securityOther.comment is not empty %} + <p class="mt-2">{{ traitement.securityOther.comment }}</p> + {% endif %} + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.security_entitled_persons'|trans }}</strong></td> <td> - {% set labelAipdColor = "label-default" %} - {% if analyseImpact.statut == "defavorable" %} - {% set labelAipdColor = "label-danger" %} - {% elseif analyseImpact.statut == "favorable_reserve" %} - {% set labelAipdColor = "label-warning" %} - {% elseif analyseImpact.statut == "favorable" %} - {% set labelAipdColor = "label-success" %} + {% if traitement.securityEntitledPersons %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> {% endif %} - {% set statut = analyseImpact.statut %} - {% set labelStatut = "aipd.analyse_impact.values." ~ traitement.conformiteTraitement.lastAnalyseImpact.statut %} - <span class="label {{ labelAipdColor }}" style="display: inline-block;"> - {{ labelStatut|trans}} - </span> </td> </tr> <tr> + <td><strong>{{ 'registry.treatment.label.security_open_accounts'|trans }}</strong></td> <td> - <strong>{{ 'aipd.analyse_impact.list.date_validation'|trans }}</strong> + {% if traitement.securityOpenAccounts %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> + {% else %} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> + {% endif %} </td> + </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.security_specificities_delivered'|trans }}</strong></td> <td> - {% if analyseImpact.isValidated %} - {{ analyseImpact.dateValidation|date('d/m/Y') }} + {% if traitement.securitySpecificitiesDelivered %} + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> {% else %} - {{ 'aipd.treatment.label.validation_in_progress'|trans }} + <span class="badge bg-yellow">{{ 'global.label.no'|trans }}</span> {% endif %} </td> </tr> - {% endif %} - </tbody> - </table> + </tbody> + </table> + </div> </div> - </div> - {% endif %} - - {# HISTORIC #} - <div class="box box-solid box-default"> - <div class="box-header with-border"><h3 class="box-title" style="color: white">{{ 'global.tab.history'|trans }}</h3></div> - <div class="box-body no-padding"> - <table class="table"> - <tbody> - {% if is_granted('ROLE_REFERENT') %} - <tr> - <td><strong>{{ 'global.label.organization'|trans }}</strong></td> - <td> - {{ traitement.collectivity }} - </td> - </tr> - {% endif %} - <tr> - <td><strong>{{ 'global.label.created_at'|trans }}</strong></td> - <td>{{ traitement.createdAt|date('d/m/Y H:i') }}</td> - </tr> - <tr> - <td><strong>{{ 'global.label.updated_at'|trans }}</strong></td> - <td>{{ traitement.updatedAt|date('d/m/Y H:i') }}</td> - </tr> - <tr> - <td><strong>{{ 'global.label.updated_by'|trans }}</strong></td> - <td>{{ traitement.updatedBy }}</td> - </tr> - </tbody> - </table> - </div> + + {# LINKED MODULES #} + <div class="box box-solid box-warning"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'global.tab.linked_modules'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + {# TREATMENTS #} + {% include '_Utils/_show_block_treatments.html.twig' with { treatments: traitement.treatments } %} + {# REQUESTS #} + {% include '_Utils/_show_block_requests.html.twig' with { requests: traitement.requests } %} + {# VIOLATIONS #} + {% include '_Utils/_show_block_violations.html.twig' with { violations: traitement.violations } %} + {# PROOFS #} + {% include '_Utils/_show_block_proofs.html.twig' with { proofs: traitement.proofs } %} + {# MESUREMENTS #} + {% include '_Utils/_show_block_mesurements.html.twig' with { mesurements: traitement.mesurements } %} + </tbody> + </table> + </div> + </div> + + {# TREATMENT CONFORMITY & AIPD #} + {% if traitement.collectivity.hasModuleConformiteTraitement %} + {# TREATMENT CONFORMITY #} + <div class="box box-solid box-success"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.conformite'|trans }}</h4></div> + <div class="box-body no-padding"> + <table role="presentation" class="table"> + <tbody> + <tr> + <td style="width: 35%"> + <strong>{{ 'registry.treatment.label.last_conformite_traitement'|trans }}</strong> + </td> + <td> + {% if traitement.conformiteTraitement is not null %} + {{ traitement.conformiteTraitement.updatedAt|date('d/m/Y') }} + {% else %} + <i>{{ 'registry.treatment.label.no_conformite_traitement'|trans }}</i> + {% endif %} + </td> + </tr> + {% if traitement.conformiteTraitement is not null %} + <tr> + <td> + <strong>{{ 'registry.conformite_traitement.label.conformite_traitement'|trans }}</strong> + </td> + <td> + {{ getConformiteTraitementLabel(traitement.conformiteTraitement)|raw }} + </td> + </tr> + <tr> + <td> + <strong>{{ 'registry.conformite_traitement.label.conformite_reponse'|trans }}</strong> + </td> + <td> + {% set nbTotal = traitement.conformiteTraitement.nbConformes + traitement.conformiteTraitement.nbNonConformesMineures + traitement.conformiteTraitement.nbNonConformesMajeures %} + {% set widthNbConforme = ((traitement.conformiteTraitement.nbConformes * 100) / nbTotal)|round %} + {% set widthnbNonConformesMineures = ((traitement.conformiteTraitement.nbNonConformesMineures * 100) / nbTotal)|round %} + {% set widthnbNonConformesMajeures = 100 - (widthNbConforme + widthnbNonConformesMineures) %} + <div class="stacked-bar-graph"> + {% if widthNbConforme %}<span style="width:{{ widthNbConforme }}%" class="bar-conforme tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.conforme'|trans }} {{ traitement.conformiteTraitement.nbConformes }}</span></span>{% endif %} + {% if widthnbNonConformesMineures %}<span style="width:{{ widthnbNonConformesMineures }}%" class="bar-non-conforme-mineure tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.minor_conforme'|trans }} {{ traitement.conformiteTraitement.nbNonConformesMineures }}</span></span>{% endif %} + {% if widthnbNonConformesMajeures %}<span style="width:{{ widthnbNonConformesMajeures }}%" class="bar-non-conforme-majeure tooltipchart"><span class="tooltipcharttext">{{ 'registry.conformite_traitement.label.tooltip.major_conforme'|trans }} {{ traitement.conformiteTraitement.nbNonConformesMajeures }}</span></span>{% endif %} + </div> + </td> + </tr> + {% endif %} + </tbody> + </table> + </div> + </div> + {# AIPD #} + {% if traitement.conformiteTraitement is not null %} + {% set analyseImpact = traitement.conformiteTraitement.lastAnalyseImpact %} + {% endif %} + <div class="box box-solid box-primary"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'registry.treatment.tab.last_aipd'|trans }}</h4></div> + <div class="box-body no-padding"> + <table role="presentation" class="table"> + <tbody> + <tr> + <td style="width: 35%"> + <strong>{{ 'aipd.treatment.label.last_aipd'|trans }}</strong> + </td> + <td> + {% if traitement.conformiteTraitement is null %} + <i>{{ 'aipd.treatment.label.no_conformite_traitement'|trans }}</i> + {% elseif traitement.conformiteTraitement is not null and analyseImpact is null %} + <i>{{ 'aipd.treatment.label.no_aipd'|trans }}</i> + {% else %} + {{ analyseImpact.createdAt|date('d/m/Y') }} + {% endif %} + </td> + </tr> + {% if traitement.conformiteTraitement is not null and analyseImpact is not null %} + <tr> + <td> + <strong>{{ 'aipd.treatment.label.avis_aipd'|trans }}</strong> + </td> + <td> + {% set labelAipdColor = "label-default" %} + {% if analyseImpact.statut == "defavorable" %} + {% set labelAipdColor = "label-danger" %} + {% elseif analyseImpact.statut == "favorable_reserve" %} + {% set labelAipdColor = "label-warning" %} + {% elseif analyseImpact.statut == "favorable" %} + {% set labelAipdColor = "label-success" %} + {% endif %} + {% set statut = analyseImpact.statut %} + {% set labelStatut = "aipd.analyse_impact.values." ~ traitement.conformiteTraitement.lastAnalyseImpact.statut %} + <span class="label {{ labelAipdColor }}" style="display: inline-block;"> + {{ labelStatut|trans}} + </span> + </td> + </tr> + <tr> + <td> + <strong>{{ 'aipd.analyse_impact.list.date_validation'|trans }}</strong> + </td> + <td> + {% if analyseImpact.isValidated %} + {{ analyseImpact.dateValidation|date('d/m/Y') }} + {% else %} + {{ 'aipd.treatment.label.validation_in_progress'|trans }} + {% endif %} + </td> + </tr> + {% endif %} + </tbody> + </table> + </div> + </div> + {% endif %} + + {# HISTORIC #} + <div class="box box-solid box-default"> + <div class="box-header with-border"><h4 class="box-title" style="color: white">{{ 'global.tab.history'|trans }}</h4></div> + <div class="box-body no-padding"> + <table class="table"> + <tbody> + {% if is_granted('ROLE_REFERENT') %} + <tr> + <td><strong>{{ 'global.label.organization'|trans }}</strong></td> + <td> + {{ traitement.collectivity }} + </td> + </tr> + {% endif %} + <tr> + <td><strong>{{ 'global.label.created_at'|trans }}</strong></td> + <td>{{ traitement.createdAt|date('d/m/Y H:i') }}</td> + </tr> + <tr> + <td><strong>{{ 'global.label.updated_at'|trans }}</strong></td> + <td>{{ traitement.updatedAt|date('d/m/Y H:i') }}</td> + </tr> + <tr> + <td><strong>{{ 'global.label.updated_by'|trans }}</strong></td> + <td>{{ traitement.updatedBy }}</td> + </tr> + </tbody> + </table> + </div> + </div> + </section> </div> - </div> -</div> - -<script type="text/javascript"> - // wkhtmltopdf 0.12.5 crash fix. - // https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192 - 'use strict'; - (function(setLineDash) { - CanvasRenderingContext2D.prototype.setLineDash = function() { - if(!arguments[0].length){ - arguments[0] = [1,0]; - } - // Now, call the original method - return setLineDash.apply(this, arguments); - }; - })(CanvasRenderingContext2D.prototype.setLineDash); - Function.prototype.bind = Function.prototype.bind || function (thisp) { - var fn = this; - return function () { - return fn.apply(thisp, arguments); - }; - }; - - function radarChart(id, labels, serieLabel, data, color) { - var dataset = []; - data.forEach(function(item, index) { - dataset.push( - { - label: serieLabel[index], - data: item, - backgroundColor: color[index], - } - ); - }); - new Chart( - document.getElementById(id), { - "responsive": false, - "type":"radar", - "data":{ - "labels":labels, - "datasets":dataset - }, - "options":{ - "scale": { - "ticks": { - "min": 0, - "max": 5, + + <script type="text/javascript"> + // wkhtmltopdf 0.12.5 crash fix. + // https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192 + 'use strict'; + (function(setLineDash) { + CanvasRenderingContext2D.prototype.setLineDash = function() { + if(!arguments[0].length){ + arguments[0] = [1,0]; + } + // Now, call the original method + return setLineDash.apply(this, arguments); + }; + })(CanvasRenderingContext2D.prototype.setLineDash); + Function.prototype.bind = Function.prototype.bind || function (thisp) { + var fn = this; + return function () { + return fn.apply(thisp, arguments); + }; + }; + + function radarChart(id, labels, serieLabel, data, color) { + var dataset = []; + data.forEach(function(item, index) { + dataset.push( + { + label: serieLabel[index], + data: item, + backgroundColor: color[index], + } + ); + }); + new Chart( + document.getElementById(id), { + "responsive": false, + "type":"radar", + "data":{ + "labels":labels, + "datasets":dataset }, - }, - "legend": { - "display" : false, + "options":{ + "scale": { + "ticks": { + "min": 0, + "max": 5, + }, + }, + "legend": { + "display" : false, + } + } } - } + ); } - ); - } - - function stackedBarChart(id, labels, data) { - - new Chart(document.getElementById(id), { - type: 'bar', - data: { - labels: labels, - datasets: data, - }, - options: { - scales: { - yAxes: [{ - stacked: true, - ticks : { - beginAtZero: false, - stepSize: 1, - callback: function(label, index, labels) { - switch (label) { - case 1: - return 'Négligeable' - case 2: - return 'Limité' - case 3: - return 'Important' - case 4: - return 'Maximal' - } - } - }, - }], - xAxes: [{ - stacked: true, - }], - x: { - stacked: true, - }, - y: { - stacked: true, + function stackedBarChart(id, labels, data) { + + new Chart(document.getElementById(id), { + type: 'bar', + data: { + labels: labels, + datasets: data, }, - }, - animation: { - duration: 0 - } - } - }); - } - - function bubbleChart(id, labels, data) { - new Chart(document.getElementById(id), { - type: 'bubble', - data: { - datasets: data, - }, - options: { - layout: { - padding: { - left: 50, - right: 50, - top: 0, - bottom: 0 - } - }, - scales: { - yAxes: [{ - gridLines: { - offsetGridLines: true, - }, - ticks : { - stepSize: 1, - min: 0, - max: 4, + options: { + scales: { + yAxes: [{ + stacked: true, + ticks : { + beginAtZero: false, + stepSize: 1, + callback: function(label, index, labels) { + switch (label) { + case 1: + return 'Négligeable' + case 2: + return 'Limité' + case 3: + return 'Important' + case 4: + return 'Maximal' + } + } + }, + + }], + xAxes: [{ + stacked: true, + }], + x: { + stacked: true, + }, + y: { + stacked: true, + }, }, - scaleLabel: { - display: true, - labelString: 'Gravité', + animation: { + duration: 0 } - }], - xAxes: [{ - gridLines: { - offsetGridLines: true - }, - ticks : { - stepSize: 1, - min: 0, - max: 4, + } + }); + } + + function bubbleChart(id, labels, data) { + new Chart(document.getElementById(id), { + type: 'bubble', + data: { + datasets: data, + }, + options: { + layout: { + padding: { + left: 50, + right: 50, + top: 0, + bottom: 0 + } }, - scaleLabel: { - display: true, - labelString: 'Vraisemblance', + scales: { + yAxes: [{ + gridLines: { + offsetGridLines: true, + }, + ticks : { + stepSize: 1, + min: 0, + max: 4, + }, + scaleLabel: { + display: true, + labelString: 'Gravité', + } + }], + xAxes: [{ + gridLines: { + offsetGridLines: true + }, + ticks : { + stepSize: 1, + min: 0, + max: 4, + }, + scaleLabel: { + display: true, + labelString: 'Vraisemblance', + }, + }], }, - }], - }, - animation: { - duration: 0 - } + animation: { + duration: 0 + } + } + }); } - }); - } - - var colorBlue = 'rgba(54, 162, 235, 0.5)'; - var colorPurple = 'rgba(153, 51, 204, 0.5)'; - var colorTeal = 'rgba(109, 199, 200, 1)'; - var colorPink = 'rgba(243, 109, 143, 1)'; - - var domainesLabels = []; - var domainesDatas = []; - - - {% for critere in object.criterePrincipeFondamentaux %} - {% if critere.reponse != 'non_applicable' %} - domainesLabels.push("{{ critere.label|u.truncate(28,'...')|raw|escape('js') }}"); - {% if critere.reponse == 'conforme' %} - domainesDatas.push(5); - {% else %} - domainesDatas.push(1); - {% endif %} - {% endif %} - {% endfor %} - - {% for question in object.questionConformites|sort((a, b) => a.position >= b.position) %} - {% set reponse = object.conformiteTraitement.reponseOfName(question.question) %} - {% if reponse and reponse.conforme %} - domainesDatas.push(5); - {% elseif reponse and reponse.actionProtections is not empty %} - domainesDatas.push(3); - {% else %} - domainesDatas.push(1); - {% endif %} - domainesLabels.push("{{ question.question|u.truncate(28, "...")|raw|escape('js') }}"); - {% endfor %} - /* The format of the data used by the chart is [[],[]] but here we use only 1 set of data */ - domainesDatas = [domainesDatas]; - - var mesuresLabels = []; - var mesuresDatas = []; - var risquesLabels = []; - var risquesDataSet1 = []; - var risquesDataSet2 = []; - var dicResiduelsData = []; - var risquesResiduelsLabels = []; - - var dispoGravity = 0; - var dispoVraisemblance = 0; - var integrityGravity = 0; - var integrityVraisemblance = 0; - var confidentialityGravity = 0; - var confidentialityVraisemblance = 0; - var vraisemblance = 0; - var gravite = 0; - - {% for scenario in object.scenarioMenaces %} - vraisemblance = {{ getScenarioMenaceIndicateurResiduel(scenario, 'vraisemblance') }} - gravite = {{ getScenarioMenaceIndicateurResiduel(scenario, 'gravite') }} - {% if (scenario.isDisponibilite) %} - dispoGravity = gravite > dispoGravity ? gravite : dispoGravity; - dispoVraisemblance = vraisemblance > dispoVraisemblance ? vraisemblance : dispoVraisemblance; - // P(x,y) => si x>0,6 alors x=x-0,5 si y>0,6 alors y=y-0,5 - // https://gitlab.adullact.net/soluris/madis/-/issues/635 - //dispoGravity = dispoGravity > 0.6 ? dispoGravity - 0.5 : dispoGravity - //dispoVraisemblance = dispoVraisemblance > 0.6 ? dispoVraisemblance - 0.5 : dispoVraisemblance - {% endif %} - {% if (scenario.isIntegrite) %} - integrityGravity = gravite > integrityGravity ? gravite : integrityGravity; - integrityVraisemblance = vraisemblance > integrityVraisemblance ? vraisemblance : integrityVraisemblance; - // P(x,y) => si x>0,6 alors x=x-0,5 si y>0,6 alors y=y-0,5 - // https://gitlab.adullact.net/soluris/madis/-/issues/635 - //integrityGravity = integrityGravity > 0.6 ? integrityGravity - 0.5 : integrityGravity - //integrityVraisemblance = integrityVraisemblance > 0.6 ? integrityVraisemblance - 0.5 : integrityVraisemblance - {% endif %} - {% if (scenario.isConfidentialite) %} - confidentialityGravity = gravite > confidentialityGravity ? gravite : confidentialityGravity; - confidentialityVraisemblance = vraisemblance > confidentialityVraisemblance ? vraisemblance : confidentialityVraisemblance; - - //confidentialityGravity = confidentialityGravity > 0.6 ? confidentialityGravity - 0.5 : confidentialityGravity - //confidentialityVraisemblance = confidentialityVraisemblance > 0.6 ? confidentialityVraisemblance - 0.5 : confidentialityVraisemblance - {% endif %} - - {% set rr = getScenarioMenaceImpactResiduel(scenario) %} - {% set rp = getScenarioMenaceImpactPotentiel(scenario) %} - risquesDataSet1.push({{ rp-rr }}) - risquesDataSet2.push({{ rr }}); - risquesResiduelsLabels.push("{{ scenario.nom|u.truncate(28, '...') }}"); - {% endfor %} - dicResiduelsData.push({ - label: "Disponibilité", - data: [{x: dispoVraisemblance, y: dispoGravity, r: 10}], - backgroundColor: 'hsl({{ 23 % 360 }}, 100%, 50%)' - },{ - label: "Intégrité", - data: [{x: integrityVraisemblance, y: integrityGravity, r: 10}], - backgroundColor: 'hsl({{ 46 % 360 }}, 100%, 50%)' - },{ - label: "Confidentialité", - data: [{x: confidentialityVraisemblance, y: confidentialityGravity, r: 10}], - backgroundColor: 'hsl({{ 69 % 360 }}, 100%, 50%)' - }); - {% for mesure in object.mesureProtections %} - mesuresLabels.push("{{ mesure.nomCourt|raw|escape('js') }}"); - {% if mesure.reponse == 'insatisfaisant' or mesure.reponse is null %} - mesuresDatas.push(1); - {% elseif mesure.reponse == 'besoin_amelioration' %} - mesuresDatas.push(3); - {% else %} - mesuresDatas.push(5); - {% endif %} - {% endfor %} - mesuresDatas = [mesuresDatas]; - risquesDataSet1 = {label: "Risque couvert", data: risquesDataSet1, backgroundColor: colorTeal}; - risquesDataSet2 = {label: "Risque résiduel", data: risquesDataSet2, backgroundColor: colorPink}; - var risquesDatas = [risquesDataSet2, risquesDataSet1]; - - window.onload = function() { - radarChart("grandsDomaines-chart", domainesLabels, [''], domainesDatas, [colorBlue]); - radarChart('mesuresSecurite-chart', mesuresLabels, [''], mesuresDatas, [colorPurple]); - stackedBarChart("risquesResiduels-chart", risquesResiduelsLabels, risquesDatas); - bubbleChart('dicResiduels-chart', risquesLabels, dicResiduelsData); - }; - -</script> -</body> + + var colorBlue = 'rgba(54, 162, 235, 0.5)'; + var colorPurple = 'rgba(153, 51, 204, 0.5)'; + var colorTeal = 'rgba(109, 199, 200, 1)'; + var colorPink = 'rgba(243, 109, 143, 1)'; + + var domainesLabels = []; + var domainesDatas = []; + + + {% for critere in object.criterePrincipeFondamentaux %} + {% if critere.reponse != 'non_applicable' %} + domainesLabels.push("{{ critere.label|u.truncate(28,'...')|raw|escape('js') }}"); + {% if critere.reponse == 'conforme' %} + domainesDatas.push(5); + {% else %} + domainesDatas.push(1); + {% endif %} + {% endif %} + {% endfor %} + + {% for question in object.questionConformites|sort((a, b) => a.position >= b.position) %} + {% set reponse = object.conformiteTraitement.reponseOfName(question.question) %} + {% if reponse and reponse.conforme %} + domainesDatas.push(5); + {% elseif reponse and reponse.actionProtections is not empty %} + domainesDatas.push(3); + {% else %} + domainesDatas.push(1); + {% endif %} + domainesLabels.push("{{ question.question|u.truncate(28, "...")|raw|escape('js') }}"); + {% endfor %} + /* The format of the data used by the chart is [[],[]] but here we use only 1 set of data */ + domainesDatas = [domainesDatas]; + + var mesuresLabels = []; + var mesuresDatas = []; + var risquesLabels = []; + var risquesDataSet1 = []; + var risquesDataSet2 = []; + var dicResiduelsData = []; + var risquesResiduelsLabels = []; + + var dispoGravity = 0; + var dispoVraisemblance = 0; + var integrityGravity = 0; + var integrityVraisemblance = 0; + var confidentialityGravity = 0; + var confidentialityVraisemblance = 0; + var vraisemblance = 0; + var gravite = 0; + + {% for scenario in object.scenarioMenaces %} + vraisemblance = {{ getScenarioMenaceIndicateurResiduel(scenario, 'vraisemblance') }} + gravite = {{ getScenarioMenaceIndicateurResiduel(scenario, 'gravite') }} + {% if (scenario.isDisponibilite) %} + dispoGravity = gravite > dispoGravity ? gravite : dispoGravity; + dispoVraisemblance = vraisemblance > dispoVraisemblance ? vraisemblance : dispoVraisemblance; + // P(x,y) => si x>0,6 alors x=x-0,5 si y>0,6 alors y=y-0,5 + // https://gitlab.adullact.net/soluris/madis/-/issues/635 + //dispoGravity = dispoGravity > 0.6 ? dispoGravity - 0.5 : dispoGravity + //dispoVraisemblance = dispoVraisemblance > 0.6 ? dispoVraisemblance - 0.5 : dispoVraisemblance + {% endif %} + {% if (scenario.isIntegrite) %} + integrityGravity = gravite > integrityGravity ? gravite : integrityGravity; + integrityVraisemblance = vraisemblance > integrityVraisemblance ? vraisemblance : integrityVraisemblance; + // P(x,y) => si x>0,6 alors x=x-0,5 si y>0,6 alors y=y-0,5 + // https://gitlab.adullact.net/soluris/madis/-/issues/635 + //integrityGravity = integrityGravity > 0.6 ? integrityGravity - 0.5 : integrityGravity + //integrityVraisemblance = integrityVraisemblance > 0.6 ? integrityVraisemblance - 0.5 : integrityVraisemblance + {% endif %} + {% if (scenario.isConfidentialite) %} + confidentialityGravity = gravite > confidentialityGravity ? gravite : confidentialityGravity; + confidentialityVraisemblance = vraisemblance > confidentialityVraisemblance ? vraisemblance : confidentialityVraisemblance; + + //confidentialityGravity = confidentialityGravity > 0.6 ? confidentialityGravity - 0.5 : confidentialityGravity + //confidentialityVraisemblance = confidentialityVraisemblance > 0.6 ? confidentialityVraisemblance - 0.5 : confidentialityVraisemblance + {% endif %} + + {% set rr = getScenarioMenaceImpactResiduel(scenario) %} + {% set rp = getScenarioMenaceImpactPotentiel(scenario) %} + risquesDataSet1.push({{ rp-rr }}) + risquesDataSet2.push({{ rr }}); + risquesResiduelsLabels.push("{{ scenario.nom|u.truncate(28, '...') }}"); + {% endfor %} + dicResiduelsData.push({ + label: "Disponibilité", + data: [{x: dispoVraisemblance, y: dispoGravity, r: 10}], + backgroundColor: 'hsl({{ 23 % 360 }}, 100%, 50%)' + },{ + label: "Intégrité", + data: [{x: integrityVraisemblance, y: integrityGravity, r: 10}], + backgroundColor: 'hsl({{ 46 % 360 }}, 100%, 50%)' + },{ + label: "Confidentialité", + data: [{x: confidentialityVraisemblance, y: confidentialityGravity, r: 10}], + backgroundColor: 'hsl({{ 69 % 360 }}, 100%, 50%)' + }); + {% for mesure in object.mesureProtections %} + mesuresLabels.push("{{ mesure.nomCourt|raw|escape('js') }}"); + {% if mesure.reponse == 'insatisfaisant' or mesure.reponse is null %} + mesuresDatas.push(1); + {% elseif mesure.reponse == 'besoin_amelioration' %} + mesuresDatas.push(3); + {% else %} + mesuresDatas.push(5); + {% endif %} + {% endfor %} + mesuresDatas = [mesuresDatas]; + risquesDataSet1 = {label: "Risque couvert", data: risquesDataSet1, backgroundColor: colorTeal}; + risquesDataSet2 = {label: "Risque résiduel", data: risquesDataSet2, backgroundColor: colorPink}; + var risquesDatas = [risquesDataSet2, risquesDataSet1]; + + window.onload = function() { + radarChart("grandsDomaines-chart", domainesLabels, [''], domainesDatas, [colorBlue]); + radarChart('mesuresSecurite-chart', mesuresLabels, [''], mesuresDatas, [colorPurple]); + stackedBarChart("risquesResiduels-chart", risquesResiduelsLabels, risquesDatas); + bubbleChart('dicResiduels-chart', risquesLabels, dicResiduelsData); + }; + + </script> + </body> </html> diff --git a/templates/Aipd/Modele_analyse/_form_criteres.html.twig b/templates/Aipd/Modele_analyse/_form_criteres.html.twig index 93a08f00fbf70720a30916cf6035216cf750bdc9..cf9667c49d244b84cb0d2448d0a84dfa32852a82 100644 --- a/templates/Aipd/Modele_analyse/_form_criteres.html.twig +++ b/templates/Aipd/Modele_analyse/_form_criteres.html.twig @@ -2,7 +2,7 @@ <td>{{ form_widget(form.label) }}</td> <td>{{ form_widget(form.labelLivrable) }}</td> <td>{{ form_widget(form.reponse) }}</td> - <td> {{ form_widget(form.isVisible) }}</td> + <td>{{ form_widget(form.isVisible) }}</td> <td>{{ form_widget(form.texteConformite) }}</td> <td>{{ form_widget(form.texteNonConformite) }}</td> <td>{{ form_widget(form.texteNonApplicable) }}</td> diff --git a/templates/Registry/Conformite_traitement/list.html.twig b/templates/Registry/Conformite_traitement/list.html.twig index 956f440ebd9d02483cc94b4f82849838c18aaa87..1325257d6ca34ae8dfd0f557203f1561c41b00f4 100644 --- a/templates/Registry/Conformite_traitement/list.html.twig +++ b/templates/Registry/Conformite_traitement/list.html.twig @@ -185,7 +185,6 @@ <script> function cbColRenderFunction (data, type, full, meta){ - console.log(data, type, full, meta) return data } diff --git a/templates/Registry/Contractor/show.html.twig b/templates/Registry/Contractor/show.html.twig index 32adba8be84b9abfaf08ec280464c2ba373d90c3..602849c5a02664deb78424669ded3fbe851dcaa2 100644 --- a/templates/Registry/Contractor/show.html.twig +++ b/templates/Registry/Contractor/show.html.twig @@ -101,9 +101,9 @@ <td><strong>{{ 'registry.contractor.label.sending_data_outside_eu'|trans }}</strong></td> <td> {% if object.sendingDataOutsideEu %} - <span class="badge bg-red">{{ 'global.label.yes'|trans }}</span> + <span class="badge bg-green">{{ 'global.label.yes'|trans }}</span> {% else %} - <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> + <span class="badge bg-red">{{ 'global.label.no'|trans }}</span> {% endif %} </td> </tr> diff --git a/templates/Registry/Treatment/_form.html.twig b/templates/Registry/Treatment/_form.html.twig index 0c47318d82366ea4013b879dc2158f1bbeb93147..ea9bd5bfae4b0470e30f56576d02b39e63df4cf5 100644 --- a/templates/Registry/Treatment/_form.html.twig +++ b/templates/Registry/Treatment/_form.html.twig @@ -66,18 +66,18 @@ {% if serviceEnabled is defined and serviceEnabled %} {{ form_row(form.service) }} {% endif %} - {{ form_row(form.goal) }} <div id="author_group"> {{ form_row(form.author) }} {{ form_row(form.coordonneesResponsableTraitement) }} </div> {{ form_row(form.manager) }} - {{ form_row(form.active) }} + {{ form_row(form.goal) }} {{ form_row(form.legalBasis) }} {{ form_row(form.legalBasisJustification) }} {{ form_row(form.consentRequest) }} {{ form_row(form.consentRequestFormat) }} {{ form_row(form.observation) }} + {{ form_row(form.active) }} {{ form_row(form.public) }} </div> </div> @@ -105,13 +105,13 @@ <div class="box-header with-border"><h3 class="box-title">{{ 'registry.treatment.tab.specific'|trans }}</h3></div> <div class="box-body"> {{ form_row(form.exempt_AIPD) }} - {{ form_row(form.systematicMonitoring) }} {{ form_row(form.largeScaleCollection) }} - {{ form_row(form.vulnerablePeople) }} {{ form_row(form.dataCrossing) }} - {{ form_row(form.evaluationOrRating) }} {{ form_row(form.automatedDecisionsWithLegalEffect) }} + {{ form_row(form.evaluationOrRating) }} {{ form_row(form.automaticExclusionService) }} + {{ form_row(form.vulnerablePeople) }} + {{ form_row(form.systematicMonitoring) }} {{ form_row(form.innovativeUse) }} </div> </div> diff --git a/templates/Registry/Treatment/_form_render.html.twig b/templates/Registry/Treatment/_form_render.html.twig index 9685eb15200f5331b91da42ff6fb2ae4dd6b010d..c40c3ade5eb5214cfb0ee237478b9cbcf5e9fff5 100644 --- a/templates/Registry/Treatment/_form_render.html.twig +++ b/templates/Registry/Treatment/_form_render.html.twig @@ -1,30 +1,28 @@ - {% if form.vars.value.createdAt.timestamp is defined %} {% set submitValue = submitValue|default('registry.treatment.action.edit_submit'|trans) %} {% else %} {% set submitValue = submitValue|default('registry.treatment.action.new_submit'|trans) %} {% endif %} - {{ form_start(form) }} -{{ include('Registry/Treatment/_form.html.twig') }} - -<div class="row"> - <div class="col-md-12"> - <div class="box box-solid"> - <div class="box-body text-center"> - <a href="{{ path('registry_treatment_list') }}" class="btn btn-default"> - {{ 'global.action.back_to_list'|trans }} - </a> - {% if not is_granted('ROLE_ADMIN') and not is_granted('ROLE_REFERENT') %} - <input type="submit" class="btn btn-info draft" value="{{ ('global.action.draft'|trans) }}"> - {% endif %} - <input type="submit" class="btn btn-primary" value="{{ submitValue }}"> + {{ include('Registry/Treatment/_form.html.twig') }} + + <div class="row"> + <div class="col-md-12"> + <div class="box box-solid"> + <div class="box-body text-center"> + <a href="{{ path('registry_treatment_list') }}" class="btn btn-default"> + {{ 'global.action.back_to_list'|trans }} + </a> + {% if not is_granted('ROLE_ADMIN') and not is_granted('ROLE_REFERENT') %} + <input type="submit" class="btn btn-info draft" value="{{ ('global.action.draft'|trans) }}"> + {% endif %} + <input type="submit" class="btn btn-primary" value="{{ submitValue }}"> + </div> </div> </div> </div> -</div> {{ form_end(form) }} @@ -36,16 +34,8 @@ $('#treatment_statut').val('draft'); }) - if (!$("input[id='treatment_legalBasis_1']").is(':checked')){ - $("label[for='treatment_consentRequest']").parents('.form-group').hide(); - $("label[for='treatment_consentRequestFormat']").parents('.form-group').hide(); - $("#treatment_consentRequestFormat").hide(); - $("#treatment_consentRequestFormat").val(''); - $("#treatment_consentRequest").prop('checked',false); - } - - $("input[name='treatment[legalBasis]']").on('change',function(){ - if($(this).val() === 'consent'){ + function toggleConsentFields() { + if ($('#treatment_legalBasis').val() === 'consent') { $("label[for='treatment_consentRequest']").parents('.form-group').show(); $("label[for='treatment_consentRequestFormat']").parents('.form-group').show(); $("#treatment_consentRequestFormat").show(); @@ -54,8 +44,16 @@ $("label[for='treatment_consentRequestFormat']").parents('.form-group').hide(); $("#treatment_consentRequestFormat").hide(); $("#treatment_consentRequestFormat").val(''); - $("#treatment_consentRequest").prop('checked',false); + $("#treatment_consentRequest").prop('checked', false); } - }) + } + + // Initial check on page load + toggleConsentFields(); + + // Event listener for change + $('#treatment_legalBasis').on('change', function(){ + toggleConsentFields(); + }); }); </script> diff --git a/templates/Registry/Treatment/configuration.html.twig b/templates/Registry/Treatment/configuration.html.twig index 8322ecfb1b234ec7f512d45fbae4a0d40e37a0d3..cdeed2c7d4709e002ba0694dc2e5b0ee7b07e06f 100644 --- a/templates/Registry/Treatment/configuration.html.twig +++ b/templates/Registry/Treatment/configuration.html.twig @@ -49,11 +49,10 @@ <div class="box-body"> {{ form_row(form.name) }} {{ form_row(form.service, {'label': 'registry.label.service'}) }} - {{ form_row(form.goal) }} {{ form_row(form.author) }} {{ form_row(form.coordonneesResponsableTraitement) }} {{ form_row(form.manager) }} - {{ form_row(form.active) }} + {{ form_row(form.goal) }} {{ form_row(form.legalBasis) }} {{ form_row(form.legalBasisJustification) }} {{ form_row(form.consentRequest) }} @@ -91,13 +90,13 @@ </div> <div class="box-body"> {{ form_row(form.exempt_AIPD, {'label': 'registry.treatment.label.exempt_AIPD'}) }} - {{ form_row(form.systematicMonitoring) }} {{ form_row(form.largeScaleCollection) }} - {{ form_row(form.vulnerablePeople) }} {{ form_row(form.dataCrossing) }} - {{ form_row(form.evaluationOrRating) }} {{ form_row(form.automatedDecisionsWithLegalEffect) }} + {{ form_row(form.evaluationOrRating) }} {{ form_row(form.automaticExclusionService) }} + {{ form_row(form.vulnerablePeople) }} + {{ form_row(form.systematicMonitoring) }} {{ form_row(form.innovativeUse) }} </div> </div> diff --git a/templates/Registry/Treatment/pdf.html.twig b/templates/Registry/Treatment/pdf.html.twig index 1913f8cea32ca82e36e878d0126b4bee69c78df0..7e142c4e1f3e93fd70c31be414aa12c64e5e7b1d 100644 --- a/templates/Registry/Treatment/pdf.html.twig +++ b/templates/Registry/Treatment/pdf.html.twig @@ -50,10 +50,6 @@ <td>{{ object.service }}</td> </tr> {% endif %} - <tr> - <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> - <td>{{ object.goal|nl2br }}</td> - </tr> <tr> <td><strong>{{ 'registry.treatment.label.author'|trans }}</strong></td> <td>{% if object.author is not null %}{{ object.author|dictionary('registry_treatment_author') }}{% endif %}</td> @@ -69,14 +65,8 @@ <td>{{ object.manager }}</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> - <td> - {% if object.active %} - <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> - {% else %} - <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> - {% endif %} - </td> + <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> + <td>{{ object.goal|nl2br }}</td> </tr> <tr> <td><strong>{{ 'registry.treatment.label.legal_basis'|trans }}</strong></td> @@ -106,6 +96,16 @@ <td><strong>{{ 'registry.treatment.label.observation'|trans }}</strong></td> <td>{{ object.observation|nl2br }}</td> </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> + <td> + {% if object.active %} + <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> + {% else %} + <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> + {% endif %} + </td> + </tr> <tr> <td><strong>{{ 'registry.treatment.label.public_registry'|trans }}</strong></td> <td> @@ -192,9 +192,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> <td> - {% if object.systematicMonitoring %} + {% if object.largeScaleCollection %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -202,9 +202,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> <td> - {% if object.largeScaleCollection %} + {% if object.dataCrossing %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -212,9 +212,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> <td> - {% if object.vulnerablePeople %} + {% if object.automatedDecisionsWithLegalEffect %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -222,9 +222,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> <td> - {% if object.dataCrossing %} + {% if object.evaluationOrRating %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -232,9 +232,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> <td> - {% if object.evaluationOrRating %} + {% if object.automaticExclusionService %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -242,9 +242,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> <td> - {% if object.automatedDecisionsWithLegalEffect %} + {% if object.vulnerablePeople %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -252,9 +252,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> <td> - {% if object.automaticExclusionService %} + {% if object.systematicMonitoring %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> diff --git a/templates/Registry/Treatment/pdf_all.html.twig b/templates/Registry/Treatment/pdf_all.html.twig index 99acc3e9a69b0c9ae7bea6d43e03580fb70bf32e..68c94439eb599871b4077ccda294f8142f65ff87 100644 --- a/templates/Registry/Treatment/pdf_all.html.twig +++ b/templates/Registry/Treatment/pdf_all.html.twig @@ -52,10 +52,6 @@ <td>{{ object.service }}</td> </tr> {% endif %} - <tr> - <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> - <td>{{ object.goal|nl2br }}</td> - </tr> <tr> <td><strong>{{ 'registry.treatment.label.author'|trans }}</strong></td> <td>{% if object.author is not null %}{{ object.author|dictionary('registry_treatment_author') }}{% endif %}</td> @@ -71,14 +67,8 @@ <td>{{ object.manager }}</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> - <td> - {% if object.active %} - <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> - {% else %} - <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> - {% endif %} - </td> + <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> + <td>{{ object.goal|nl2br }}</td> </tr> <tr> <td><strong>{{ 'registry.treatment.label.legal_basis'|trans }}</strong></td> @@ -108,6 +98,16 @@ <td><strong>{{ 'registry.treatment.label.observation'|trans }}</strong></td> <td>{{ object.observation|nl2br }}</td> </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> + <td> + {% if object.active %} + <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> + {% else %} + <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> + {% endif %} + </td> + </tr> <tr> <td><strong>{{ 'registry.treatment.label.public_registry'|trans }}</strong></td> <td> @@ -194,9 +194,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> <td> - {% if object.systematicMonitoring %} + {% if object.largeScaleCollection %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -204,9 +204,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> <td> - {% if object.largeScaleCollection %} + {% if object.dataCrossing %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -214,9 +214,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> <td> - {% if object.vulnerablePeople %} + {% if object.automatedDecisionsWithLegalEffect %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -224,9 +224,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> <td> - {% if object.dataCrossing %} + {% if object.evaluationOrRating %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -234,9 +234,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> <td> - {% if object.evaluationOrRating %} + {% if object.automaticExclusionService %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -244,9 +244,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> <td> - {% if object.automatedDecisionsWithLegalEffect %} + {% if object.vulnerablePeople %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -254,9 +254,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> <td> - {% if object.automaticExclusionService %} + {% if object.systematicMonitoring %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> diff --git a/templates/Registry/Treatment/public_show.html.twig b/templates/Registry/Treatment/public_show.html.twig index 51bc589d2d7b1cf15b07e6da90c786ece24eb9f9..7fca02950cec214d4bfc39d88c6b8f96b00702ea 100644 --- a/templates/Registry/Treatment/public_show.html.twig +++ b/templates/Registry/Treatment/public_show.html.twig @@ -37,11 +37,10 @@ {% if ( (object.name and config.name == true) or (object.service and config.service == true) - or (object.goal and config.goal == true) or (object.author and config.author == true) or (object.author == "processing_manager" and object.coordonneesResponsableTraitement and config.coordonneesResponsableTraitement == true) or (object.manager and config.manager == true) - or (object.active and config.active == true) + or (object.goal and config.goal == true) or (object.legalBasis and config.legalBasis == true) or (object.legalBasisJustification and config.legalBasisJustification == true) or (object.consentRequest and config.consentRequest == true) @@ -71,15 +70,6 @@ <td>{{ object.service }}</td> </tr> {% endif %} - - {% if (object.goal and config.goal == true) %} - <tr> - <td> - <strong>{{ 'registry.treatment.label.goal'|trans }}</strong> - </td> - <td>{{ object.goal|nl2br }}</td> - </tr> - {% endif %} {% if (object.author and config.author == true) %} <tr> <td> @@ -108,18 +98,12 @@ <td>{{ object.manager }}</td> </tr> {% endif %} - {% if (object.active and config.active == true) %} + {% if (object.goal and config.goal == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.active'|trans }}</strong> - </td> - <td> - {% if object.active %} - <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> - {% else %} - <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> - {% endif %} + <strong>{{ 'registry.treatment.label.goal'|trans }}</strong> </td> + <td>{{ object.goal|nl2br }}</td> </tr> {% endif %} {% if (object.legalBasis and config.legalBasis == true) %} @@ -265,13 +249,13 @@ {# SPECIFIC #} {% if ( (config.exempt_AIPD == true) - or (config.systematicMonitoring == true) or (config.largeScaleCollection == true) - or (config.vulnerablePeople == true) or (config.dataCrossing == true) - or (config.evaluationOrRating == true) or (config.automatedDecisionsWithLegalEffect == true) + or (config.evaluationOrRating == true) or (config.automaticExclusionService == true) + or (config.vulnerablePeople == true) + or (config.systematicMonitoring == true) or (config.innovativeUse == true) ) %} <div class="box box-solid box-info"> @@ -295,13 +279,13 @@ </td> </tr> {% endif %} - {% if (config.systematicMonitoring == true) %} + {% if (config.largeScaleCollection == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong> + <strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong> </td> <td> - {% if object.systematicMonitoring %} + {% if object.largeScaleCollection %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -309,13 +293,13 @@ </td> </tr> {% endif %} - {% if (config.largeScaleCollection == true) %} + {% if (config.dataCrossing == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong> + <strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong> </td> <td> - {% if object.largeScaleCollection %} + {% if object.dataCrossing %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -323,13 +307,13 @@ </td> </tr> {% endif %} - {% if (config.vulnerablePeople == true) %} + {% if (config.automatedDecisionsWithLegalEffect == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong> + <strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong> </td> <td> - {% if object.vulnerablePeople %} + {% if object.automatedDecisionsWithLegalEffect %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -337,13 +321,13 @@ </td> </tr> {% endif %} - {% if (config.dataCrossing == true) %} + {% if (config.evaluationOrRating == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong> + <strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong> </td> <td> - {% if object.dataCrossing %} + {% if object.evaluationOrRating %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -351,13 +335,13 @@ </td> </tr> {% endif %} - {% if (config.evaluationOrRating == true) %} + {% if (config.automaticExclusionService == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong> + <strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong> </td> <td> - {% if object.evaluationOrRating %} + {% if object.automaticExclusionService %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -365,13 +349,13 @@ </td> </tr> {% endif %} - {% if (config.automatedDecisionsWithLegalEffect == true) %} + {% if (config.vulnerablePeople == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong> + <strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong> </td> <td> - {% if object.automatedDecisionsWithLegalEffect %} + {% if object.vulnerablePeople %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -379,13 +363,13 @@ </td> </tr> {% endif %} - {% if (config.automaticExclusionService == true) %} + {% if (config.systematicMonitoring == true) %} <tr> <td> - <strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong> + <strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong> </td> <td> - {% if object.automaticExclusionService %} + {% if object.systematicMonitoring %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> diff --git a/templates/Registry/Treatment/show.html.twig b/templates/Registry/Treatment/show.html.twig index 41992c9bdc69d4f6bdce65f4e1492620b56dd33d..5c40bbb3435c7e83c14a6468a43144450fd6444a 100644 --- a/templates/Registry/Treatment/show.html.twig +++ b/templates/Registry/Treatment/show.html.twig @@ -88,10 +88,6 @@ <td>{{ object.service }}</td> </tr> {% endif %} - <tr> - <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> - <td>{{ object.goal|nl2br }}</td> - </tr> <tr> <td><strong>{{ 'registry.treatment.label.author'|trans }}</strong></td> <td>{% if object.author is not null %}{{ object.author|dictionary('registry_treatment_author') }}{% endif %}</td> @@ -107,14 +103,8 @@ <td>{{ object.manager }}</td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> - <td> - {% if object.active %} - <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> - {% else %} - <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> - {% endif %} - </td> + <td><strong>{{ 'registry.treatment.label.goal'|trans }}</strong></td> + <td>{{ object.goal|nl2br }}</td> </tr> <tr> <td><strong>{{ 'registry.treatment.label.legal_basis'|trans }}</strong></td> @@ -144,6 +134,16 @@ <td><strong>{{ 'registry.treatment.label.observation'|trans }}</strong></td> <td>{{ object.observation|nl2br }}</td> </tr> + <tr> + <td><strong>{{ 'registry.treatment.label.active'|trans }}</strong></td> + <td> + {% if object.active %} + <span class="badge bg-green">{{ 'global.label.active'|trans }}</span> + {% else %} + <span class="badge bg-red">{{ 'global.label.inactive'|trans }}</span> + {% endif %} + </td> + </tr> <tr> <td><strong>{{ 'registry.treatment.label.public_registry'|trans }}</strong></td> <td> @@ -230,9 +230,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> <td> - {% if object.systematicMonitoring %} + {% if object.largeScaleCollection %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -240,9 +240,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.large_scale_collection'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> <td> - {% if object.largeScaleCollection %} + {% if object.dataCrossing %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -250,9 +250,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> <td> - {% if object.vulnerablePeople %} + {% if object.automatedDecisionsWithLegalEffect %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -260,9 +260,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.data_crossing'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> <td> - {% if object.dataCrossing %} + {% if object.evaluationOrRating %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -270,9 +270,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.evaluation_or_rating'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> <td> - {% if object.evaluationOrRating %} + {% if object.automaticExclusionService %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -280,9 +280,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automated_decisions_with_legal_effect'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.vulnerable_people'|trans }}</strong></td> <td> - {% if object.automatedDecisionsWithLegalEffect %} + {% if object.vulnerablePeople %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> @@ -290,9 +290,9 @@ </td> </tr> <tr> - <td><strong>{{ 'registry.treatment.label.automatic_exclusion_service'|trans }}</strong></td> + <td><strong>{{ 'registry.treatment.label.systematic_monitoring'|trans }}</strong></td> <td> - {% if object.automaticExclusionService %} + {% if object.systematicMonitoring %} <span class="badge bg-yellow">{{ 'global.label.yes'|trans }}</span> {% else %} <span class="badge bg-green">{{ 'global.label.no'|trans }}</span> diff --git a/templates/User/Collectivity/edit.html.twig b/templates/User/Collectivity/edit.html.twig index db3a6d4c49721b94ac9f843ebdb2d88f7fa805f7..ceb745e56ac94fd5de0e6e77e175d6d6df6c37e6 100644 --- a/templates/User/Collectivity/edit.html.twig +++ b/templates/User/Collectivity/edit.html.twig @@ -42,7 +42,6 @@ $("#collectivity_reviewData_logo").after('<div style="margin-top:1em"><img height="80" src="{{ object.reviewData.logo }}" /><button id="setDeleteLogo" class="btn btn-link"><i aria-hidden="true" class="fa fa-trash"></i> Supprimer le logo</button></div>') $("body").on('click', '#setDeleteLogo', function(ev) { ev.preventDefault() - console.log('click', ev) $(ev.target).parent().remove() $('#collectivity_reviewData_deleteLogo').val(1); }) diff --git a/templates/User/Collectivity/list.html.twig b/templates/User/Collectivity/list.html.twig index 82b3b0e236ee5f1dd5edac6153e5eab2ee08498f..338e10d72bf4408e6a0eaf17f0472889a0d0742b 100644 --- a/templates/User/Collectivity/list.html.twig +++ b/templates/User/Collectivity/list.html.twig @@ -255,7 +255,7 @@ $('body').append(form); form.submit(); }).fail(function(err) { - console.log(err) + // console.log(err) }) }) } diff --git a/templates/User/Profile/collectivity_edit.html.twig b/templates/User/Profile/collectivity_edit.html.twig index c4e71648099885d67e18b16e037c5d888654e3ac..93081c03079a80aad4172c961593778045538928 100644 --- a/templates/User/Profile/collectivity_edit.html.twig +++ b/templates/User/Profile/collectivity_edit.html.twig @@ -197,7 +197,6 @@ $("#collectivity_reviewData_logo").after('<div style="margin-top:1em"><img height="80" src="{{ object.reviewData.logo }}" /><button id="setDeleteLogo" class="btn btn-link"><i aria-hidden="true" class="fa fa-trash"></i> Supprimer le logo</button></div>') $("body").on('click', '#setDeleteLogo', function(ev) { ev.preventDefault() - console.log('click', ev) $(ev.target).parent().remove() $('#collectivity_reviewData_deleteLogo').val(1); }) diff --git a/tests/Domain/Admin/Cloner/TreatmentClonerTest.php b/tests/Domain/Admin/Cloner/TreatmentClonerTest.php index c6e4c7f88bd4615849076a52c767893b12f19c8e..cf7ad3151f30822bcb655e32d7c22173e60f78f8 100644 --- a/tests/Domain/Admin/Cloner/TreatmentClonerTest.php +++ b/tests/Domain/Admin/Cloner/TreatmentClonerTest.php @@ -110,10 +110,10 @@ class TreatmentClonerTest extends TestCase $this->assertInstanceOf(Model\Embeddable\ComplexChoice::class, $securityOther); $this->assertFalse($securityOther->isCheck()); $this->assertNull($securityOther->getComment()); - $this->assertFalse($cloned->isSystematicMonitoring()); $this->assertFalse($cloned->isLargeScaleCollection()); - $this->assertFalse($cloned->isVulnerablePeople()); $this->assertFalse($cloned->isDataCrossing()); + $this->assertFalse($cloned->isVulnerablePeople()); + $this->assertFalse($cloned->isSystematicMonitoring()); $this->assertTrue($cloned->isActive()); $this->assertFalse($cloned->isSecurityEntitledPersons()); $this->assertFalse($cloned->isSecurityOpenAccounts()); @@ -167,10 +167,10 @@ class TreatmentClonerTest extends TestCase $securityOther = $referent->getSecurityOther(); $securityOther->setCheck(true); $securityOther->setComment('comment'); - $referent->setSystematicMonitoring(true); $referent->setLargeScaleCollection(true); - $referent->setVulnerablePeople(true); $referent->setDataCrossing(true); + $referent->setVulnerablePeople(true); + $referent->setSystematicMonitoring(true); $referent->setActive(false); $referent->setSecurityEntitledPersons(false); $referent->setSecurityOpenAccounts(true); @@ -225,10 +225,10 @@ class TreatmentClonerTest extends TestCase $this->assertEquals($referentSecurityOther->isCheck(), $clonedSecurityOther->isCheck()); $this->assertEquals($referentSecurityOther->getComment(), $clonedSecurityOther->getComment()); - $this->assertEquals($referent->isSystematicMonitoring(), $cloned->isSystematicMonitoring()); $this->assertEquals($referent->isLargeScaleCollection(), $cloned->isLargeScaleCollection()); - $this->assertEquals($referent->isVulnerablePeople(), $cloned->isVulnerablePeople()); $this->assertEquals($referent->isDataCrossing(), $cloned->isDataCrossing()); + $this->assertEquals($referent->isVulnerablePeople(), $cloned->isVulnerablePeople()); + $this->assertEquals($referent->isSystematicMonitoring(), $cloned->isSystematicMonitoring()); $this->assertEquals($referent->isActive(), $cloned->isActive()); $this->assertEquals($referent->isSecurityEntitledPersons(), $cloned->isSecurityEntitledPersons()); $this->assertEquals($referent->isSecurityOpenAccounts(), $cloned->isSecurityOpenAccounts()); diff --git a/tests/Domain/Registry/Model/TreatmentTest.php b/tests/Domain/Registry/Model/TreatmentTest.php index 3e07fa182fa885b7450821b29ceb63bd5299bfff..23bb5bae3822ba3ae4d9c96036e49d632b77191d 100644 --- a/tests/Domain/Registry/Model/TreatmentTest.php +++ b/tests/Domain/Registry/Model/TreatmentTest.php @@ -55,10 +55,10 @@ class TreatmentTest extends TestCase $this->assertInstanceOf(ComplexChoice::class, $model->getSecuritySaving()); $this->assertInstanceOf(ComplexChoice::class, $model->getSecurityTracability()); $this->assertInstanceOf(ComplexChoice::class, $model->getSecurityOther()); - $this->assertFalse($model->isSystematicMonitoring()); $this->assertFalse($model->isLargeScaleCollection()); - $this->assertFalse($model->isVulnerablePeople()); $this->assertFalse($model->isDataCrossing()); + $this->assertFalse($model->isVulnerablePeople()); + $this->assertFalse($model->isSystematicMonitoring()); $this->assertTrue($model->isActive()); }