Commit abbdff0b authored by THEO GUILLON's avatar THEO GUILLON
Browse files

Merge branch '175-formulaire-conditionnelle' into '1.2.0'

Resolve "Formulaire conditionnelle"

See merge request web-DPO/web-DPO!301
parents bff6664a 0740b5d8
......@@ -38,6 +38,7 @@ la création d'un traitement.
- Ajout des normes "Normes simplifiées" (NS-060)
- Ajout des normes "Référentiel santé" (RS)
- Ajout des normes "Métodomogies de référence" (MR)
- Ajout possibilité de rentre obligatoire un champ case à coché dans le formulaire
### Evolutions
- Affichage de l'onglet "Information de l'entité" lors de la visualisation d'un traitement au registre
......
......@@ -106,6 +106,7 @@ ALTER TABLE fiches
DROP CONSTRAINT fiches_form_id_fkey,
ADD CONSTRAINT fiches_form_id_fkey FOREIGN KEY (form_id) REFERENCES formulaires (id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE fiches ADD COLUMN soustraitance NOT NULL BOOLEAN DEFAULT FALSE;
ALTER TABLE fiches ADD COLUMN obligation_pia BOOL DEFAULT NULL;
ALTER TABLE fiches ADD COLUMN realisation_pia BOOL DEFAULT NULL;
ALTER TABLE fiches ADD COLUMN depot_pia BOOL DEFAULT NULL;
......
......@@ -473,6 +473,8 @@ class FormulairesController extends AppController {
$success = true;
$this->Formulaire->begin();
// debug($this->request->data);die;
$data = $this->request->data;
unset($data['Fiche']);
......@@ -493,79 +495,22 @@ class FormulairesController extends AppController {
}
if ($success == true) {
$array = json_decode($data['Formulaire']['json'], true);
foreach ($array as $value) {
$sortie = array();
foreach ($value as $clef => $valeur) {
switch ($clef) {
case 'onglet':
$ongletChampCoresponsable = false;
$ongletChampSoustraitant = false;
if ($valeur === 'form-container-coresponsable') {
$ongletChampCoresponsable = true;
}
if ($valeur === 'form-container-soustraitant') {
$ongletChampSoustraitant = true;
}
break;
case 'type':
$type = $valeur;
break;
case 'ligne':
$ligne = (int)round($valeur, 0);
break;
case 'colonne':
$colonne = (int)round($valeur, 0);
break;
case 'name':
$sortie[$clef] = LettercaseFormattableBehavior::formatageVariable($valeur);
break;
case 'options':
$options = [];
foreach ($valeur as $key => $option) {
$options[$key] = trim($option);
}
$sortie[$clef] = $options;
break;
case 'default':
if (!is_array($valeur)) {
$sortie[$clef] = trim($valeur);
} else {
$options = [];
foreach ($valeur as $key => $option) {
$options[$key] = trim($option);
}
$sortie[$clef] = $options;
}
break;
if (isset($data['Formulaire']['form-container-formulaire'])) {
foreach ($data['Formulaire']['form-container-formulaire'] as $key => $fields) {
$success = $this->saveFields($id, $fields);
}
}
default:
$sortie[$clef] = $valeur;
break;
}
if (isset($data['Formulaire']['form-container-coresponsable']) && $success == true) {
foreach ($data['Formulaire']['form-container-coresponsable'] as $key => $fields) {
$success = $this->saveFields($id, $fields, true);
}
}
$this->Champ->create([
'formulaire_id' => $id,
'type' => $type,
'ligne' => $ligne,
'colonne' => $colonne,
'details' => json_encode($sortie),
'champ_coresponsable' => $ongletChampCoresponsable,
'champ_soustraitant' => $ongletChampSoustraitant,
]);
$success = false !== $this->Champ->save() && $success;
if (isset($data['Formulaire']['form-container-soustraitant']) && $success == true) {
foreach ($data['Formulaire']['form-container-soustraitant'] as $key => $fields) {
$success = $this->saveFields($id, $fields, false, true);
}
}
}
......@@ -583,13 +528,181 @@ class FormulairesController extends AppController {
}
}
// if ($this->request->params['action'] === 'edit') {
$this->getFields($id);
// }
$this->getFields($id);
$this->view = 'edit';
}
private function saveFields($formulaire_id, $fields, $ongletChampCoresponsable = false, $ongletChampSoustraitant = false)
{
$success = true;
$typeFields = [
'input',
'textarea',
'date',
'checkboxes',
'radios',
'deroulant',
'multi-select',
'title',
'help',
'texte',
];
$valueConditionResult = [
'shown',
'hidden',
];
foreach ($fields as $field) {
$array = (array)json_decode($field['details'], true);
$valeur = array_merge($field, $array);
unset($valeur['details']);
foreach ($valeur as $clef => $val) {
if ($success == false) {
break;
}
switch ($clef) {
case 'type':
if (in_array($val, $typeFields)) {
$type = $val;
} else {
$success = false;
}
break;
case 'ligne':
$ligne = (int)round($val, 0);
break;
case 'colonne':
$colonne = (int)round($val, 0);
break;
case 'name':
$sortie[$clef] = LettercaseFormattableBehavior::formatageVariable($val);
break;
case 'options':
$options = [];
foreach ($val as $key => $option) {
$options[$key] = trim($option);
}
$sortie[$clef] = $options;
break;
case 'default':
if (!is_array($val)) {
$sortie[$clef] = trim($val);
} else {
$options = [];
foreach ($val as $key => $option) {
$options[$key] = trim($option);
}
$sortie[$clef] = $options;
}
break;
case 'conditions':
if (empty($val)) {
break;
}
$conditionsChecked = [];
$conditions = json_decode($val, true);
if (empty($conditions)){
break;
}
foreach ($conditions as $uuid => $condition) {
$condition = (array)$condition;
if (!isset($condition['ifTheField']) || $condition['ifTheField'] == '') {
$success = false;
}
if (!isset($condition['hasValue']) || $condition['hasValue'] == '') {
$success = false;
}
if (!isset($condition['thenTheField']) || $condition['thenTheField'] == '') {
$success = false;
}
if (!isset($condition['mustBe']) || in_array($condition['mustBe'], $valueConditionResult) == false) {
$success = false;
}
if (!isset($condition['ifNot']) || in_array($condition['ifNot'], $valueConditionResult) == false) {
$success = false;
}
if ($success == true) {
$save = true;
// On recupère uniquement les champs qui nous interesse
$tmpCondition = [
'ifTheField' => $condition['ifTheField'],
'hasValue' => $condition['hasValue'],
'thenTheField' => $condition['thenTheField'],
'mustBe' => $condition['mustBe'],
'ifNot' => $condition['ifNot'],
];
if (!empty($conditionsChecked)) {
// On vérifie dans les conditions près à être sauvegarder qu'il n'y a pas de doublon
foreach ($conditionsChecked as $tmp) {
if ($save == false) {
break;
}
$diff_result = array_diff($tmpCondition, $tmp);
if (empty($diff_result)) {
$save = false;
}
}
}
if ($save == true) {
$conditionsChecked[$uuid] = $tmpCondition;
}
}
}
$sortie[$clef] = json_encode($conditionsChecked, JSON_FORCE_OBJECT);
break;
default:
$sortie[$clef] = $val;
break;
}
}
if ($success == false) {
break;
}
$data = [
'formulaire_id' => $formulaire_id,
'type' => $type,
'ligne' => $ligne,
'colonne' => $colonne,
'details' => json_encode($sortie),
'champ_coresponsable' => $ongletChampCoresponsable,
'champ_soustraitant' => $ongletChampSoustraitant,
];
$this->Champ->create($data);
$success = false !== $this->Champ->save(null, ['atomic' => false]) && $success;
}
return $success;
}
/**
* Récupére en BDD les champs défini dans le formulaire en fonction des différents onglet
* Ajoute les valeurs par défault défini dans le formulaire
......@@ -671,7 +784,7 @@ class FormulairesController extends AppController {
];
if (empty($this->request->data)) {
if ($formulaireOLD === false && $this->request->params['action'] == 'edit') {
if ($formulaireOLD === false && $this->request->params['action'] === 'edit') {
$this->request->data = $this->Formulaire->find('first', [
'conditions' => [
'id' => $formulaire_id
......@@ -700,47 +813,49 @@ class FormulairesController extends AppController {
}
}
}
}
// valeur par défault
if ($this->request->params['action'] == 'add' && empty($this->request->data)) {
$fields['coresponsable'] = [
[
'Champ' => [
'type' => 'input',
'ligne' => 1,
'colonne' => 1,
'details' => '{"name":"nom_responsable_conjoint","placeholder":"Nom et prénom","label":"Nom et prénom du responsable conjoint","default":"","obligatoire":true,"repeat":false}'
]
],
[
'Champ' => [
'type' => 'input',
'ligne' => 3,
'colonne' => 1,
'details' => '{"name":"structure_responsable_conjointe","placeholder":"Raison sociale","label":"Raison sociale de la structure conjointe","default":"","obligatoire":true,"repeat":false}'
]
],
[
'Champ' => [
'type' => 'input',
'ligne' => 1,
'colonne' => 2,
'details' => '{"name":"email_responsable_conjoint","placeholder":"Adresse e-mail","label":"Adresse mail du responsable conjoint","default":"","obligatoire":true,"repeat":false}'
]
],
[
'Champ' => [
'type' => 'textarea',
'ligne' => 3,
'colonne' => 2,
'details' => '{"name":"adresse_structure_responsable_conjointe","placeholder":"Adresse postale","label":"Adresse de la structure conjointe","default":"","obligatoire":false,"repeat":false}'
]
]
];
// valeur par défault
// if ($this->request->params['action'] == 'add' && empty($this->request->data)) {
// $fields['coresponsable'] = [
// [
// 'Champ' => [
// 'type' => 'input',
// 'ligne' => 1,
// 'colonne' => 1,
// 'details' => '{"name":"nom_responsable_conjoint","placeholder":"Nom et prénom","label":"Nom et prénom du responsable conjoint","default":"","obligatoire":true,"repeat":false}'
// ]
// ],
// [
// 'Champ' => [
// 'type' => 'input',
// 'ligne' => 3,
// 'colonne' => 1,
// 'details' => '{"name":"structure_responsable_conjointe","placeholder":"Raison sociale","label":"Raison sociale de la structure conjointe","default":"","obligatoire":true,"repeat":false}'
// ]
// ],
// [
// 'Champ' => [
// 'type' => 'input',
// 'ligne' => 1,
// 'colonne' => 2,
// 'details' => '{"name":"email_responsable_conjoint","placeholder":"Adresse e-mail","label":"Adresse mail du responsable conjoint","default":"","obligatoire":true,"repeat":false}'
// ]
// ],
// [
// 'Champ' => [
// 'type' => 'textarea',
// 'ligne' => 3,
// 'colonne' => 2,
// 'details' => '{"name":"adresse_structure_responsable_conjointe","placeholder":"Adresse postale","label":"Adresse de la structure conjointe","default":"","obligatoire":false,"repeat":false}'
// ]
// ]
// ];
// }
$this->request->data['Formulaire']['form-container-formulaire'] = $fields['formulaire'];
$this->request->data['Formulaire']['form-container-coresponsable'] = $fields['coresponsable'];
$this->request->data['Formulaire']['form-container-soustraitant'] = $fields['soustraitant'];
}
$this->set(compact('fields'));
}
......
......@@ -194,6 +194,9 @@ msgstr "Champ d'information"
msgid "formulaire.btnLabel"
msgstr "Label"
msgid "formulaire.btnCondition"
msgstr "Ajouter une condition"
msgid "formulaire.champFichier"
msgstr "Fichier"
......@@ -251,4 +254,19 @@ msgstr "Avez-vous réalisé l'analyse d'impact (AIPD) ?"
msgid "formulaire.champDepotPia"
msgstr "Avez-vous déposer dans l'onglet annexe l'analyse d'impact (AIPD) ?"
###############################################################################
\ No newline at end of file
###############################################################################
msgid "formulaire.champIfTheField"
msgstr "Si le champ"
msgid "formulaire.champHasValue"
msgstr "a comme valeur"
msgid "formulaire.champThenTheField"
msgstr "alors le champ"
msgid "formulaire.champMustBe"
msgstr "doit être"
msgid "formulaire.champIfNot"
msgstr "sinon il sera"
\ No newline at end of file
......@@ -24,6 +24,43 @@ App::uses('AppModel', 'Model');
class Champ extends AppModel {
/**
* validate associations
*
* @var array
*
* @access public
* @created 27/03/2020
* @version V1.2.0
*/
public $validate = [
'formulaire_id' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'type' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'ligne' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'colonne' => [
'notBlank' => [
'rule' => ['notBlank']
]
],
'details' => [
'notBlank' => [
'rule' => ['notBlank']
]
]
];
/**
* hasOne associations
*
......
......@@ -480,6 +480,10 @@ class WebdpoFiche extends AppModel {
$Fiche->create($data['Fiche']);
$success = false !== $Fiche->save(null, ['atomic' => false]) && $success;
$newDataChamps = $this->checkDataConditons($data, $champs);
$data = Hash::extract($newDataChamps, 'data');
$champs = Hash::extract($newDataChamps, 'champs');
foreach ($champs as $champ) {
$details = json_decode(Hash::get($champ, 'Champ.details'));
if ($details->obligatoire == true) {
......@@ -785,6 +789,80 @@ class WebdpoFiche extends AppModel {
return $success;
}
/**
* On vérifie que les champs dans "data" soit en adéquation avec les conditions créées sur les champs
*
* @access protected
*
* @param $data
* @param $champs
* @return array
*
* @created 15/04/2020
* @version V1.2.0
* @author Théo GUILLON <theo.guillon@libriciel.coop>
*/
protected function checkDataConditons($data, $champs)
{
foreach ($champs as $key => $champ) {
$options = json_decode($champ['Champ']['details'], true);
if (isset($options['conditions']) && !empty($options['conditions'])) {
$fieldConditions = json_decode($options['conditions'], true);
foreach ($fieldConditions as $fieldCondition) {
if (isset($fieldCondition['ifTheField']) && isset($data[$this->alias][$fieldCondition['ifTheField']])) {
$valueCondition = '';
if (is_array($data[$this->alias][$fieldCondition['ifTheField']])) {
// champ checkbox, multi-select
if (in_array(substr($fieldCondition['hasValue'], -1), $data[$this->alias][$fieldCondition['ifTheField']])){
$valueCondition = $fieldCondition['mustBe'];
} else {
$valueCondition = $fieldCondition['ifNot'];
}
} else {
// input, textearea, radio, deroulant
if ($data[$this->alias][$fieldCondition['ifTheField']] == $fieldCondition['hasValue']) {
$valueCondition = $fieldCondition['mustBe'];
} else {
$valueCondition = $fieldCondition['ifNot'];
}
}
if ($valueCondition == 'hidden' && isset($data[$this->alias][$fieldCondition['thenTheField']])) {
// On supprimer le champ qui doit être cacher par la condition
unset($data[$this->alias][$fieldCondition['thenTheField']]);
if ($options['obligatoire'] == true) {
$options['obligatoire'] = false;
$champs[$key]['Champ']['details'] = json_encode($options);
}
}
} else {
// On supprimer le champ qui doit être cacher par la condition
unset($data[$this->alias][$fieldCondition['thenTheField']]);
if ($options['obligatoire'] == true) {
$options['obligatoire'] = false;
$champs[$key]['Champ']['details'] = json_encode($options);
}
}
}
}
}
$newDataChamps = [
'data' => $data,
'champs' => $champs
];
return ($newDataChamps);
}
public function beforeValidate($options = array()) {
// $this->data = $this->cleanupData($this->data);
return parent::beforeValidate($options);
......
......@@ -7,6 +7,8 @@ echo $this->Html->script([
echo $this->Html->css('/js/smalot-bootstrap-datetimepicker/css/bootstrap-datetimepicker.min');
$calendrier = [];
$conditions = [];
$col = 1;
$line = 1;
?>
......@@ -35,6 +37,11 @@ $line = 1;
}
$options = json_decode($value['Champ']['details'], true);
if (isset($options['conditions']) && !empty($options['conditions'])) {
$fieldConditions = json_decode($options['conditions'], true);
$conditions = array_merge($conditions, $fieldConditions);
}
?>
<div class="row row35">
......@@ -139,7 +146,7 @@ $line = 1;
],
'options' => $options['options'],
'required' => $options['obligatoire'],
'class' => 'usersDeroulant transformSelect form-control',
'class' => 'transformSelect form-control',
'empty' => true,
'placeholder' => false,
'data-placeholder' => ' '
......@@ -209,6 +216,7 @@ $line = 1;
<!-- Fin onglet Formulaire -->
<script type="text/javascript">