Commit d7797653 authored by Théo GUILLON's avatar Théo GUILLON
Browse files

Ajout : d'un coresponsable lors de la déclaration d'un traitement

Ajout : d'un droit pour crée un coresponsable à la création d'un traitement
Modification : de la modal d'association d'un coresponsable, soustraitant et typage des annexes
parent 9b0bb550
......@@ -526,13 +526,15 @@ INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, mo
INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, modified) VALUES (63, 1, 31, '2020-03-02 15:19:54', '2020-03-02 15:19:54');
INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, modified) VALUES (64, 1, 32, '2020-03-02 15:19:54', '2020-03-02 15:19:54');
INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, modified) VALUES (65, 1, 33, '2020-03-02 15:19:54', '2020-03-02 15:19:54');
INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, modified) VALUES (66, 1, 34, '2020-03-02 15:19:54', '2020-03-02 15:19:54');
INSERT INTO public.droits (id, organisation_user_id, liste_droit_id, created, modified) VALUES (67, 1, 35, '2020-03-02 15:19:54', '2020-03-02 15:19:54');
--
-- Name: droits_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--
SELECT pg_catalog.setval('public.droits_id_seq', 65, true);
SELECT pg_catalog.setval('public.droits_id_seq', 67, true);
--
......@@ -919,12 +921,14 @@ INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (70, 2, 30);
INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (71, 4, 32);
INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (72, 5, 32);
INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (73, 5, 33);
INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (74, 5, 34);
INSERT INTO public.role_droits (id, role_id, liste_droit_id) VALUES (75, 5, 35);
--
-- Name: role_droits_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--
SELECT pg_catalog.setval('public.role_droits_id_seq', 73, true);
SELECT pg_catalog.setval('public.role_droits_id_seq', 75, true);
--
......
......@@ -424,4 +424,59 @@ UPDATE etats SET libelle = 'Traitement initialisé, recu pour rédaction' WHERE
INSERT INTO etats (libelle, value, created, modified) VALUES
('Rédaction du traitement initialisé par le DPO', 13, NOW(), NOW());
CREATE UNIQUE INDEX responsables_raisonsocialestructure_idx ON responsables (raisonsocialestructure);
CREATE UNIQUE INDEX responsables_raisonsocialestructure_siretstructure_idx ON responsables (raisonsocialestructure, siretstructure);
CREATE UNIQUE INDEX responsables_emailstructure_idx ON responsables (emailstructure);
CREATE UNIQUE INDEX responsables_emailresponsable_idx ON responsables (emailresponsable);
ALTER TABLE responsables
ADD COLUMN civiliteresponsable VARCHAR(4),
ADD COLUMN civility_dpo VARCHAR(4),
ADD COLUMN prenom_dpo VARCHAR(50),
ADD COLUMN nom_dpo VARCHAR(50),
ADD COLUMN numerocnil_dpo VARCHAR(50),
ADD COLUMN email_dpo VARCHAR(100),
ADD COLUMN telephonefixe_dpo VARCHAR(15),
ADD COLUMN telephoneportable_dpo VARCHAR(15)
;
CREATE UNIQUE INDEX responsables_email_dpo_idx ON responsables (email_dpo);
CREATE UNIQUE INDEX responsables_numerocnil_dpo_idx ON responsables (numerocnil_dpo);
ALTER TABLE responsables ADD CONSTRAINT responsables_civiliteresponsable_in_list_chk CHECK (cakephp_validate_in_list(civiliteresponsable, ARRAY['M.', 'Mme.']));
ALTER TABLE responsables ADD CONSTRAINT responsables_civility_dpo_in_list_chk CHECK (cakephp_validate_in_list(civility_dpo, ARRAY['M.', 'Mme.']));
ALTER TABLE responsables ADD CONSTRAINT responsables_email_dpo_email_chk CHECK (cakephp_validate_email(email_dpo));
ALTER TABLE responsables ADD CONSTRAINT responsables_telephonefixe_dpo_phone_chk CHECK ( cakephp_validate_phone( telephonefixe_dpo, NULL, 'fr' ) );
ALTER TABLE responsables ADD CONSTRAINT responsables_telephoneportable_dpo_phone_chk CHECK ( cakephp_validate_phone( telephoneportable_dpo, NULL, 'fr' ) );
ALTER TABLE responsables ALTER COLUMN nomresponsable DROP NOT NULL;
ALTER TABLE responsables ALTER COLUMN prenomresponsable DROP NOT NULL;
ALTER TABLE responsables ALTER COLUMN emailresponsable DROP NOT NULL;
ALTER TABLE responsables ALTER COLUMN telephoneresponsable DROP NOT NULL;
ALTER TABLE responsables ALTER COLUMN fonctionresponsable DROP NOT NULL;
ALTER TABLE responsables ALTER COLUMN apestructure DROP NOT NULL;
ALTER TABLE coresponsables
DROP COLUMN nomcoresponsable,
DROP COLUMN prenomcoresponsable,
DROP COLUMN fonctioncoresponsable,
DROP COLUMN emailcoresponsable,
DROP COLUMN telephonecoresponsable,
DROP COLUMN raisonsocialestructure,
DROP COLUMN siretstructure,
DROP COLUMN apestructure,
DROP COLUMN telephonestructure,
DROP COLUMN faxstructure,
DROP COLUMN adressestructure,
DROP COLUMN emailstructure
;
ALTER TABLE coresponsables ADD FOREIGN KEY (responsable_id) REFERENCES responsables(id) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE UNIQUE INDEX coresponsables_fiche_id_responsable_id_idx ON coresponsables (fiche_id, responsable_id);
ALTER TABLE liste_droits ALTER COLUMN libelle TYPE VARCHAR(100);
INSERT INTO liste_droits (libelle, value, created, modified) VALUES
('Gestion des co-responsables lors de la déclaration d''un traitement', 34, NOW(), NOW()),
('Gestion des sous-traitants lors de la déclaration d''un traitement', 35, NOW(), NOW());
ALTER TABLE connecteur_ldaps ALTER COLUMN login TYPE VARCHAR(100);
COMMIT;
......@@ -2582,4 +2582,15 @@ class FichesController extends AppController
return $success;
}
public function ajax_update_listing_responsable()
{
$this->autoRender = false;
if ($this->request->is('get')) {
return json_encode($this->_responsables());
}
return null;
}
}
......@@ -26,6 +26,7 @@ class ResponsablesController extends AppController {
public $uses = [
'Responsable',
'Coresponsable',
];
/**
......@@ -35,7 +36,13 @@ class ResponsablesController extends AppController {
public function beforeFilter() {
parent::beforeFilter();
$this->Droits->assertAuthorized([ListeDroit::GESTION_CORESPONSABLE]);
$action = Inflector::underscore($this->request->params['action']);
if ($action === 'ajax_add') {
$this->Droits->assertAuthorized([ListeDroit::GESTION_CORESPONSABLE_TRAITEMENT]);
} else {
$this->Droits->assertAuthorized([ListeDroit::GESTION_CORESPONSABLE]);
}
}
/**
......@@ -44,14 +51,18 @@ class ResponsablesController extends AppController {
*
* @return array
*/
protected function _getSearchResults() {
protected function _getSearchResults()
{
$paginate = [
'contain' => [
'Organisation' => [
'id',
'raisonsociale',
'order' => ['raisonsociale']
]
],
'Fiche'=> [
'id'
],
],
'conditions' => [],
'order' => [
......@@ -106,7 +117,8 @@ class ResponsablesController extends AppController {
* @created 12/04/2018
* @version v1.0.0
*/
public function index() {
public function index()
{
$this->set('title', __d('responsable', 'responsable.titreGestionResponsableApplication'));
if ($this->request->is('post')) {
......@@ -165,7 +177,8 @@ class ResponsablesController extends AppController {
]);
}
protected function _optionsFiltre($organisation_id = null) {
protected function _optionsFiltre($organisation_id = null)
{
$options = [
'apestructure' => $this->Responsable->getStringOptionList('apestructure', $organisation_id),
'organisations' => $this->Responsable->Organisation->find('list', ['order' => ['Organisation.raisonsociale ASC']]),
......@@ -185,7 +198,8 @@ class ResponsablesController extends AppController {
* @created 12/04/2018
* @version v1.0.0
*/
public function entite() {
public function entite()
{
$this->set('title', __d('responsable', 'responsable.titreGestionResponsableEntitee'));
$this->set([
......@@ -204,7 +218,8 @@ class ResponsablesController extends AppController {
* @created 20/12/2017
* @version V1.0.0
*/
public function add() {
public function add()
{
$this->edit(null);
}
......@@ -219,46 +234,92 @@ class ResponsablesController extends AppController {
* @created 20/12/2017
* @version V1.0.0
*/
public function edit($id) {
if ($this->request->params['action'] === 'add') {
public function edit($id)
{
if (in_array($this->request->params['action'], ['add', 'ajax_add'])) {
$this->set('title', __d('responsable', 'responsable.titreAjouterResponsable'));
} else {
$responsable = $this->Droits->getAndCheckLinkedOrganisationsRecord('Responsable', $id, false);
$this->set('title', __d('responsable', 'responsable.titreModifierResponsable'));
}
$cannotModified = false;
if ($this->request->is('post') || $this->request->is('put')) {
if ('Cancel' === Hash::get($this->request->data, 'submit')) {
$this->redirect($this->Referers->get());
}
if ($this->request->params['action'] === 'add') {
if (in_array($this->request->params['action'], ['add', 'ajax_add'])) {
$data = $this->request->data;
$data['Responsable']['createdbyorganisation'] = $this->Droits->isSu() ? null : $this->Session->read('Organisation.id');
} else {
$data = $this->request->data;
$responsableUseInFiche = $this->Coresponsable->find('all', [
'conditions' => [
'responsable_id' => $id
]
]);
if (!empty($responsableUseInFiche)) {
unset($data['Responsable']['raisonsocialestructure']);
unset($data['Responsable']['siretstructure']);
}
foreach (['id', 'createdbyorganisation'] as $fieldName) {
$data['Responsable'][$fieldName] = $responsable['Responsable'][$fieldName];
}
}
$success = true;
$this->Responsable->begin();
$this->Responsable->create($data);
if (false !== $this->Responsable->save(null, ['atomic' => true])) {
$this->Session->setFlash(__d('responsable', 'responsable.flashsuccessSaveResponsable'), 'flashsuccess');
$this->redirect($this->Referers->get());
$success = $success && false !== $this->Responsable->save(null, ['atomic' => true]);
if ($success == true) {
$this->Responsable->commit();
if ($this->request->params['action'] === 'ajax_add') {
$this->layout = null;
$this->autoRender = false;
$this->response->type('application/json');
$this->response->body(json_encode(['id' => $this->Responsable->getLastInsertID()]));
return $this->response->statusCode(201);
} else {
$this->Session->setFlash(__d('responsable', 'responsable.flashsuccessSaveResponsable'), 'flashsuccess');
$this->redirect($this->Referers->get());
}
} else {
$this->Responsable->rollback();
$this->Session->setFlash(__d('responsable', 'responsable.flasherrorSaveResponsable'), 'flasherror');
}
} elseif ($this->request->params['action'] === 'add') {
$this->request->data['Organisation']['Organisation'] = $this->Droits->isSu() ? null : $this->Session->read('Organisation.id');
} else {
$this->request->data = $responsable;
$responsableUseInFiche = $this->Coresponsable->find('all', [
'conditions' => [
'responsable_id' => $id
]
]);
if (!empty($responsableUseInFiche)) {
$cannotModified = true;
}
}
$mesOrganisations = $this->WebcilUsers->mesOrganisations('list');
$this->set(compact('mesOrganisations'));
$this->set(compact('mesOrganisations', 'cannotModified'));
$this->view = 'edit';
if ($this->request->params['action'] === 'ajax_add') {
$this->view = 'ajax_add';
} else {
$this->view = 'edit';
}
}
/**
......@@ -271,7 +332,8 @@ class ResponsablesController extends AppController {
* @created 12/04/2018
* @version v1.0.0
*/
public function show($id) {
public function show($id)
{
$this->set('title', __d('responsable', 'responsable.titreVisualiserResponsable'));
$query = [
......@@ -317,17 +379,28 @@ class ResponsablesController extends AppController {
* @created 12/04/2018
* @version v1.0.0
*/
public function delete($id) {
public function delete($id)
{
$this->Droits->getAndCheckLinkedOrganisationsRecord('Responsable', $id, true);
$this->Responsable->begin();
$responsableUseInFiche = $this->Coresponsable->find('all', [
'conditions' => [
'responsable_id' => $id
]
]);
if (false !== $this->Responsable->delete($id)) {
$this->Responsable->commit();
$this->Session->setFlash(__d('responsable', 'responsable.flashsuccessSuppressionResponsableEntite'), 'flashsuccess');
if (empty($responsableUseInFiche)) {
$this->Responsable->begin();
if (false !== $this->Responsable->delete($id)) {
$this->Responsable->commit();
$this->Session->setFlash(__d('responsable', 'responsable.flashsuccessSuppressionResponsableEntite'), 'flashsuccess');
} else {
$this->Responsable->rollback();
$this->Session->setFlash(__d('responsable', 'responsable.flasherrorErreurSuppressionResponsableEntite'), 'flasherror');
}
} else {
$this->Responsable->rollback();
$this->Session->setFlash(__d('responsable', 'responsable.flasherrorErreurSuppressionResponsableEntite'), 'flasherror');
$this->Session->setFlash(__d('responsable', 'responsable.flasherrorErreurCannotDeleteResponsableUseFiche'), 'flasherror');
}
$this->redirect($this->Referers->get());
......@@ -344,7 +417,8 @@ class ResponsablesController extends AppController {
* @created 12/04/2018
* @version v1.0.0
*/
public function dissocierResponsable($id) {
public function dissocierResponsable($id)
{
$this->Droits->assertRecordAuthorized('Responsable', $id, ['superadmin' => true]);
$this->Responsable->begin();
......@@ -364,4 +438,24 @@ class ResponsablesController extends AppController {
$this->redirect($this->Referers->get());
}
/**
*
* @access public
*
* @author Théo GUILLON <theo.guillon@libriciel.coop>
* @created 01/07/2020
* @version v2.0.0
*/
public function ajax_add()
{
if ($this->request->is('post')) {
$data['Responsable'] = $this->request->data;
$data['Organisation']['Organisation'] = [$this->Session->read('Organisation.id')];
$this->layout = 'ajax';
$this->request->data = $data;
$this->add();
}
}
}
......@@ -580,6 +580,9 @@ msgstr "Une analyse d’impact sur la protection des données est une étude qui
msgid "fiche.champDepotPia"
msgstr "Avez-vous déposer dans l'onglet annexe l'analyse d'impact (AIPD) ?"
msgid "fiche.popupAddResponsableInFiche"
msgstr "Ajout d'un co-responsable"
#######################
msgid "fiche.emptySelectTypeFile"
......
......@@ -67,6 +67,9 @@ msgstr "Certaines associations entre le responsable sont existantes. Le responsa
msgid "responsable.flasherrorErreurEnregistrementSousTraitantAffecter"
msgstr "Une erreur est survenue lors de l'affectation du responsable à l'entité"
msgid "responsable.flasherrorErreurCannotDeleteResponsableUseFiche"
msgstr "Il n'est pas possible de supprimer un responsable utilisé dans un traitement en tant que co-responsable !"
################
###############################################################################
......@@ -115,7 +118,7 @@ msgstr "Il n'existe aucun responsable pour ces filtres"
msgid "responsable.btnAjouterResponsable"
msgstr " Ajouter un responsable"
msgid "responsable.popupTitreAffecterSousTraitant"
msgid "responsable.popupTitreAffecterResponsable"
msgstr "Associer un ou plusieurs responsable(s) à une ou plusieurs entité(s)"
msgid "responsable.champSelectOrganisation"
......@@ -182,29 +185,32 @@ msgstr "Le responsable :"
msgid "responsable.titreCoresponsable"
msgstr "Le co-responsable :"
msgid "responsable.champCiviliteresponsable"
msgstr "Civilité du responsable"
msgid "responsable.champNomresponsable"
msgstr "Nom du responsable"
msgid "responsable.placeholderChampNomresponsable"
msgstr "Nom du responsable (requis)"
msgstr "Nom de famille du responsable de la structure"
msgid "responsable.champPrenomresponsable"
msgstr "Prénom du responsable"
msgid "responsable.placeholderChampPrenomresponsable"
msgstr "Prénom du responsable (requis)"
msgstr "Prénom du responsable de la structure"
msgid "responsable.champFonctionresponsable"
msgstr "Fonction du responsable "
msgid "responsable.placeholderChampFonctionresponsable"
msgstr "Fonction du responsable (requis)"
msgstr "Fonction du responsable de la structure (PDG, Maire, ...)"
msgid "responsable.champEmailresponsable"
msgstr "E-mail du responsable"
msgid "responsable.placeholderChampEmailresponsable"
msgstr "E-mail du responsable (requis)"
msgstr "E-mail du responsable de la structure"
msgid "responsable.champTelephoneresponsable"
msgstr "Téléphone du responsable"
......@@ -237,7 +243,7 @@ msgid "responsable.champApestructure"
msgstr "Code APE"
msgid "responsable.placeholderChampApestructure"
msgstr "Code APE (requis)"
msgstr "Code APE (facultatif)"
msgid "responsable.placeholderSelectOrganisation"
msgstr "Sélectionnez une ou plusieurs entité(s)"
......@@ -258,15 +264,36 @@ msgid "responsable.champAdressestructure"
msgstr "Adresse"
msgid "responsable.placeholderChampAdressestructure"
msgstr "Adresse du responsable (facultatif)"
msgstr "Adresse de la structure (facultatif)"
msgid "responsable.champEmailstructure"
msgstr "E-mail"
msgid "responsable.placeholderChampEmailstructure"
msgstr "E-mail du responsable (facultatif)"
msgstr "E-mail de la structure (facultatif)"
msgid "responsable.titreAssociationEntiteResponsable"
msgstr "Association du responsable à une entité"
msgid "responsable.champCivilityDpo"
msgstr "Civilité du DPO"
msgid "responsable.champPrenomDpo"
msgstr "Prénom du DPO"
msgid "responsable.champNomDpo"
msgstr "Nom du DPO"
msgid "responsable.champNumerocnilDpo"
msgstr "Numéro d'enregistrement CNIL du DPO"
msgid "responsable.champEmailDpo"
msgstr "E-mail du DPO"
msgid "responsable.champTelephonefixeDpo"
msgstr "Téléphone fixe du DPO"
msgid "responsable.champTelephoneportableDpo"
msgstr "Téléphone portable du DPO"
###############################################################################
......@@ -26,29 +26,6 @@ class Coresponsable extends AppModel {
public $name = 'Coresponsable';
public $validationDomain = 'validation';
public $actsAs = [
'Database.DatabaseFormattable' => [
'Database.DatabaseDefaultFormatter' => [
'formatTrim' => [
'NOT' => ['binary']
],
'formatNull' => true,
'formatNumeric' => [
'float',
'integer'
],
'formatSuffix' => '/_id$/',
'formatStripNotAlnum' => '/^(telephonecoresponsable|telephonestructure|faxstructure|siretstructure)$/'
]
],
'LettercaseFormattable' => [
'upper_noaccents' => ['nomcoresponsable'],
'title' => ['prenomcoresponsable']
]
];
/**
* validate associations
*
......@@ -69,55 +46,6 @@ class Coresponsable extends AppModel {
'rule' => ['notBlank']
]
],
'nomcoresponsable' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'prenomcoresponsable' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'fonctioncoresponsable' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'emailcoresponsable' => [
[
'rule' => ['custom', REGEXP_EMAIL_FR],
'message' => 'validation.adresseMailNonValide'
]
],
'telephonecoresponsable' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'raisonsocialestructure' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'siretstructure' => [
'luhn' => [
'rule' => [
'luhn',
true
],
'message' => 'validation.numeroSIRETNonValide'
],
[
'rule' => 'numeric',
'message' => 'validation.numeroSIRETUniquementComposeChiffre'
],
],
'apestructure' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
];
/**
......@@ -133,6 +61,10 @@ class Coresponsable extends AppModel {
'Fiche' => [
'className' => 'Fiche',
'foreignKey' => 'fiche_id'
]
],
'Responsable' => [
'className' => 'Responsable',
'foreignKey' => 'responsable_id'
],
];
}
......@@ -428,6 +428,23 @@ class Fiche extends AppModel implements LinkedOrganisationInterface {
],
];
public $hasAndBelongsToMany = [
'Responsable' => [
'className' => 'Responsable',
'joinTable' => 'coresponsables',
'foreignKey' => 'fiche_id',
'associationForeignKey' => 'responsable_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => 'Coresponsable'
],
];