Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 529
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TreatmentGenerator
0.00% covered (danger)
0.00%
0 / 529
0.00% covered (danger)
0.00%
0 / 6
16770
0.00% covered (danger)
0.00%
0 / 1
 addGlobalOverview
0.00% covered (danger)
0.00%
0 / 84
0.00% covered (danger)
0.00%
0 / 1
210
 addSyntheticView
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
42
 addDetailedView
0.00% covered (danger)
0.00%
0 / 307
0.00% covered (danger)
0.00%
0 / 1
3080
 TreatmentAnnexeList
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
110
 RiskTreatmentAnnexeList
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 1
1806
 IsMesureOk
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
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
22declare(strict_types=1);
23
24namespace App\Domain\Reporting\Generator\Word;
25
26use App\Domain\Registry\Dictionary\TreatmentAuthorDictionary;
27use App\Domain\Registry\Dictionary\TreatmentCollectingMethodDictionary;
28use App\Domain\Registry\Dictionary\TreatmentLegalBasisDictionary;
29use App\Domain\Registry\Dictionary\TreatmentStatutDictionary;
30use App\Domain\Registry\Dictionary\TreatmentUltimateFateDictionary;
31use App\Domain\Registry\Model\Treatment;
32use PhpOffice\PhpWord\Element\Section;
33use PhpOffice\PhpWord\Shared\Converter;
34use PhpOffice\PhpWord\Style\Cell;
35
36class 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}