From 3c4f9138ae3fe491f92fab3e26e1955555a21faf Mon Sep 17 00:00:00 2001
From: Etienne Pallier
config/bootstrap.php: Impossible de charger le fichier de configuration des champs matériels (".CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.".yml)");
+ echo("
- soit ce fichier n'est pas accessible en lecture par le serveur web (attention, il faut aussi qu'il soit accessible en écriture)");
+ echo("
- soit il n'existe pas => dans ce cas, créez le en faisant une copie du fichier de configuration par défaut :");
+ echo("
cd ".CONFIG);
+ echo("
cp $config_matos_full_file_name_default $config_matos_full_file_name");
+ echo("
chown webserver_user_name $config_matos_full_file_name");
+ echo("
chmod 600 $config_matos_full_file_name");
+ echo("
(si vous ne voulez pas faire le chown, faite plutot un chmod 666, moins propre, mais marche aussi)");
+ die();
}
// Load an environment local configuration file.
diff --git a/src/Controller/ConfigurationFieldsController.php b/src/Controller/ConfigurationFieldsController.php
new file mode 100644
index 0000000..f50c75e
--- /dev/null
+++ b/src/Controller/ConfigurationFieldsController.php
@@ -0,0 +1,308 @@
+is_authorized_action[]) as $a) if ($a != 'display') unset($this->is_authorized_action[$a]);
+ $this->is_authorized_action = [];
+
+ // admin (+) only
+ $this->setAuthorizationsForAction('index', -1, ['admin'=>0, 'super'=>0]);
+ $this->setAuthorizationsForAction('view', -1, ['admin'=>0, 'super'=>0]);
+ $this->setAuthorizationsForAction('edit', -1, ['admin'=>0, 'super'=>0]);
+ $this->setAuthorizationsForAction('resetToDefault', -1, ['admin'=>0, 'super'=>0]);
+ // tous
+ //$this->setAuthorizationsForAction('index', 0);
+ // Superadmin only :
+ //$this->setAuthorizationsForAction('index', -1, ['super'=>0]);
+
+ }
+
+ public function index() {
+ $this->view();
+ }
+
+ public function view() {
+
+ $this->edit(true);
+ // Lecteurs configurés : 'default', 'yaml'
+ //debug(Configure::configured());
+
+ //$fields = Configure::readOrFail('MANDATORY_FIELDS_FOR_LOT'.$lot_num);
+ /*
+ $fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS');
+ $this->set(compact('fields'));
+ */
+ }
+
+ public function resetToDefault() {
+ $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml';
+ $config_mandatory_fields_file_name_default = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.default.yml';
+
+ $config_default = Yaml::parse(file_get_contents($config_mandatory_fields_file_name_default)); //parse le fichier
+ $config_default_as_yaml = Yaml::dump($config_default); //remet en yaml
+ if (! file_put_contents($config_mandatory_fields_file_name, $config_default_as_yaml) )
+ throw new \ErrorException("Impossible de remettre la configuration des champs de matériel aux valeurs par défaut - le fichier de config $config_mandatory_fields_file_name n'est pas accessible en écriture");
+
+ $this->Flash->success("La configuration des champs de matériel a bien été réinitialisée aux valeurs par défaut");
+ return $this->redirect(['action' => 'view']);
+ }
+
+
+ public function edit($READONLY=false) {
+
+ $contact = new ConfigurationFieldsForm();
+ //debug($contact);
+
+ // - En mode POST
+ if ($this->request->is('post')) {
+ /*
+ * We use the execute() method to run our form’s _execute() method only when the data is valid,
+ * and set flash messages accordingly.
+ * We could have also used the validate() method to only validate the request data:
+ * $isValid = $form->validate($this->request->getData());
+ */
+ //debug($this->request->getData());
+
+ // - OK
+ if ($contact->execute($this->request->getData())) {
+ $fieldsets = $this->request->getData();
+ //debug($data);
+ $contact->setData($fieldsets);
+
+ // On sauvegarde le contenu de $fieldsets dans le fichier de config (array => yaml)
+
+ //debug($contact);
+ // See : https://book.cakephp.org/3/en/development/configuration.html#writing-configuration-data
+ /*
+ Configure::write('Company.name','Pizza, Inc.');
+ Configure::write('Company.slogan','Pizza for your body and soul');
+ // idem :
+ Configure::write('Company', [
+ 'name' => 'Pizza, Inc.',
+ 'slogan' => 'Pizza for your body and soul'
+ ]);
+ */
+ //$data1 = Configure::read('MANDATORY_AND_READONLY_FIELDS');
+ //debug($data1);
+ /*
+ Configure::write('MANDATORY_AND_READONLY_FIELDS',$data);
+ $data2 = Configure::read('MANDATORY_AND_READONLY_FIELDS');
+ */
+ //debug($data2);
+ //$name = $contact->getData('name');
+ /* NE MARCHE PAS, WHY ???
+ $config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields';
+ if ( Configure::dump($config_mandatory_fields_file_name, 'my_yaml', ['MANDATORY_AND_READONLY_FIELDS']) )
+ $this->Flash->success("La configuration des champs matériels a bien été sauvegardée");
+ */
+ //$config_mandatory_fields_file_name = CONFIG.DS.'app_labinvent_mandatory_fields'.'.yml';
+ $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml';
+ // Symfony YAML component : https://symfony.com/doc/current/components/yaml.html
+ /*
+ $array = Yaml::parse(file_get_contents($config_mandatory_fields_file_name)); //parse le fichier
+ debug($array);
+ $res = Yaml::dump($array); //remet en yaml
+ */
+ $fieldsets_new = [];
+ $fieldsets_new['MANDATORY_AND_READONLY_FIELDS']=$fieldsets;
+ //debug($fieldsets_new);
+
+ $fieldsets_as_yaml = Yaml::dump($fieldsets_new); //remet en yaml
+ //debug($res); exit;
+ if (! file_put_contents($config_mandatory_fields_file_name, $fieldsets_as_yaml) )
+ throw new \ErrorException("Impossible d'enregistrer la configuration des champs de matériel - le fichier de config $config_mandatory_fields_file_name n'est pas accessible en écriture");
+ $this->Flash->success("La configuration des champs de matériel a bien été sauvegardée");
+ return $this->redirect(['action' => 'view']);
+ }
+
+ // - KO
+ else {
+ // Once a form has been validated you can retrieve the errors from it:
+ $errors = $form->getErrors(); // $form->errors(); // prior to 3.7.0
+ debug($errors);
+ /* $errors contains
+ [
+ 'email' => ['A valid email address is required']
+ ]
+ */
+ $this->Flash->error("La configuration n'a pas pu être enregistrée");
+ }
+ }
+
+ // - En mode GET (ou POST avec erreur)
+
+ if ($this->request->is('get')) {
+ /*
+ $contact->setData([
+ 'name' => 'John Doe',
+ 'email' => 'john.doe@example.com'
+ ]);
+ */
+ }
+
+ $this->set('contact', $contact);
+
+ $fieldsets = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS');
+ $this->set(compact('READONLY', 'fieldsets'));
+
+ } // edit()
+
+
+ public function OLD_edit($READONLY=false)
+ {
+ $contact = new ConfigurationFieldsForm();
+ //debug($contact);
+
+ // - En mode POST
+ if ($this->request->is('post')) {
+ /*
+ * We use the execute() method to run our form’s _execute() method only when the data is valid,
+ * and set flash messages accordingly.
+ * We could have also used the validate() method to only validate the request data:
+ * $isValid = $form->validate($this->request->getData());
+ */
+ //debug($this->request->getData());
+
+ // - OK
+ if ($contact->execute($this->request->getData())) {
+ $fieldsets = $this->request->getData();
+ //debug($data);
+ $contact->setData($fieldsets);
+
+ /*
+ * 1) On retouche $fieldsets pour qu'il puisse être sauvegardé au format fichier texte (yaml) :
+ *
+ * Ex:
+ 'designation' => [
+ 'selected' => '0',
+ 'labl' => 'commentaire',
+ 'roles' => [
+ (int) 0 => 'Responsable',
+ (int) 1 => 'Administration'
+ ]
+ ],
+ *
+ * - '.selected' : si = 0 => on préfixe le nom du champ par "OFF_"
+ * => 'OFF_designation'
+ * - '.labl' : on l'ajoute entre parenthèse à la suite du nom du champ
+ * => 'OFF_designation (commentaire)'
+ * - '.roles' : on les ajoute entre parenthèse à la fin du nom du champ =>
+ * => 'OFF_designation (commentaire) (sauf Responsable, Administration)'
+ */
+ $fieldsets_new = [];
+ $fieldsets_new['MANDATORY_AND_READONLY_FIELDS']=[];
+ //$fn = &$fieldsets_new['MANDATORY_AND_READONLY_FIELDS'];
+ foreach ($fieldsets as $fieldset_name=>$fields) {
+ $fieldsets_new['MANDATORY_AND_READONLY_FIELDS'][$fieldset_name] = [];
+ foreach ($fields as $field_name=>$attributes) {
+ $field_name_new = $field_name;
+ // - selected
+ if (! $attributes['selected'] )
+ $field_name_new = 'OFF_'.$field_name_new;
+ // - labl
+ if ($attributes['labl'])
+ $field_name_new .= ' ('. $attributes['labl'] .')';
+ // - roles
+ if (isset($attributes['except_roles']) && $attributes['except_roles'])
+ $field_name_new .= ' (sauf '. implode(',',$attributes['except_roles']) .')';
+ //debug($field_name_new);
+ $fieldsets_new['MANDATORY_AND_READONLY_FIELDS'][$fieldset_name][] = $field_name_new;
+ }
+ }
+ //debug($fieldsets_new); exit;
+
+ // 2) On sauvegarde le contenu de $fieldsets dans le fichier de config (array => yaml)
+
+ //debug($contact);
+ // See : https://book.cakephp.org/3/en/development/configuration.html#writing-configuration-data
+ /*
+ Configure::write('Company.name','Pizza, Inc.');
+ Configure::write('Company.slogan','Pizza for your body and soul');
+ // idem :
+ Configure::write('Company', [
+ 'name' => 'Pizza, Inc.',
+ 'slogan' => 'Pizza for your body and soul'
+ ]);
+ */
+ //$data1 = Configure::read('MANDATORY_AND_READONLY_FIELDS');
+ //debug($data1);
+ /*
+ Configure::write('MANDATORY_AND_READONLY_FIELDS',$data);
+ $data2 = Configure::read('MANDATORY_AND_READONLY_FIELDS');
+ */
+ //debug($data2);
+ //$name = $contact->getData('name');
+ /* NE MARCHE PAS, WHY ???
+ $config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields';
+ if ( Configure::dump($config_mandatory_fields_file_name, 'my_yaml', ['MANDATORY_AND_READONLY_FIELDS']) )
+ $this->Flash->success("La configuration des champs matériels a bien été sauvegardée");
+ */
+ //$config_mandatory_fields_file_name = CONFIG.DS.'app_labinvent_mandatory_fields'.'.yml';
+ $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml';
+ // Symfony YAML component : https://symfony.com/doc/current/components/yaml.html
+ /*
+ $array = Yaml::parse(file_get_contents($config_mandatory_fields_file_name)); //parse le fichier
+ debug($array);
+ $res = Yaml::dump($array); //remet en yaml
+ */
+ $fieldsets_new_as_yaml = Yaml::dump($fieldsets_new); //remet en yaml
+ //debug($res); exit;
+ if ( file_put_contents($config_mandatory_fields_file_name, $fieldsets_new_as_yaml) )
+ $this->Flash->success("La configuration des champs matériels a bien été sauvegardée");
+ return $this->redirect(['action' => 'view']);
+ }
+
+ // - KO
+ else {
+ // Once a form has been validated you can retrieve the errors from it:
+ $errors = $form->getErrors(); // $form->errors(); // prior to 3.7.0
+ debug($errors);
+ /* $errors contains
+ [
+ 'email' => ['A valid email address is required']
+ ]
+ */
+ $this->Flash->error("La configuration n'a pas pu être enregistrée");
+ }
+ }
+
+ // - En mode GET (ou POST avec erreur)
+
+ if ($this->request->is('get')) {
+ /*
+ $contact->setData([
+ 'name' => 'John Doe',
+ 'email' => 'john.doe@example.com'
+ ]);
+ */
+ }
+
+ $this->set('contact', $contact);
+
+ $fieldsets = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS');
+ $this->set(compact('READONLY', 'fieldsets'));
+
+ } // edit()
+
+
+
+} // end of class
\ No newline at end of file
diff --git a/src/Controller/MaterielsController.php b/src/Controller/MaterielsController.php
index f9c026d..54b802d 100755
--- a/src/Controller/MaterielsController.php
+++ b/src/Controller/MaterielsController.php
@@ -1913,8 +1913,40 @@ class MaterielsController extends AppController {
}
*/
$recommended_fields = $this->Materiels->getRecommendedFieldsForMaterielStatus($materiel->status);
- foreach ($recommended_fields as $fname => $msg) {
-
+ //debug($recommended_fields);
+ /*
+ * Ex :
+ [
+ 'etiquette' => [
+ 'selected' => '1',
+ 'comment' => 'd'imprimer l'étiquette associée et de la coller sur le matériel',
+ 'roles' => ''
+ ],
+ 'numero_inventaire_organisme' => [
+ 'selected' => '1',
+ 'comment' => 'de renseigner le champ 'N° inventaire comptable/tutelles _Organisme_'',
+ 'roles' => ''
+ ],
+ 'DOC_BC' => [
+ 'selected' => '1',
+ 'comment' => 'd'ajouter le Bon de Commande',
+ 'roles' => ''
+ ],
+ 'DOC_BL' => [
+ 'selected' => '1',
+ 'comment' => 'd'ajouter le Bon de Livraison',
+ 'roles' => ''
+ ],
+ 'DOC_FACTURE' => [
+ 'selected' => '1',
+ 'comment' => 'd'ajouter la Facture',
+ 'roles' => ''
+ ]
+ */
+ //foreach ($recommended_fields as $fname => $msg) {
+ //foreach ($recommended_fields as $fname => $attributes) {
+ foreach ( array_keys($recommended_fields) as $fname ) {
+
//debug($fname);
// - Documents attachés (champs virtuels)
// DOC_DEVIS, DOC_BC, ...
@@ -1937,8 +1969,8 @@ class MaterielsController extends AppController {
}
// Les champs restants sont les champs manquants => message flash de rappel
- foreach ($recommended_fields as $fname => $reminder_msg)
- $this->Flash->set("Ce matériel est '".$entity->getNiceStatus()."' mais n'oubliez pas $reminder_msg");
+ foreach ($recommended_fields as $fname => $attributes)
+ $this->Flash->set("Ce matériel est '".$entity->getNiceStatus()."' mais n'oubliez pas ".$attributes['comment']);
} // view
@@ -1974,7 +2006,6 @@ class MaterielsController extends AppController {
// uniquement à cause de parent::add_or_edit() :
$entity_name=null, array $associated_entities=[], $with_parent=false) {
- //debug("ici"); exit;
$this->myDebug("step 3: MaterielsController.add_or_edit()");
$IS_EDIT = !$IS_ADD;
@@ -2080,72 +2111,11 @@ class MaterielsController extends AppController {
$materiel->numero_laboratoire = null;
}
}
- //debug($materiel); exit;
- /*
- // ADD
- if ($IS_ADD) {
- // 1) on crée un materiel vide
- $materiel = $this->Materiels->newEntity();
- // - add_by_copy : COPIE de materiel (on a cliqué sur "Copier ce materiel") => id passé en argument
- if (isset($this->request->getAttribute('params')['pass'][0])) {
- // On récupère le materiel à copier et on le copie dans $materiel
- /S
- $materiel_to_copy = $this->Materiels->get($this->request->getAttribute('params')['pass'][0]);
- $materiel_to_copy = $materiel_to_copy->toArray();
- S/
- $materiel_to_copy = $this->e->toArray();
- //var_dump($materiel_to_copy);
- ///foreach ($materiel_to_copy as $key=>$value) $materiel->$key = $value;
- // IMPORTANT: validate=False car sinon, les données sont validées avant la copie,
- // et le numero_laboratoire est vu comme invalide car déjà utilisé et doit etre unique !!!
- // et on a pour résultat : "le matériel n'a pas pu être ajouté" (sans savoir pourquoi !!!)
- $materiel = $this->Materiels->patchEntity($materiel, $materiel_to_copy, ['validate' => false]);
- //TODO: On pourrait traiter les erreurs de validation déjà ici
- if ($materiel->errors()) {
- // traitement
- }
- // Du coup, on supprime le champ numero_laboratoire car il va être généré automatiquement
- unset($materiel->numero_laboratoire);
- // IMPORTANT: on ne doit pas laisser l'id égal à celui du matériel copié !!! il en faut un nouveau
- $materiel->id = NULL;
- //$materiel->id = False;
- //unset($materiel->id);
-
- /S
- $attribute="[original]";
- $materiel->$attribute = [];
- S/
- //$materiel->id = FALSE;
- //$materiel->'[new]' => true,
- }
- // - NOUVEAU materiel (on a cliqué sur "Nouveau materiel")
- else {
- //$materiel = $this->Materiels->newEntity();
- /S (EP 20200505 plus nécessaire car on utilise désormais NULL)
- // Set default values : "N/A"
- $materiel->groupes_thematique_id = 1;
- $materiel->groupes_metier_id = 1;
- $materiel->site_id = 9;
- S/
- }
- }
- // EDIT
- else {
- /S
- $this->log("Edit a doc1 !", 'debug');
- Log::write('debug',"Edit a doc2 !");
- $this->dlog("Edit a doc1 !");
- S/
- $materiel = $this->Materiels->get($id, [
- 'contain' => [] // load associated entities
- ]);
- //$this->myDebug($materiel);
- //debug($materiel);
- }
- */
- /* SI POST...
+ /*
+ * SI POST...
+ *
* Les données ont été saisies et postées
* On va donc les sauvegarder (si ok)
*/
@@ -2154,123 +2124,32 @@ class MaterielsController extends AppController {
$authorized_actions = $IS_ADD ? ['post'] : ['post','patch','put'];
if ( $this->request->is($authorized_actions) ) {
- //debug($this->request->getData());
- //exit;
-
- /*
- // ADD
- // Nouveau materiel saisi et posted
- ($is_add && $this->request->is('post'))
-
- ||
-
- // EDIT
- // materiel modifié et posted
- ( (!$is_add) && $this->request->is(['patch','post','put']) )
- */
+ //debug($this->request->getData()); exit;
// (1) On remplit $materiel avec les données de ce materiel
$materiel = $this->Materiels->patchEntity($materiel, $this->request->getData());
-
- /*
- // AVIRER
- // BUGFIX temporaire pour php5 !!!
- if ($this->isLabinventDebugMode()) {
- $d2 = $materiel->date_reception;
- $d1 = $materiel->date_acquisition;
- debug("d1 achat avant:"); debug($d1);
- debug("d2 recep avant:"); debug($d2);
- /S
- $tz = new \DateTimeZone('Europe/Paris');
- $d1 = new \DateTime(strtr($d1,'/','-'),$tz);
- $d2 = new \DateTime(strtr($d2,'/','-'),$tz);
- debug("d1 achat après:"); debug($d1);
- debug("d2 recep après:"); debug($d2);
- S/
- if ($d2 < $d1) debug("d2 < d1 !!!");
- // $d2 > $d1 oui mais pas trop...
- $diff = $d2->diff($d1);
- //debug($diff->y);
- debug("diff:"); debug($diff);
- debug("diff->y:"); debug($diff->y);
- debug("diff->days:"); debug($diff->days);
- exit;
- }
- // FIN BUGFIX
- */
-
- // ADD : Set the user_id from the session.
- //$materiel->user_id = $this->Auth->user('id');
- // EDIT : Added: Disable modification of user_id.
- //'accessibleFields' => ['user_id' => false]
-
- /* (EP 7/12/20 : déjà fait dans la vue, donc inutile !!!)
- // (2) Si l'utilisateur courant est un "administratif" => le mettre comme gestionnaire du materiel
- // (tout ça pour ça !!! Faudra réduire ce bazar !)
- $current_user_name = $_SESSION['Auth']['User']['sn'][0];
- if (in_array(
- $current_user_name,
- $usersTable
- ->find('list', [
- 'keyField' => 'id',
- 'valueField' => 'nom'
- ])
- ->where([
- 'role =' => 'Administration'
- ])
- ->toArray()
- )) {
- $materiel->gestionnaire_id = $usersTable
- ->find()
- ->where([
- 'nom' => $current_user_name
- ])
- ->first()->id;
- }
- */
-
-
+ //debug($materiel);
+
/*
* \AV1 : Attributs OBLIGATOIRES
* On définit les infos obligatoires et on vérifie qu'elles sont bien présentes dans le POST
*/
- /*
- // Attributs obligatoires pour la phase COMMANDE
- //$LOT1 = $this->Materiels->MANDATORY_FIELDS_FOR_LOT1;
- $LOT1 = $this->Materiels->getMandatoryFieldsForLot(1);
-
- // Attributs obligatoires pour la phase VALIDATION (livré et payé)
- //$LOT2 = $this->Materiels->MANDATORY_FIELDS_FOR_LOT2;
- $LOT2 = $this->Materiels->getMandatoryFieldsForLot(2);
-
- //TODO 202109
- // Seulement si prix > 10K€ : exiger la facture jointe et le n° série
- if ($materiel->prix_ht > 10000) {
- //$LOT2[] = 'facture jointe';
- $LOT2['numero_serie'] = 'S/N';
- }
- // LOT2 = LOT1 + LOT2;
- ////$LOT2 = array_merge($LOT1, $LOT2);
- //debug($LOT2);exit;
- // Champs obligatoires = LOT1 si CREATED, LOT2 sinon (>CREATED, c'est à dire VALIDATED ou plus)
- $mandatory_fields = ($materiel->status == 'CREATED') ? $LOT1 : $LOT2;
- //debug($mandatory_fields); exit;
- */
//$mandatory_fields = MaterielsTable::getMandatoryFieldsForMaterielStatus($materiel->status);
$mandatory_fields = $this->Materiels->getMandatoryFieldsForMateriel($materiel);
+ //debug($mandatory_fields);
//$mandatory_fields = $this->Materiels->getMandatoryFieldsForMaterielStatus($materiel->status);
- //debug($mandatory_fields); exit;
$verb = $IS_ADD ? "ajouté" : "modifié";
// On vérifie que les infos obligatoires sont présentes
// Si au moins un champ obligatoire est nul ou vide => ERROR
- $ALL_MANDATORY_FIELDS_FOR_GIVEN = true;
+ $ALL_MANDATORY_FIELDS_GIVEN = true;
//foreach ($mandatory_fields as $fname => $fval) {
//print_r($materiel);
- foreach ($mandatory_fields as $fname=>$fname_nice) {
-
+ //foreach ($mandatory_fields as $fname=>$fname_nice) {
+ foreach ($mandatory_fields as $fname=>$attributes) {
+
/*
* Champs obligatoires à ignorer :
* - champs virtuels (n'existent pas physiquement) => DOC_XXX (DOC_DEVIS, DOC_BC, ...)
@@ -2282,7 +2161,7 @@ class MaterielsController extends AppController {
//if ( in_array($fname, ['DOC_DEVIS', 'fournisseur_id', 'etiquette', 'numero_inventaire_organisme']) ) continue;
if ($materiel->$fname === null || $materiel->$fname == '') {
- $ALL_MANDATORY_FIELDS_FOR_GIVEN = false;
+ $ALL_MANDATORY_FIELDS_GIVEN = false;
/* (EP 2020 03)
* Ce genre de ligne ($this->Flash->...) affichant un message flash en haut de page,
* ne fonctionnait plus à cause de bootstrap (css).
@@ -2292,7 +2171,8 @@ class MaterielsController extends AppController {
* de bootstrap, ou bootsrap-ui, ou cakephp..., à surveiller donc)
*/
//$msgError1 = "Le champ suivant est obligatoire : ".$fname_nice.' du matériel';
- $error_msg = "Le champ suivant est obligatoire : ".$fname_nice;
+ //$error_msg = "Le champ suivant est obligatoire : ".$fname_nice;
+ $error_msg = "Le champ suivant est obligatoire : ".$attributes['comment'];
/////debug($msgError1);
$this->Flash->error($error_msg);
/* MARCHE PAS POURQUOI ?
@@ -2307,10 +2187,11 @@ class MaterielsController extends AppController {
///////////////$this->Flash->error(__("Le matériel n'a pas pu être $verb"));
//return false;
break;
- }
- }
+ } // si champ obligatoire pas rempli
+
+ } // foreach $mandatory_fields
- if ($ALL_MANDATORY_FIELDS_FOR_GIVEN) {
+ if ($ALL_MANDATORY_FIELDS_GIVEN) {
// (3) On l'ajoute en BD, on envoie un email, et on affiche ok sur page accueil
//$verb = $IS_ADD ? "ajouté" : "modifié";
@@ -2342,7 +2223,8 @@ class MaterielsController extends AppController {
foreach ($materiel->getErrors() as $f=>$e)
foreach($e as $k=>$v) $this->Flash->error(__($v.' : '.$f));
- }
+ } // save KO
+
else {
//debug($this->getCurrentEntity()); exit;
//debug($this->Materiels->current_entity); exit;
@@ -2380,7 +2262,7 @@ class MaterielsController extends AppController {
'action' => 'view',
$id
]);
- }
+ } // save KO
} // $ALL_MANDATORY_FIELDS_FOR_GIVEN
@@ -2388,11 +2270,12 @@ class MaterielsController extends AppController {
-
- /* SINON (PAS POST)
+ /* SINON (GET, PAS POST)
* C'est la première fois qu'on vient sur cette vue,
* donc on va préparer le formulaire de saisie)
*/
+ //debug($materiel); exit;
+
/*
@@ -2709,6 +2592,7 @@ class MaterielsController extends AppController {
'ARCHIVED' => 'ARCHIVED'
];
$entity = $materiel;
+ //debug($entity);
$this->set(compact(
'IS_ADD',
'mail_responsable',
@@ -2738,8 +2622,10 @@ class MaterielsController extends AppController {
'gestionnaires'
));
-
- $this->set('readonlyFields', $this->getUneditableFieldsForMaterielStatus($materiel->status));
+ $readonlyFields = $this->getUneditableFieldsForMaterielStatus($materiel->status);
+ $this->set(compact('readonlyFields'));
+ //debug($materiel->status);
+ //debug($readonlyFields);
//$this->set('readonlyFields', $IS_ADD ? [] : $this->getUneditableFieldsForMaterielStatus($materiel->status));
//debug($this->Materiels->getUneditableFieldsForMaterielStatus($status)); exit;
//$this->set('readonlyFields', $IS_ADD ? [] : $this->Materiels->getUneditableFieldsForMaterielStatus($materiel->status));
@@ -2767,11 +2653,12 @@ class MaterielsController extends AppController {
if ($this->USER_IS_SUPERADMIN()) return [];
$uneditable_fields = $this->Materiels->getUneditableFieldsForMaterielStatus($materiel_status);
- foreach ($uneditable_fields as $fname=>$except_list) {
+ //foreach ($uneditable_fields as $fname=>$except_list) {
+ foreach ($uneditable_fields as $fname=>$attributes) {
// S'il y a une exception, voir si elle concerne le USER courant, sinon supprimer ce champ $fname
- if ($except_list) {
+ if ($attributes['except_roles']) {
//debug($except_list);
- if ($this->currentUserRoleInList($except_list)) unset($uneditable_fields[$fname]);
+ if ($this->currentUserRoleInList($attributes['except_roles'])) unset($uneditable_fields[$fname]);
//debug("remove $fname");
}
}
@@ -3051,10 +2938,11 @@ class MaterielsController extends AppController {
// Attributs obligatoires pour la phase COMMANDE (LOT1)
$mandatoryFields = $this->Materiels->getMandatoryFieldsForLot(1);
+ //debug($mandatoryFields);
$ACTION = 'ordonner la commande de';
// Si au moins un champ obligatoire est nul ou vide => ERROR
- foreach ($mandatoryFields as $fname => $fnicename) {
+ foreach ($mandatoryFields as $fname => $attributes) {
// Doc attaché obligatoire ? (champ virtuel)
//if (strtoupper($fname) == 'DOC_DEVIS') {
@@ -3085,7 +2973,7 @@ class MaterielsController extends AppController {
$fval = $materiel->$fname;
if ($fval === null || $fval == '') {
//$msgError1 = "Pour $ACTION ce matériel, le champ suivant ne doit pas être vide : ".$fnicename.' du matériel';
- $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $fnicename);
+ $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $attributes['comment']);
$this->Flash->error($error_msg);
// Utile ??? (plante les tests)
////$this->e->setError($fname, 'Ce champ ne doit pas être vide');
@@ -3108,6 +2996,7 @@ class MaterielsController extends AppController {
if ($newStatus == 'VALIDATED') {
// Attributs obligatoires pour la phase VALIDATION (livré et payé) (LOT2)
$mandatoryFields = $this->Materiels->getMandatoryFieldsForLot(2);
+ //$mandatoryFields = $this->Materiels->getCategoryFieldsForLot('MANDATORY_FIELDS_FOR_LOT', 2)
//$mandatoryFields = $this->Materiels->MANDATORY_FIELDS_FOR_LOT2;
//debug($mandatoryFields);exit;
/*
@@ -3142,7 +3031,7 @@ class MaterielsController extends AppController {
*/
// Si au moins un champ obligatoire est nul ou vide => ERROR
- foreach ($mandatoryFields as $fname => $fnicename) {
+ foreach ($mandatoryFields as $fname => $attributes) {
$ACTION = 'valider';
@@ -3184,7 +3073,8 @@ class MaterielsController extends AppController {
* de bootstrap, ou bootsrap-ui, ou cakephp..., à surveiller donc)
*/
//$msgError1 = "Pour $ACTION ce matériel, le champ suivant ne doit pas être vide : ".$fnicename.' du matériel';
- $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $fnicename);
+ //debug($fname);
+ $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $attributes['comment']);
$this->Flash->error($error_msg);
//debug($error_msg);
diff --git a/src/Controller/PagesController.php b/src/Controller/PagesController.php
index 7cc24eb..d4038d7 100755
--- a/src/Controller/PagesController.php
+++ b/src/Controller/PagesController.php
@@ -70,6 +70,7 @@ class PagesController extends AppController
{
$this->myDebug("step 0A (specific): PagesController.initialize()");
parent::initialize();
+ $this->modelClass = false;
// On autorise l'action add SANS authentification (unauthenticated)
//$this->Auth->allow(['add']);
//$this->LdapAuth->allow(['display']);
diff --git a/src/Controller/StatsController.php b/src/Controller/StatsController.php
index 8df56a9..0da3aa3 100644
--- a/src/Controller/StatsController.php
+++ b/src/Controller/StatsController.php
@@ -61,7 +61,7 @@ class StatsController extends AppController
'nice_name'=>"Temps connexion cumulé (h)", 'f'=>'getHourMnSecForDuration'],
'connex_nb'=>['nice_name'=>"Nb connexions"],
'connexDurAvg'=>[
- 'nice_name'=>"Durée connexion moyenne (sur année)", 'f'=>'getHourMnSecForDuration']
+ 'nice_name'=>"Durée connexion moyenne (sur 1 an)", 'f'=>'getHourMnSecForDuration']
],
['Users'],
false, false,
diff --git a/src/Controller/SurCategoriesController.php b/src/Controller/SurCategoriesController.php
index a55cbf5..ca62d75 100755
--- a/src/Controller/SurCategoriesController.php
+++ b/src/Controller/SurCategoriesController.php
@@ -256,6 +256,8 @@ class SurCategoriesController extends AppController
$surCategory = $this->SurCategories->get($id, [
'contain' => []
]);
+
+ // En mode POST
if ($this->request->is([
'patch',
'post',
@@ -274,10 +276,14 @@ class SurCategoriesController extends AppController
$this->Flash->error(__('Le domaine n\'a pas pu être édité.'));
}
}
+
+ // En mode GET (ou alors POST après une erreur)
$this->set(compact('surCategory'));
+ /* (EP) inutile sauf si json
$this->set('_serialize', [
'surCategory'
]);
+ */
}
/**
diff --git a/src/Form/ConfigurationFieldsForm.php b/src/Form/ConfigurationFieldsForm.php
new file mode 100644
index 0000000..2e23f0e
--- /dev/null
+++ b/src/Form/ConfigurationFieldsForm.php
@@ -0,0 +1,47 @@
+$val) debug($fname);
+
+ return $schema
+ ->addField('name', 'string')
+ ->addField('email', ['type' => 'string'])
+ ->addField('body', ['type' => 'text']);
+ }
+ */
+
+ /*
+ public function validationDefault(Validator $validator)
+ {
+ $validator->add('name', 'length', [
+ 'rule' => ['minLength', 5],
+ 'message' => 'A name is required'
+ ])->add('email', 'format', [
+ 'rule' => 'email',
+ 'message' => 'A valid email address is required',
+ ]);
+
+ return $validator;
+ }
+ */
+
+ protected function _execute(array $data)
+ {
+ // Send an email.
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/Model/Table/MaterielsTable.php b/src/Model/Table/MaterielsTable.php
index f8751d0..de359d2 100755
--- a/src/Model/Table/MaterielsTable.php
+++ b/src/Model/Table/MaterielsTable.php
@@ -252,60 +252,84 @@ class MaterielsTable extends AppTable
* - LOT0 total = [] + LOT0
* - LOT1 total = LOT0 + LOT1
* - LOT2 total = LOT1 + LOT2
+ *
+ * Algo RECURSIF
*/
+ public static function getCategoryFieldsForLot($categ, $lot_num, $categ_initial=null) {
+ //debug($lot_num);
+ // ex: $categ = RECOMMENDED_FIELDS_AFTER_LOT
+ //if ($lot_num < 0) return $categ_initial ? Configure::readOrFail('UNEDITABLE_FIELDS') : [];
+ if ($lot_num < 0) return $categ_initial ? Configure::readOrFail("MANDATORY_AND_READONLY_FIELDS.$categ_initial") : [];
+
+ // Recursive call
+ $base_fields = self::getCategoryFieldsForLot($categ, $lot_num-1, $categ_initial);
+ $base_fields = self::removeUnselectedFieldsFrom($base_fields);
+ //debug($base_fields);
+
+ //$new_fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS.RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num);
+ $new_fields = Configure::readOrFail("MANDATORY_AND_READONLY_FIELDS.$categ".$lot_num);
+ $new_fields = self::removeUnselectedFieldsFrom($new_fields);
+ //debug($new_fields);
+
+ //debug($new_fields);
+ return array_merge($base_fields, $new_fields);
+ }
+
+
+
+ public static function removeUnselectedFieldsFrom($fields) {
+ /*
+ * Exemple :
+ Before remove :
+ {
+ designation: { selected: '0', comment: commentaire, roles: '' },
+ description: { selected: '0', comment: autre, roles: '' },
+ nom_responsable: { selected: '1', comment: 'nom du responsable',
+ }
+ After remove :
+ {
+ nom_responsable: { selected: '1', comment: 'nom du responsable',
+ }
+ */
+ //$fields_selected = [];
+ foreach ($fields as $field_name => $attributes) {
+ if ( $field_name=='fieldset_comment' || !$attributes['selected'] ) unset($fields[$field_name]);
+ }
+ return $fields;
+ }
+
public static function getMandatoryFieldsForLot($lot_num) {
+ return self::getCategoryFieldsForLot('MANDATORY_FIELDS_FOR_LOT', $lot_num);
/*
$specific_constant_name = "MANDATORY_FIELDS_FOR_LOT1_".self::getLabName();
$mandatory_fields_lot1 = defined($specific_constant_name) ? constant($specific_constant_name) : MANDATORY_FIELDS_FOR_LOT1;
return $mandatory_fields_lot1;
*/
+ /*
if ($lot_num < 0) return [];
$base_fields = self::getMandatoryFieldsForLot($lot_num-1);
$new_fields = Configure::readOrFail('MANDATORY_FIELDS_FOR_LOT'.$lot_num);
//debug($new_fields);
return array_merge($base_fields, $new_fields);
+ */
}
+ // RECURSIF
public static function getRecommendedFieldsForLot($lot_num) {
+ return self::getCategoryFieldsForLot('RECOMMENDED_FIELDS_AFTER_LOT', $lot_num);
+ /*
if ($lot_num < 0) return [];
$base_fields = self::getRecommendedFieldsForLot($lot_num-1);
- $new_fields = Configure::readOrFail('RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num);
+ $new_fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS.RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num);
//debug($new_fields);
return array_merge($base_fields, $new_fields);
+ */
}
-
- // (EP 2021 10)
- public static function list_to_dict($uneditable_fields) {
- $dict = [];
- foreach ($uneditable_fields as $f) {
- $except_roles = [];
- $except_str = '(sauf';
- $pos0 = strpos($f, '(');
- $pos = strpos($f, $except_str);
- // Si le nom du champ $f fini par "(sauf ...)", on récupère cette chaine except (sans le mot 'sauf' ni la parenthèse finale) dans $except
- if ($pos0 !== false) {
- $error_msg = "Erreur dans le fichier de configuration des champs non modifiables";
- // EXCEPTION si parenthèse début mais pas suivie du mot-clé 'sauf'
- if ($pos === false)
- throw new \Exception("$error_msg : une parenthèse doit toujours être suivie du mot-clé 'sauf', ce qui n'est pas le cas de la ligne '$f'");
- // EXCEPTION si pas de parenthèse finale, ou role mal orthographié
- //$except_list = trim( substr($f, $pos + strlen($except_str), -1) );
- if ( substr($f, -1) != ')' )
- throw new \Exception("$error_msg : il manque une parenthèse à la fin de la ligne '$f'");
- $except_roles = str_replace(" ", "", substr($f, $pos + strlen($except_str), -1) );
- $except_roles = explode(',', $except_roles);
- foreach ($except_roles as $role) if (! self::isValidRole($role))
- throw new \Exception("$error_msg : le role '$role' est mal orthographié dans la ligne '$f'");
- $f = trim( substr($f,0,$pos) );
- }
- $dict[$f] = $except_roles;
- }
- return $dict;
- }
-
// (EP 2021 09) fonction récursive :
// => champs readonly pour le lot N = champs readonly pour le lot N-1 + champs readonly pour le lot N :
public static function getUneditableFieldsForLot($lot_num) {
-
+ return self::getCategoryFieldsForLot('UNEDITABLE_FIELDS_AFTER_LOT', $lot_num, 'UNEDITABLE_FIELDS');
+ /*
+
// Si N = -1 => on retourne la liste initiale de champs readonly (fin de la récursivité)
//if ($lot_num < 0) return [];
if ($lot_num < 0) return self::list_to_dict( Configure::readOrFail('UNEDITABLE_FIELDS') );
@@ -323,10 +347,57 @@ class MaterielsTable extends AppTable
// => Somme des 2 (champs readonly pour le lot N-1 + champs readonly pour le lot N)
//return array_unique(array_merge($base_uneditable_fields, $new_uneditable_fields));
return array_merge($base_uneditable_fields, $new_uneditable_fields);
+ */
}
+ public static function separateFieldNameAndExceptedRoles($f) {
+ $except_roles = [];
+ $except_str = '(sauf';
+ $pos0 = strpos($f, '(');
+ $pos = strpos($f, $except_str);
+ // Si le nom du champ $f fini par "(sauf ...)", on récupère cette chaine except (sans le mot 'sauf' ni la parenthèse finale) dans $except
+ if ($pos0 !== false) {
+ $error_msg = "Erreur dans le fichier de configuration des champs non modifiables";
+
+ // EXCEPTION si parenthèse début mais pas suivie du mot-clé 'sauf'
+ /*
+ if ($pos === false)
+ throw new \Exception("$error_msg : une parenthèse doit toujours être suivie du mot-clé 'sauf', ce qui n'est pas le cas de la ligne '$f'");
+ */
+ if ($pos !== false) {
+
+ // EXCEPTION si pas de parenthèse finale, ou role mal orthographié
+ //$except_list = trim( substr($f, $pos + strlen($except_str), -1) );
+ if ( substr($f, -1) != ')' )
+ throw new \Exception("$error_msg : il manque une parenthèse à la fin de la ligne '$f'");
+
+ $except_roles = str_replace(" ", "", substr($f, $pos + strlen($except_str), -1) );
+ $except_roles = explode(',', $except_roles);
+ foreach ($except_roles as $role) if (! self::isValidRole($role))
+ throw new \Exception("$error_msg : le role '$role' est mal orthographié dans la ligne '$f'");
+
+ $f = trim( substr($f,0,$pos) );
+ }
+ }
+ //return [$f=>$except_roles];
+ return ['name'=>$f, 'roles'=>$except_roles];
+ }
+
+ // (EP 2021 10)
+ public static function list_to_dict($uneditable_fields) {
+ $dict = [];
+ foreach ($uneditable_fields as $f) {
+ //$dict[$f] = $except_roles;
+ $fieldNameAndExceptedRoles = self::separateFieldNameAndExceptedRoles($f);
+ $dict[$fieldNameAndExceptedRoles['name']] = $fieldNameAndExceptedRoles['except_roles'];
+ }
+ return $dict;
+ }
+
+
+
/*
public static function getMandatoryFieldsLot1() {
/S
@@ -353,7 +424,13 @@ class MaterielsTable extends AppTable
$fields = self::getMandatoryFieldsForMaterielStatus($status);
// Seulement si prix > 10K€ : exiger la facture jointe et le n° série et lieu de stockage précis
if ($status == 'VALIDATED' && $mat->prix_ht && $mat->prix_ht > 10000) {
- $fields['numero_serie'] = 'S/N';
+ //$fields['numero_serie'] = 'S/N';
+ /*
+ $fields['numero_serie'] = [
+ //'selected'=>'1',
+ 'comment'=>'S/N'
+ ];
+ */
//TODO 202109
//$fields[] = 'lieu stockage';
//$fields[] = 'facture jointe';
@@ -361,7 +438,9 @@ class MaterielsTable extends AppTable
return $fields;
}
public static function getMandatoryFieldsForMaterielStatus($status) {
-
+ //return self::getCategoryFieldsForMaterielStatus('MANDATORY_FIELDS_FOR_LOT', $status);
+ return self::getCategoryFieldsForMaterielStatus('MANDATORY', $status);
+ /*
if (is_null($status)) $status='CREATED';
// On recup le LOT qui convient au status courant du matos
//$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2);
@@ -375,9 +454,12 @@ class MaterielsTable extends AppTable
//debug($fields);
return $fields;
+ */
}
public static function getUneditableFieldsForMaterielStatus($status) {
-
+ //return self::getCategoryFieldsForMaterielStatus('UNEDITABLE_FIELDS_AFTER_LOT', $status);
+ return self::getCategoryFieldsForMaterielStatus('UNEDITABLE', $status);
+ /*
if (is_null($status)) $status='CREATED';
// On recup le LOT qui convient au status courant du matos
//$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2);
@@ -390,12 +472,19 @@ class MaterielsTable extends AppTable
$fields = self::getUneditableFieldsForLot($lot_num);
return $fields;
+ */
}
public static function getRecommendedFieldsForMaterielStatus($status) {
- return self::getFieldsCategoryForMaterielStatus('RECOMMENDED', $status);
+ //return self::getCategoryFieldsForMaterielStatus('RECOMMENDED', $status);
+ //return self::getCategoryFieldsForMaterielStatus('RECOMMENDED_FIELDS_AFTER_LOT', $status);
+ return self::getCategoryFieldsForMaterielStatus('RECOMMENDED', $status);
}
- public static function getFieldsCategoryForMaterielStatus($fields_categ, $status) {
- $func_name = "get".ucfirst($fields_categ)."FieldsForLot"; // getUneditableFieldsForLot()
+
+ public static function getCategoryFieldsForMaterielStatus($categ, $status) {
+ //$func_name = "get".ucfirst($fields_categ)."FieldsForLot"; // getUneditableFieldsForLot()
+ //$func_name = "getCategoryFieldsForLot"; // getUneditableFieldsForLot()
+ $func_name = "get".ucfirst($categ)."FieldsForLot"; // getUneditableFieldsForLot()
+
if (is_null($status)) $status='CREATED';
// On recup le LOT qui convient au status courant du matos
//$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2);
@@ -1560,6 +1649,9 @@ class MaterielsTable extends AppTable
$fournisseur_asis = $entity->fournisseur ? $entity->fournisseur['name'] : '';
// Enlever les espaces superflus
$fournisseur = trim($fournisseur_asis);
+ //debug($fournisseur);
+ //debug($entity);
+
// Si champ fournisseur obligatoire, vérification qu'il est bien rempli (ou emission d'une erreur)
//if (IP2I && $entity->fournisseur && $fournisseur == '') {
@@ -1688,6 +1780,7 @@ class MaterielsTable extends AppTable
} // ssi changement
// Finalement, on supprime les champs 'fournisseur' car sinon erreur de sauvegarde,
// (normal ces champs n'existent pas dans materiel)
+ //debug($entity); exit;
unset($entity->fournisseur_orig);
unset($entity->fournisseur);
//debug($entity); exit;
diff --git a/src/Template/ConfigurationFields/edit.ctp b/src/Template/ConfigurationFields/edit.ctp
new file mode 100644
index 0000000..302ed42
--- /dev/null
+++ b/src/Template/ConfigurationFields/edit.ctp
@@ -0,0 +1,149 @@
+ 'hiraigc02eb46spa06iiog6tvh'
+]
+*/
+//debug($_ENV);
+//debug($_REQUEST);
+
+// Variables passées par le controleur
+$CAN_EDIT = true;
+$CAN_EDIT = $CAN_EDIT;
+$READONLY = $READONLY;
+$contact = $contact;
+$fieldsets = $fieldsets;
+//debug($fieldsets);
+
+$icon = $READONLY ? '' : "";
+//$icon = $READONLY ? '' : "";
+//$end = $READONLY ? "(Visualisation)" : "(Modification)";
+//$title = "Configuration des champs obligatoires ou non modifiables de la fiche Matériel $end";
+$title = "Configuration des champs obligatoires ou non modifiables de la fiche Matériel";
+echo "$icon $title
";
+/*
+ Autres icones possibles :
+echo " $title
";
+echo " $title
";
+echo " $title
";
+echo " $title
";
+echo " $title
";
+*/
+
+if ($READONLY && $CAN_EDIT) $this->MyHelper->echoEditButton();
+if ($READONLY && $CAN_EDIT) $this->MyHelper->echoButtonForAction('icon-trash', 'reset-to-default', 'Remettre les valeurs par défaut', 'Remettre les valeurs par défaut', true);
+
+//echo $this->Html->icon('pencil');
+
+echo $this->Form->create($contact);
+
+ if (!$READONLY) {
+ echo $this->Form->button('Enregistrer', ['class'=>'btn btn-outline-success', 'type'=>'submit']);
+ //echo $this->Form->button('Submit');
+ echo '
';
+ }
+
+ //echo $this->Form->button($this->Html->icon('pencil'), ['escape' => false]);
+ // ...can be easily rewritten as:
+ //echo $this->Form->button('i:pencil');
+
+ foreach ($fieldsets as $fieldset_name => $fields) {
+ $controls = [];
+
+ //foreach ($fields as $field) {
+ foreach ($fields as $field_name => $attributes) {
+
+ if ($field_name=='fieldset_comment') continue;
+
+ // champ activé ou désactivé
+ $checked = $attributes['selected'];
+ $comment = $attributes['comment'];
+ $except_roles = isset($attributes['except_roles']) ? $attributes['except_roles'] : [];
+
+ $name = "$fieldset_name.$field_name";
+
+ // - CHAMP de la table materiel : Checkbox pour le dé/sélectionner
+ $label = $field_name;
+ if ($READONLY) {
+ if ($comment) $label .= ' ('.$comment.')';
+ if ($except_roles) $label .= ' (sauf '.implode(', ',$except_roles).')';
+ }
+ $controls["$name.selected"] = [
+ 'type' => 'checkbox',
+ //'hiddenField' => true,
+ 'label' => $label,
+ 'checked' => $checked,
+ 'disabled' => $READONLY,
+ //'readonly' =>$READONLY,
+ //'readonly' => 'readonly',
+ ];
+
+ // (EDIT ONLY)
+ // - Label associé au champ (entre parenthèses) doit pouvoir être modifié
+ if (!$READONLY) $controls["$name.comment"] = [
+ //'type' => 'input',
+ 'label' => false,
+ 'val' => $comment,
+ //'size' => 20,
+ //'disabled' => $READONLY,
+ //'readonly' => $READONLY,
+ ];
+
+ // (EDIT ONLY)
+ $fieldsets_with_roles = ['UNEDITABLE_FIELDS','UNEDITABLE_FIELDS_AFTER_LOT0', 'UNEDITABLE_FIELDS_AFTER_LOT1', 'UNEDITABLE_FIELDS_AFTER_LOT2'];
+ // - ROLES exceptés (select multiple list)
+ //if (!$READONLY && $field_name!='HAS_ORDER_BUTTON')
+ if ( !$READONLY && in_array($fieldset_name, $fieldsets_with_roles) ) $controls["$name.except_roles"] = [
+ 'type' => 'select',
+ 'label' => '(excepté pour les rôles)',
+ //'options' => ['