Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 529 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
TreatmentGenerator | |
0.00% |
0 / 529 |
|
0.00% |
0 / 6 |
16770 | |
0.00% |
0 / 1 |
addGlobalOverview | |
0.00% |
0 / 84 |
|
0.00% |
0 / 1 |
210 | |||
addSyntheticView | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
42 | |||
addDetailedView | |
0.00% |
0 / 307 |
|
0.00% |
0 / 1 |
3080 | |||
TreatmentAnnexeList | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
110 | |||
RiskTreatmentAnnexeList | |
0.00% |
0 / 87 |
|
0.00% |
0 / 1 |
1806 | |||
IsMesureOk | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | /** |
4 | * This file is part of the MADIS - RGPD Management application. |
5 | * |
6 | * @copyright Copyright (c) 2018-2019 Soluris - Solutions Numériques Territoriales Innovantes |
7 | * |
8 | * This program is free software: you can redistribute it and/or modify |
9 | * it under the terms of the GNU Affero General Public License as published by |
10 | * the Free Software Foundation, either version 3 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU Affero General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Affero General Public License |
19 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | */ |
21 | |
22 | declare(strict_types=1); |
23 | |
24 | namespace App\Domain\Reporting\Generator\Word; |
25 | |
26 | use App\Domain\Registry\Dictionary\TreatmentAuthorDictionary; |
27 | use App\Domain\Registry\Dictionary\TreatmentCollectingMethodDictionary; |
28 | use App\Domain\Registry\Dictionary\TreatmentLegalBasisDictionary; |
29 | use App\Domain\Registry\Dictionary\TreatmentStatutDictionary; |
30 | use App\Domain\Registry\Dictionary\TreatmentUltimateFateDictionary; |
31 | use App\Domain\Registry\Model\Treatment; |
32 | use PhpOffice\PhpWord\Element\Section; |
33 | use PhpOffice\PhpWord\Shared\Converter; |
34 | use PhpOffice\PhpWord\Style\Cell; |
35 | |
36 | class TreatmentGenerator extends AbstractGenerator implements ImpressionGeneratorInterface |
37 | { |
38 | /** |
39 | * Global overview : Information to display for treatment in overview report. |
40 | */ |
41 | public function addGlobalOverview(Section $section, array $data): void |
42 | { |
43 | // GENERATE ALL DATA BEFORE WORD GENERATION IN ORDER TO AVOID SEVERAL LOOP |
44 | $nbTreatments = \count($data); |
45 | $overview = [ |
46 | [ |
47 | 'Nom', |
48 | 'Gestionnaire', |
49 | ], |
50 | ]; |
51 | $digitalisation = [ |
52 | 'paper' => 0, |
53 | 'onlyDigital' => 0, |
54 | 'digital' => 0, |
55 | 'both' => 0, |
56 | 'other' => 0, |
57 | ]; |
58 | $security = [ |
59 | 'accessControl' => 0, |
60 | 'tracability' => 0, |
61 | 'saving' => 0, |
62 | 'update' => 0, |
63 | ]; |
64 | |
65 | /* |
66 | * @var Treatment |
67 | */ |
68 | foreach ($data as $key => $treatment) { |
69 | /* @var Treatment $treatment */ |
70 | // Overview |
71 | |
72 | if (10 > $key) { |
73 | $overview[] = [ |
74 | $treatment->getName(), |
75 | $treatment->getManager() ?? $this->parameterBag->get('APP_DEFAULT_REFERENT'), |
76 | ]; |
77 | } |
78 | |
79 | // Digitalisation |
80 | $hasSoft = $treatment->getCollectivity()->isHasModuleTools() ? count($treatment->getTools()) > 0 : !\is_null($treatment->getSoftware()); |
81 | if ($hasSoft && $treatment->isPaperProcessing()) { |
82 | ++$digitalisation['both']; |
83 | } elseif ($hasSoft) { |
84 | ++$digitalisation['onlyDigital']; |
85 | } elseif ($treatment->isPaperProcessing()) { |
86 | ++$digitalisation['paper']; |
87 | } else { |
88 | ++$digitalisation['other']; |
89 | } |
90 | |
91 | // Security |
92 | if ($hasSoft) { |
93 | if ($treatment->getSecurityAccessControl()->isCheck()) { |
94 | ++$security['accessControl']; |
95 | } |
96 | if ($treatment->getSecurityUpdate()->isCheck()) { |
97 | ++$security['update']; |
98 | } |
99 | if ($treatment->getSecuritySaving()->isCheck()) { |
100 | ++$security['saving']; |
101 | } |
102 | if ($treatment->getSecurityTracability()->isCheck()) { |
103 | ++$security['tracability']; |
104 | } |
105 | } |
106 | } |
107 | // Then aggregate |
108 | $digitalisation['digital'] = $digitalisation['onlyDigital'] + $digitalisation['both']; |
109 | |
110 | $section->addTitle('Registre des traitements', 2); |
111 | $section->addText('La liste des traitements de données à caractère personnel réalisés est documentée. Chaque fiche de registre est établie sur une base de 20 critères. Les critères exigés par le règlement sont pris en compte.'); |
112 | |
113 | $textrun = $section->addTextRun(); |
114 | $textrun->addText('Une version de ces traitements et à valeur de preuve '); |
115 | $textrun->addLink('listTreatments', 'figure en annexe.', ['underline' => 'single'], [], true); |
116 | |
117 | $section->addTitle('Analyse du registre des traitements', 2); |
118 | $section->addText("Il y a aujourd’hui {$nbTreatments} traitements de données à caractère personnel inventoriés."); |
119 | |
120 | $section->addText('Informatisation des traitements :'); |
121 | |
122 | $categories = ['Uniquement papier', 'Complétement informatisé', 'Informatisé et papier', 'Non renseigné']; |
123 | $chartData = $digitalisation; |
124 | unset($chartData['digital']); // Remove aggregate data which cumulate onlyDigital + both |
125 | |
126 | $chartTable = $section->addTable(); |
127 | $chartTable->addRow(); |
128 | $cell = $chartTable->addCell(4000); |
129 | $cell->addChart( |
130 | 'pie', |
131 | $categories, |
132 | $chartData, |
133 | [ |
134 | 'height' => Converter::cmToEmu(6), |
135 | 'width' => Converter::cmToEmu(9), |
136 | 'alignmant' => 'left', |
137 | 'wrappingStyle' => 'square', |
138 | 'positioning' => 'absolute', |
139 | ] |
140 | ); |
141 | $cell = $chartTable->addCell(4000); |
142 | $cell->addText("Sur les {$nbTreatments} traitements : "); |
143 | $cell->addListItem("{$digitalisation['paper']} sont uniquement papier"); |
144 | $cell->addListItem("{$digitalisation['onlyDigital']} sont complétement informatisés"); |
145 | $cell->addListItem("{$digitalisation['both']} sont informatisés et papier"); |
146 | if (0 < $digitalisation['other']) { |
147 | $cell->addListItem("{$digitalisation['other']} ne sont pas renseignés"); |
148 | } |
149 | |
150 | $section->addTitle('Sécurité de base des traitements informatisés', 2); |
151 | $section->addText("Sur les {$digitalisation['digital']} traitements informatisés :"); |
152 | $section->addListItem("{$security['accessControl']} ont un contrôle d'accès"); |
153 | $section->addListItem("{$security['tracability']} ont une traçabilité"); |
154 | $section->addListItem("{$security['saving']} sont sauvegardés"); |
155 | $section->addListItem("{$security['update']} sont mis à jour"); |
156 | |
157 | $section->addText('Par ailleurs, des mesures de protection ont été mises en place sur les ' . ($nbTreatments - $digitalisation['digital']) . ' traitements non informatisés.'); |
158 | } |
159 | |
160 | public function addSyntheticView(Section $section, array $data, bool $forOverviewReport = false): void |
161 | { |
162 | // Break page for overview report |
163 | if ($forOverviewReport) { |
164 | $section->addPageBreak(); |
165 | } |
166 | |
167 | $section->addTitle('Liste des traitements', $forOverviewReport ? 2 : 1); |
168 | |
169 | // Table data |
170 | // Add header |
171 | $tableData = [ |
172 | [ |
173 | 'Nom', |
174 | 'Gestionnaire', |
175 | ], |
176 | ]; |
177 | /** @var Treatment $treatment */ |
178 | // Add content |
179 | foreach ($data as $treatment) { |
180 | $tableData[] = [ |
181 | $treatment->getName() . ('draft' === $treatment->getStatut() ? ' (Brouillon)' : ''), |
182 | $treatment->getManager() ?? $this->parameterBag->get('APP_DEFAULT_REFERENT'), |
183 | ]; |
184 | } |
185 | |
186 | $this->addTable($section, $tableData, true, self::TABLE_ORIENTATION_HORIZONTAL); |
187 | |
188 | // Don't break page if it's overview report |
189 | if (!$forOverviewReport) { |
190 | $section->addPageBreak(); |
191 | } |
192 | } |
193 | |
194 | public function addDetailedView(Section $section, array $data): void |
195 | { |
196 | $section->addTitle('Détail des traitements', 1); |
197 | |
198 | foreach ($data as $key => $treatment) { |
199 | /* @var Treatment $treatment */ |
200 | if (0 !== $key) { |
201 | $section->addPageBreak(); |
202 | } |
203 | |
204 | $section->addTitle($treatment->getName() . ('draft' === $treatment->getStatut() ? ' (Brouillon)' : ''), 2); |
205 | |
206 | $precoDPDData = [ |
207 | [ |
208 | 'Statut', |
209 | $treatment->getStatut() && isset(TreatmentStatutDictionary::getStatuts()[$treatment->getStatut()]) ? TreatmentStatutDictionary::getStatuts()[$treatment->getStatut()] : '', |
210 | ], |
211 | ]; |
212 | |
213 | if (!empty($treatment->getDpoMessage())) { |
214 | $precoDPDData[] = [ |
215 | 'Préconisations', |
216 | $treatment->getDpoMessage(), |
217 | ]; |
218 | } |
219 | |
220 | $generalInformationsData = [ |
221 | [ |
222 | 'Nom', |
223 | $treatment->getName(), |
224 | ], |
225 | ]; |
226 | |
227 | // Ajouter les services si le module est actif |
228 | if ($treatment->getCollectivity()->getIsServicesEnabled()) { |
229 | $generalInformationsData[] = [ |
230 | 'Service', |
231 | $treatment->getService(), |
232 | ]; |
233 | } |
234 | |
235 | $generalInformationsData = array_merge($generalInformationsData, [ |
236 | [ |
237 | 'Finalités', |
238 | $treatment->getGoal() ? \preg_split('/\R/', $treatment->getGoal()) : null, |
239 | ], |
240 | [ |
241 | 'En tant que', |
242 | !\is_null($treatment->getAuthor()) && array_key_exists($treatment->getAuthor(), TreatmentAuthorDictionary::getAuthors()) ? TreatmentAuthorDictionary::getAuthors()[$treatment->getAuthor()] : $treatment->getAuthor(), |
243 | ], |
244 | ]); |
245 | |
246 | // Ajouter les coordonnées du responsable de traitement si l'auteur est différent du Responsable de Traitement |
247 | if ('processing_manager' !== $treatment->getAuthor()) { |
248 | $generalInformationsData[] = [ |
249 | 'Coordonnées du responsable de traitement', |
250 | $treatment->getCoordonneesResponsableTraitement() ? $treatment->getCoordonneesResponsableTraitement() : 'Non renseigné', |
251 | ]; |
252 | } |
253 | |
254 | $generalInformationsData = array_merge($generalInformationsData, [ |
255 | [ |
256 | 'Gestionnaire', |
257 | $treatment->getManager() ?? $this->parameterBag->get('APP_DEFAULT_REFERENT'), |
258 | ], |
259 | [ |
260 | 'État', |
261 | $treatment->isActive() ? 'Actif' : 'Inactif', |
262 | ], |
263 | [ |
264 | 'Base légale', |
265 | TreatmentLegalBasisDictionary::getBasis()[$treatment->getLegalBasis()], |
266 | ], |
267 | [ |
268 | 'Justification de la base légale', |
269 | $treatment->getLegalBasisJustification() ? \preg_split('/\R/', $treatment->getLegalBasisJustification()) : null, |
270 | ], |
271 | ]); |
272 | |
273 | // Ajouter le consentement demandé et son format si la base légale est "consent" |
274 | if ('consent' === $treatment->getLegalBasis()) { |
275 | $generalInformationsData = array_merge($generalInformationsData, [ |
276 | [ |
277 | 'Consentement demandé', |
278 | $treatment->getConsentRequest() ? 'Oui' : 'Non', |
279 | ], |
280 | [ |
281 | 'Format de la demande du consentement', |
282 | $treatment->getConsentRequestFormat(), |
283 | ], |
284 | ]); |
285 | } |
286 | |
287 | $generalInformationsData = array_merge($generalInformationsData, [ |
288 | [ |
289 | 'Observations', |
290 | $treatment->getObservation() ? \preg_split('/\R/', $treatment->getObservation()) : null, |
291 | ], |
292 | [ |
293 | 'Registre public', |
294 | $treatment->getPublic() ? 'Oui' : 'Non', |
295 | ], |
296 | ]); |
297 | |
298 | $detailsData = [ |
299 | [ |
300 | 'Nombre de personnes concernées', |
301 | $treatment->getEstimatedConcernedPeople(), |
302 | ], |
303 | [ |
304 | 'Logiciels et supports', |
305 | \is_string($treatment->getToolsString()) ? $treatment->getToolsString() : null, |
306 | ], |
307 | [ |
308 | 'Traitement papier', |
309 | $treatment->isPaperProcessing() ? 'Oui' : 'Non', |
310 | ], |
311 | [ |
312 | 'Durée de conservation', |
313 | // Defined below |
314 | ], |
315 | [ |
316 | 'Origine des données', |
317 | $treatment->getDataOrigin(), |
318 | ], |
319 | [ |
320 | 'Moyens de la collecte', |
321 | !\is_null($treatment->getCollectingMethod()) ? join(', ', array_map(function ($cm) { |
322 | return TreatmentCollectingMethodDictionary::getMethods()[$cm]; |
323 | }, $treatment->getCollectingMethod())) : '', |
324 | ], |
325 | ]; |
326 | |
327 | // Ajouter l'autre moyen de collecte si le champ n'est pas vide |
328 | if (!empty($treatment->getOtherCollectingMethod())) { |
329 | $detailsData[] = [ |
330 | 'Autre moyen de collecte', |
331 | $treatment->getOtherCollectingMethod(), |
332 | ]; |
333 | } |
334 | |
335 | $detailsData[] = [ |
336 | 'Mentions légales apposées', |
337 | $treatment->getLegalMentions() ? 'Oui' : 'Non', |
338 | ]; |
339 | |
340 | // "Durée de conservation" |
341 | if (count($treatment->getShelfLifes()) > 0) { |
342 | foreach ($treatment->getShelfLifes() as $delay) { |
343 | $detailsData[3][1][] = $delay->name . ' - ' . $delay->duration . ' - ' . TreatmentUltimateFateDictionary::getUltimateFates()[$delay->ultimateFate] . "\n"; |
344 | } |
345 | } else { |
346 | $detailsData[3][1][] = ''; |
347 | } |
348 | |
349 | $categoryData = [ |
350 | [ |
351 | 'Catégorie de données', |
352 | // Values are added below |
353 | ], |
354 | [ |
355 | 'Autres catégories', |
356 | $treatment->getDataCategoryOther() ? \preg_split('/\R/', $treatment->getDataCategoryOther()) : null, |
357 | ], |
358 | ]; |
359 | // Add data categories |
360 | $dataCategories = []; |
361 | foreach ($treatment->getDataCategories() as $category) { |
362 | $dataCategories[] = [ |
363 | 'text' => $category->getName(), |
364 | 'style' => [ |
365 | 'bold' => $category->isSensible() ? true : false, |
366 | ], |
367 | ]; |
368 | } |
369 | $categoryData[0][] = $dataCategories; |
370 | |
371 | $goalData = [ |
372 | [ |
373 | 'Catégorie de destinataires', |
374 | $treatment->getRecipientCategory() ? \preg_split('/\R/', $treatment->getRecipientCategory()) : null, |
375 | ], |
376 | [ |
377 | 'Sous-traitants', |
378 | \implode(', ', $treatment->getContractors()->toArray()), |
379 | ], |
380 | ]; |
381 | |
382 | $concernedPeopleData = [ |
383 | [ |
384 | 'Particuliers', |
385 | $treatment->getConcernedPeopleParticular()->isCheck() ? 'Oui' : 'Non', |
386 | $treatment->getConcernedPeopleParticular()->getComment(), |
387 | ], |
388 | [ |
389 | 'Internautes', |
390 | $treatment->getConcernedPeopleUser()->isCheck() ? 'Oui' : 'Non', |
391 | $treatment->getConcernedPeopleUser()->getComment(), |
392 | ], |
393 | [ |
394 | 'Agents / Salariés', |
395 | $treatment->getConcernedPeopleAgent()->isCheck() ? 'Oui' : 'Non', |
396 | $treatment->getConcernedPeopleAgent()->getComment(), |
397 | ], |
398 | [ |
399 | 'Élus', |
400 | $treatment->getConcernedPeopleElected()->isCheck() ? 'Oui' : 'Non', |
401 | $treatment->getConcernedPeopleElected()->getComment(), |
402 | ], |
403 | [ |
404 | 'Professionnels', |
405 | $treatment->getConcernedPeopleCompany()->isCheck() ? 'Oui' : 'Non', |
406 | $treatment->getConcernedPeopleCompany()->getComment(), |
407 | ], |
408 | [ |
409 | 'Partenaires', |
410 | $treatment->getConcernedPeoplePartner()->isCheck() ? 'Oui' : 'Non', |
411 | $treatment->getConcernedPeoplePartner()->getComment(), |
412 | ], |
413 | [ |
414 | 'Usagers / Résidents', |
415 | $treatment->getConcernedPeopleUsager()->isCheck() ? 'Oui' : 'Non', |
416 | $treatment->getConcernedPeopleUsager()->getComment(), |
417 | ], |
418 | [ |
419 | 'Autres', |
420 | $treatment->getConcernedPeopleOther()->isCheck() ? 'Oui' : 'Non', |
421 | $treatment->getConcernedPeopleOther()->getComment(), |
422 | ], |
423 | ]; |
424 | |
425 | $securityData = [ |
426 | [ |
427 | 'Contrôle d\'accès', |
428 | $treatment->getSecurityAccessControl()->isCheck() ? 'Oui' : 'Non', |
429 | $treatment->getSecurityAccessControl()->getComment(), |
430 | ], |
431 | [ |
432 | 'Mise à jour', |
433 | $treatment->getSecurityUpdate()->isCheck() ? 'Oui' : 'Non', |
434 | $treatment->getSecurityUpdate()->getComment(), |
435 | ], |
436 | [ |
437 | 'Sauvegarde', |
438 | $treatment->getSecuritySaving()->isCheck() ? 'Oui' : 'Non', |
439 | $treatment->getSecuritySaving()->getComment(), |
440 | ], |
441 | [ |
442 | 'Traçabilité', |
443 | $treatment->getSecurityTracability()->isCheck() ? 'Oui' : 'Non', |
444 | $treatment->getSecurityTracability()->getComment(), |
445 | ], |
446 | [ |
447 | 'Autres', |
448 | $treatment->getSecurityOther()->isCheck() ? 'Oui' : 'Non', |
449 | $treatment->getSecurityOther()->getComment(), |
450 | ], |
451 | [ |
452 | 'À tout moment, il est possible de ressortir les personnes habilitées', |
453 | $treatment->isSecurityEntitledPersons() ? 'Oui' : 'Non', |
454 | '', |
455 | ], |
456 | [ |
457 | 'La personne ou la procédure qui permet d’ouvrir des comptes est clairement identifiée', |
458 | $treatment->isSecurityOpenAccounts() ? 'Oui' : 'Non', |
459 | '', |
460 | ], |
461 | [ |
462 | 'Les spécificités de sensibilisation liées à ce traitement sont délivrées', |
463 | $treatment->isSecuritySpecificitiesDelivered() ? 'Oui' : 'Non', |
464 | '', |
465 | ], |
466 | ]; |
467 | |
468 | $specificData = [ |
469 | [ |
470 | 'Est exempté d\'AIPD', |
471 | $treatment->isExemptAIPD() ? 'Oui' : 'Non', |
472 | ], |
473 | [ |
474 | 'Collecte à large échelle', |
475 | $treatment->isLargeScaleCollection() ? 'Oui' : 'Non', |
476 | ], |
477 | [ |
478 | 'Croisement d\'ensemble de données', |
479 | $treatment->isDataCrossing() ? 'Oui' : 'Non', |
480 | ], |
481 | [ |
482 | 'Décision automatique avec effet juridique', |
483 | $treatment->isAutomatedDecisionsWithLegalEffect() ? 'Oui' : 'Non', |
484 | ], |
485 | [ |
486 | 'Évaluation ou notation', |
487 | $treatment->isEvaluationOrRating() ? 'Oui' : 'Non', |
488 | ], |
489 | [ |
490 | 'Exclusion du bénéfice d\'un droit, d’un service ou contrat', |
491 | $treatment->isAutomaticExclusionService() ? 'Oui' : 'Non', |
492 | ], |
493 | [ |
494 | 'Personnes vulnérables', |
495 | $treatment->isVulnerablePeople() ? 'Oui' : 'Non', |
496 | ], |
497 | [ |
498 | 'Surveillance systématique', |
499 | $treatment->isSystematicMonitoring() ? 'Oui' : 'Non', |
500 | ], |
501 | [ |
502 | 'Usage innovant', |
503 | $treatment->isInnovativeUse() ? 'Oui' : 'Non', |
504 | ], |
505 | ]; |
506 | |
507 | $historyData = [ |
508 | [ |
509 | 'Date de création', |
510 | $this->getDate($treatment->getCreatedAt()), |
511 | ], |
512 | [ |
513 | 'Date de modification', |
514 | $this->getDate($treatment->getUpdatedAt()), |
515 | ], |
516 | [ |
517 | 'Modifié par', |
518 | $treatment->getUpdatedBy(), |
519 | ], |
520 | ]; |
521 | |
522 | $section->addTitle('Statut et préconisations DPD', 3); |
523 | $this->addTable($section, $precoDPDData, false, self::TABLE_ORIENTATION_VERTICAL); |
524 | |
525 | $section->addTitle('Informations générales', 3); |
526 | $this->addTable($section, $generalInformationsData, false, self::TABLE_ORIENTATION_VERTICAL); |
527 | |
528 | $section->addTitle('Catégorie de données', 3); |
529 | $this->addTable($section, $categoryData, false, self::TABLE_ORIENTATION_VERTICAL); |
530 | |
531 | $section->addTitle('Destinataires', 3); |
532 | $this->addTable($section, $goalData, false, self::TABLE_ORIENTATION_VERTICAL); |
533 | |
534 | $section->addTitle('Critères de risques', 3); |
535 | $this->addTable($section, $specificData, false, self::TABLE_ORIENTATION_VERTICAL); |
536 | |
537 | $section->addTitle('Détails - Personnes concernées', 3); |
538 | $this->addTable($section, $concernedPeopleData, false, self::TABLE_ORIENTATION_VERTICAL); |
539 | |
540 | $section->addTitle('Détails', 3); |
541 | $this->addTable($section, $detailsData, false, self::TABLE_ORIENTATION_VERTICAL); |
542 | |
543 | $section->addTitle('Mesures de sécurité et confidentialité', 3); |
544 | $this->addTable($section, $securityData, false, self::TABLE_ORIENTATION_VERTICAL); |
545 | |
546 | $section->addTitle('Éléments associés', 3); |
547 | $this->addLinkedData($section, $treatment); |
548 | |
549 | $section->addTitle('Historique', 3); |
550 | $this->addTable($section, $historyData, false, self::TABLE_ORIENTATION_VERTICAL); |
551 | } |
552 | } |
553 | |
554 | public function TreatmentAnnexeList($section, $data) |
555 | { |
556 | $section->addBookmark('listTreatments'); |
557 | $section->addTitle('Liste des traitements', 2); |
558 | $treatmentAnnexListTable = $section->addTable($this->tableStyle); |
559 | $treatmentAnnexListTable->addRow(null, ['tblHeader' => true, 'cantsplit' => true]); |
560 | $cell = $treatmentAnnexListTable->addCell(3000, $this->cellHeadStyle); |
561 | $cell->addText('Nom', $this->textHeadStyle); |
562 | $cell = $treatmentAnnexListTable->addCell(2000, $this->cellHeadStyle); |
563 | $cell->addText('Gestionnaire', $this->textHeadStyle); |
564 | $cell = $treatmentAnnexListTable->addCell(1500, $this->cellHeadStyle); |
565 | $cell->addText('Logiciels et supports', $this->textHeadStyle); |
566 | $cell = $treatmentAnnexListTable->addCell(2000, $this->cellHeadStyle); |
567 | $cell->addText('Mesures de sécurité et confidentialité', $this->textHeadStyle); |
568 | |
569 | foreach ($data as $item) { |
570 | $treatmentAnnexListTable->addRow(null, ['cantsplit' => true]); |
571 | $cell = $treatmentAnnexListTable->addCell(3000); |
572 | $cell->addText($item->getName()); |
573 | $cell = $treatmentAnnexListTable->addCell(2000); |
574 | $cell->addText($item->getManager()); |
575 | $cell = $treatmentAnnexListTable->addCell(1500); |
576 | $support = $item->isPaperProcessing() ? 'Papier, ' : ''; |
577 | $support = $item->getCollectivity() && $item->getCollectivity()->isHasModuleTools() ? $item->getToolsString() : $item->getSoftware(); |
578 | |
579 | $cell->addText($support); |
580 | $cell = $treatmentAnnexListTable->addCell(2000); |
581 | if ($item->getSecurityAccessControl()->isCheck()) { |
582 | $cell->addListItem('Contrôle d\'accès', null, [], [], ['spaceAfter' => 0]); |
583 | } |
584 | if ($item->getSecurityUpdate()->isCheck()) { |
585 | $cell->addListItem('Mise à jour', null, [], [], ['spaceAfter' => 0]); |
586 | } |
587 | if ($item->getSecuritySaving()->isCheck()) { |
588 | $cell->addListItem('Sauvegarde', null, [], [], ['spaceAfter' => 0]); |
589 | } |
590 | if ($item->getSecurityTracability()->isCheck()) { |
591 | $cell->addListItem('Traçabilité', null, [], [], ['spaceAfter' => 0]); |
592 | } |
593 | if ($item->getSecurityOther()->isCheck()) { |
594 | $cell->addListItem('Autres', null, [], [], ['spaceAfter' => 0]); |
595 | } |
596 | } |
597 | } |
598 | |
599 | public function RiskTreatmentAnnexeList($riskAipdSection, $treatments) |
600 | { |
601 | $riskAipdSection->addBookmark('AipdRisks'); |
602 | $riskAipdSection->addTitle('Liste des traitements à risques', 2); |
603 | $RiskTreatmentAnnexListTable = $riskAipdSection->addTable($this->tableStyle); |
604 | $RiskTreatmentAnnexListTable->addRow(3000, ['tblHeader' => true, 'cantsplit' => true]); |
605 | |
606 | $CellsStyle = [ |
607 | 'bgColor' => '3c8dbc', |
608 | 'vAlign' => 'bottom', |
609 | ]; |
610 | |
611 | $cell = $RiskTreatmentAnnexListTable->addCell(500, $CellsStyle); |
612 | $cell->addText('Traitements', $this->textHeadStyle); |
613 | $cell = $RiskTreatmentAnnexListTable->addCell(250, $CellsStyle); |
614 | $cell->addText('Type de données', $this->textHeadStyle); |
615 | |
616 | $titles = ['Données sensibles', |
617 | 'Collecte à large échelle', |
618 | 'Croisement d\'ensemble de données', |
619 | 'Décision automatique avec effet juridique', |
620 | 'Évaluation ou notation', |
621 | 'Exclusion du bénéfice d\'un droit, d’un service ou contrat', |
622 | 'Personnes vulnérables', |
623 | 'Surveillance systématique', |
624 | 'Usage innovant', |
625 | 'CNIL AIPD exemptée', |
626 | '', |
627 | 'AIPD requise']; |
628 | |
629 | $verticalStyle = [ |
630 | 'bgColor' => '3c8dbc', |
631 | 'textDirection' => Cell::TEXT_DIR_BTLR, |
632 | 'valign' => 'top', |
633 | ]; |
634 | foreach ($titles as $title) { |
635 | if ('' === $title) { |
636 | $cell = $RiskTreatmentAnnexListTable->addCell(10, ['borderTopColor' => 'ffffff', 'borderTopSize' => 2, 'borderBottomColor' => 'ffffff', 'borderBottomSize' => 2]); |
637 | $cell->addText($title); |
638 | } else { |
639 | $cell = $RiskTreatmentAnnexListTable->addCell(70, $verticalStyle); |
640 | $cell->addText($title, $this->textHeadStyle); |
641 | } |
642 | } |
643 | /** @var Treatment $item */ |
644 | foreach ($treatments as $item) { |
645 | $cnt_sensible = 0; |
646 | $sensibleDatas = []; |
647 | $specificTreatments = []; |
648 | $item->isLargeScaleCollection() ? $specificTreatments[] = 'Collecte à large échelle' : null; |
649 | $item->isDataCrossing() ? $specificTreatments[] = 'Croisement d’ensemble de données' : null; |
650 | $item->isAutomatedDecisionsWithLegalEffect() ? $specificTreatments[] = 'Décision automatique avec effet juridique' : null; |
651 | $item->isEvaluationOrRating() ? $specificTreatments[] = 'Évaluation ou notation' : null; |
652 | $item->isAutomaticExclusionService() ? $specificTreatments[] = 'Exclusion du bénéfice d\'un droit, d’un service ou contrat' : null; |
653 | $item->isVulnerablePeople() ? $specificTreatments[] = 'Personnes vulnérables' : null; |
654 | $item->isSystematicMonitoring() ? $specificTreatments[] = 'Surveillance systématique' : null; |
655 | $item->isInnovativeUse() ? $specificTreatments[] = 'Usage innovant' : null; |
656 | |
657 | $cnt_categories = count(array_filter($specificTreatments)); |
658 | |
659 | // Ignore treatments with no sensitive specific treatments. |
660 | // https://gitlab.adullact.net/soluris/madis/-/issues/859 |
661 | if (0 === $cnt_categories) { |
662 | continue; |
663 | } |
664 | |
665 | foreach ($item->getDataCategories() as $category) { |
666 | if ($category->isSensible()) { |
667 | ++$cnt_sensible; |
668 | } |
669 | } |
670 | |
671 | $RiskTreatmentAnnexListTable->addRow(null, ['cantsplit' => true]); |
672 | $cell = $RiskTreatmentAnnexListTable->addCell(); |
673 | $cell->addText($item->getName(), ['size' => 8]); |
674 | $cell = $RiskTreatmentAnnexListTable->addCell(); |
675 | foreach ($item->getDataCategories() as $category) { |
676 | $cell->addListItem($category->getName(), null, ['size' => 8], [], ['spaceAfter' => 0]); |
677 | } |
678 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $cnt_sensible > 0 ? 'ffa7a7' : null, 'valign' => 'center']); |
679 | $cell->addText($cnt_sensible > 0 ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
680 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isLargeScaleCollection() ? 'ffa7a7' : null, 'valign' => 'center']); |
681 | $cell->addText($item->isLargeScaleCollection() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
682 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isDataCrossing() ? 'ffa7a7' : null, 'valign' => 'center']); |
683 | $cell->addText($item->isDataCrossing() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
684 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isAutomatedDecisionsWithLegalEffect() ? 'ffa7a7' : null, 'valign' => 'center']); |
685 | $cell->addText($item->isAutomatedDecisionsWithLegalEffect() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
686 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isEvaluationOrRating() ? 'ffa7a7' : null, 'valign' => 'center']); |
687 | $cell->addText($item->isEvaluationOrRating() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
688 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isAutomaticExclusionService() ? 'ffa7a7' : null, 'valign' => 'center']); |
689 | $cell->addText($item->isAutomaticExclusionService() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
690 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isVulnerablePeople() ? 'ffa7a7' : null, 'valign' => 'center']); |
691 | $cell->addText($item->isVulnerablePeople() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
692 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isSystematicMonitoring() ? 'ffa7a7' : null, 'valign' => 'center']); |
693 | $cell->addText($item->isSystematicMonitoring() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
694 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isInnovativeUse() ? 'ffa7a7' : null, 'valign' => 'center']); |
695 | $cell->addText($item->isInnovativeUse() ? 'Oui' : '', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
696 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $item->isExemptAIPD() ? 'bce292' : 'ffa7a7', 'valign' => 'center']); |
697 | $cell->addText($item->isExemptAIPD() ? 'Oui' : 'Non', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
698 | $cell = $RiskTreatmentAnnexListTable->addCell(10, ['borderTopColor' => 'ffffff', 'borderTopSize' => 2, 'borderBottomColor' => 'ffffff', 'borderBottomSize' => 2]); |
699 | $cell->addText(''); |
700 | // https://gitlab.adullact.net/soluris/madis/-/issues/859 |
701 | $aipdRequired = ($cnt_sensible > 0 && $cnt_categories > 0) || $cnt_categories > 1 || ($cnt_sensible > 2); |
702 | if ($item->isExemptAIPD()) { |
703 | $aipdRequired = false; |
704 | } |
705 | $cell = $RiskTreatmentAnnexListTable->addCell(null, ['bgColor' => $aipdRequired ? 'bce292' : 'ffa7a7', 'valign' => 'center']); |
706 | $cell->addText($aipdRequired ? 'Oui' : 'Non', ['size' => 8, 'bold' => true], ['alignment' => 'center']); |
707 | } |
708 | $riskAipdSection->addPageBreak(); |
709 | } |
710 | |
711 | private function IsMesureOk($data) |
712 | { |
713 | return $data->isCheck() ? '00a65a' : '000000'; |
714 | } |
715 | } |