diff --git a/CHANGELOG b/CHANGELOG
index 0ab629b..c92a2f6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -373,12 +373,6 @@ Par contre, ok avec FPDF
*) LDAP trou sécu (autres labos) : user se connecte avec bad mdp
- *)
- Rendre modifiable la config via page web "Gérer les champs obligatoires"
- - OFF_nom_du_champ : 'libellé'
- - Restaurer la config par défaut
- - Réactiver une variable : OFF_nom_du_champ => nom_du_champ
-
*) => update matos lifecycle diag
@@ -541,11 +535,19 @@ TODO :
- add_edit generic
-- fusionner groupe thematique et metier (et projet ?)
+- fusionner groupe thematique et metier (et projet ?) :
+ => faire hériter les Controller et les Table d'une meme superclasse GroupController et GroupTable
+ => avoir un seul template
+ => c'est vraiment stupide d'avoir 2 classes qui font la meme chose...
- Utiliser les vues "index" des entités associées pour la vue "view" de materiel (et suivi) :
=> éviter la redondance, le contenu est pratiquement le meme (???, sauf que les colonnes ne sont pas triables)
+- Bien préciser quels sont les champs obligatoires avec une asterisque (et pour chaque LOT)
+
+- S/N à renseigner (recommended) ssi > 10000€
+ Ajouter champ attributes.condition = "prix > 10000"
+
======= NEXT =======
print etiquette pour les 2 serveurs + tester fin garantie orange
@@ -563,9 +565,45 @@ Vues génériques (index et view) :
- Suivis.statut => "en cours" ou "à terminer" => à calculer auto
+ *)
+ Rendre modifiable la config via page web "Gérer les champs obligatoires"
+ - OFF_nom_du_champ : 'libellé'
+ - Restaurer la config par défaut
+ - Réactiver une variable : OFF_nom_du_champ => nom_du_champ
+
+
+saisir les personnes du gt2i et de tous les groupes...
+
+groupe.users associés : ajouter "(responsable)" when relevant
+
+comment faire un tri sur la dernière colonne des stats (connexDurAvg) ?
+
+erreur download depuis page documents/ (ou depuis vue du matériel) sur inventirap : erreur 404 (action impossible)
+
+TODO config fields :
+- réadapter lecture config à new file format
+- compléter le fichier config avec tous les champs possibles à chaque lot !!!
+- fichier read-write par web server
+- ./UPDATE cral et ip2i + new config file
+- pub
+- soigner la présentation du form (peu lisible now)
+
+
+ - (b) Bugfix fournisseur perdu (et champ vide qui n'est plus modifiable !) après validation du matos
+ (quand il manque un champ pour valider), et pourtant bien enregistré dans listes des fournisseurs
+
+
======= CHANGES =======
-------
+22/11/2021 v5.3.1-3.7.9
+ - (e) BIG NEW FEATURE : Configuration des champs obligatoires et readonly se fait maintenant via page WEB !!!
+ => plus besoin de modifier manuellement le fichier de config texte yaml
+ - (e) ajout lien vers stats utilisateurs depuis page accueil superadmin
+ - (e) modif page Apropos
+
+
+-------
15/11/2021 v5.3.0-3.7.9
- (e) Refactorisation : Vue détaillée users (view) générique avec contenu enrichi ("(responsable)")
- (e) Refactorisation : Vue liste users (index) générique avec contenu enrichi ("(responsable)")
diff --git a/README.md b/README.md
index 4ed61ae..dbcc8ee 100644
--- a/README.md
+++ b/README.md
@@ -52,8 +52,8 @@ Logiciel testé et validé sur les configurations suivantes :
--------------------------------------------------------------------------------------------
-Date: 15/11/2021
-Version: v5.3.0-3.7.9
+Date: 22/11/2021
+Version: v5.3.1-3.7.9
HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes)
diff --git a/config/app_labinvent_mandatory_fields.default.yml b/config/app_labinvent_mandatory_fields.default.yml
deleted file mode 100644
index 49d91a2..0000000
--- a/config/app_labinvent_mandatory_fields.default.yml
+++ /dev/null
@@ -1,616 +0,0 @@
-# FICHIER DE CONFIGURATION PAR DÉFAUT POUR LES CHAMPS D'UN MATÉRIEL
-
-
-# Activer la possibilité de commander un matériel (au service gestion) en cliquant sur un bouton "Commander" ?
-# L'étape "A commander" (status TOBEORDERED) devient alors une étape intermédiaire OPTIONNELLE entre CREATED et VALIDATED
-# Les transitions de statut d'un materiel sont alors : CREATED => [ TEBEORDERED (à commander) ] => VALIDATED => TOBEARCHIVED => ARCHIVED
-HAS_ORDER_BUTTON: true
-#HAS_ORDER_BUTTON: false
-
-
-
-# ************************************************************
-# ************** CHAMPS INITIALEMENT READONLY ****************
-# ************************************************************
-
-# Un champ peut etre readonly pour 3 raisons :
-# - soit parce qu’il a une valeur par défaut non modifiable (ex: Acheteur = celui qui crée la fiche),
-# - soit parce qu’il est réservé à l’Administration (champs administratifs, « Admin only »),
-# - soit parce qu’il a servi à valider une étape et ne doit donc plus être changé (sous peine d’invalider l’étape)
-
-UNEDITABLE_FIELDS:
-
- # #### CHAMPS GÉNÉRAUX ####
-
- #- designation
-
- #- will_stay
-
- #- description
-
- #- hors_service
-
- #- sur_categorie_id
-
- #- categorie_id
-
- #- sous_categorie_id
-
- #- groupes_thematique_id
-
- #- groupes_metier_id
-
- #- projet_id
-
- #- materiel_technique
- #- materiel_administratif
-
- #- metrologie
-
- #- etiquette
-
- #- site_id
-
- #- lieu_detail
-
- #- date_acquisition
-
- #- date_reception
-
- # Garantie
- #- duree_garantie
- #- unite_duree_garantie
- #- date_fin_garantie
-
- # Super Administrateur only
- #- status
-
- #- numero_serie
-
- # Utilisateur du materiel (destinataire du bien)
- #- nom_user
-
- # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même
- - nom_responsable (sauf Responsable, Administration)
-
- #- nom_ancien_responsable
-
- #- resp_credit
-
- #- gestionnaire_id
-
- #- fournisseur_id
-
- #- organisme_id
-
- #- prix_ht
-
- #- budgets
-
-
- # #### CHAMPS ADMINISTRATIFS : ####
-
- # Entité(s) dépensière(s) (budget(s)) // ligne budgétaire (sur quel(s) budget(s)) ou entité(s) dépensière(s) ?)
- - eotp (sauf Administration)
- - numero_commande (sauf Administration)
- - numero_inventaire_organisme (sauf Administration)
- - numero_inventaire_old (sauf Administration)
- - numero_laboratoire # READONLY toujours car généré automatiquement
-
-
-
-
-
-
-# ***************************************************************
-# ************** LOT 0 - CRÉATION FICHE MATÉRIEL ****************
-# ***************************************************************
-
-# Champs OBLIGATOIRES pour CRÉER une fiche Matériel
-# - Aucun champ
-#MANDATORY_FIELDS_FOR_LOT0: []
-# - Au moins un champ
-MANDATORY_FIELDS_FOR_LOT0:
-
- # Infos toujours obligatoires (cachées car calculées automatiquement)
- #'status',
- #'tobeordered',
-
- designation: 'Désignation'
-
- description: 'Description'
-
- sur_categorie_id: 'Domaine'
- categorie_id: 'Catégorie'
-
- # - Acheteur (le Créateur de la fiche)
- nom_responsable: "Nom de l'Acheteur"
- #// (rempli automatiquement)
- email_responsable: "Email de l'Acheteur"
-
- # - Utilisateur
- nom_user: "Nom de l'utilisateur"
-
- # Calculé auto au moment du save()
- #'numero_laboratoire',
-
- # ******* END OF MANDATORY_FIELDS_LOT0 ********
-
-
-# Liste des champs qui sont NON MODIFIABLES APRÈS la CRÉATION d'une fiche
-# Attention, les champs UNEDITABLE_FIELDS (voir au début du fichier) sont aussi pris en compte (donc, inutile de les répéter)
-
-# - Aucun champ
-UNEDITABLE_FIELDS_AFTER_LOT0: []
-
-# - Au moins un champ
-#UNEDITABLE_FIELDS_AFTER_LOT0:
-
- # #### CHAMPS GÉNÉRAUX ####
-
- #- designation
-
- #- will_stay
-
- #- description
-
- #- hors_service
-
- #- sur_categorie_id
-
- #- categorie_id
-
- #- sous_categorie_id
-
- #- groupes_thematique_id
-
- #- groupes_metier_id
-
- #- projet_id
-
- #- materiel_technique
- #- materiel_administratif
-
- #- metrologie
-
- #- etiquette
-
- #- site_id
-
- #- lieu_detail
-
- #- date_acquisition
-
- #- date_reception
-
- # Garantie
- #- duree_garantie
- #- unite_duree_garantie
- #- date_fin_garantie
-
- # Super Administrateur only
- #- status
-
- #- numero_serie
-
- # Utilisateur du materiel (destinataire du bien)
- #- nom_user
-
- # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même
- #- nom_responsable (sauf Responsable, Administration)
-
- #- nom_ancien_responsable
-
- #- resp_credit
-
- #- gestionnaire_id
-
- #- fournisseur_id
-
- #- organisme_id
-
- #- prix_ht
-
- #- budgets
-
- # #### CHAMPS ADMINISTRATIFS : ####
- #- eotp (sauf Administration)
- #- numero_commande (sauf Administration)
- #- numero_laboratoire # READONLY toujours car généré automatiquement
- #- numero_inventaire_organisme (sauf Administration)
- #- numero_inventaire_old (sauf Administration)
-
-
-# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS COMMANDE
-# Ces champs ne seront pas demandés à la saisie, mais un simple rappel sera affiché sur la vue détaillée du matériel (tant que ces éléments sont absents)
-# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-RECOMMENDED_FIELDS_AFTER_LOT0: []
-
-
-
-
-
-
-
-
-# ******************************************************************************
-# ************** LOT 1 - COMMANDE (DEMANDE D'ACHAT) (optionnel) ****************
-# ******************************************************************************
-
-# Champs OBLIGATOIRES POUR passer la COMMANDE (La commande est une action optionnelle)
-# Attention, les champs MANDATORY_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-#MANDATORY_FIELDS_FOR_LOT1: []
-# - Au moins un champ
-MANDATORY_FIELDS_FOR_LOT1:
-
- # Infos toujours obligatoires (cachées car calculées automatiquement)
- #'status',
- #'tobeordered',
-
- #'hors_service', // O/N
-
- ##designation: 'Désignation'
-
- ##description: 'Description'
-
- #'permanent',
- #'will_stay', // O/N
-
- ##sur_categorie_id: 'Domaine'
- ##categorie_id: 'Catégorie'
-
- # - Utilisateur
- #nom_user: "Nom de l'utilisateur de ce matériel"
-
- # - Acheteur
- #nom_responsable: 'Nom du responsable'
- # (rempli automatiquement)
- #email_responsable: 'Email du responsable'
-
- # Calculé auto au moment du save()
- #'numero_laboratoire',
-
- organisme_id: 'Organisme'
-
- prix_ht: 'Prix HT'
-
- # (par défaut = acheteur)
- resp_credit: 'Responsable du crédit'
-
- # Gestionnaire de référence (recevra la commande)
- gestionnaire_id: 'Gestionnaire de référence'
-
- # Fournisseur
- fournisseur_id: 'Fournisseur'
-
- # Utilisé par la Gestion pour remplir le champ eotp
- budgets: 'Budgets'
-
- # INFOS ADMINISTRATIVES
- # - EOTP : obligatoire seulement dans LOT2
-
- # - Devis joint : c'est un champ virtuel, il n'existe pas physiquement (sauf dans la table Documents)
- DOC_DEVIS: 'Devis'
- #DOC_BC: "Bon de Commande"
- #DOC_BL: "Bon de Livraison"
- #DOC_FACTURE: "Facture"
-
-
- # ******* END OF MANDATORY_FIELDS_LOT1 ********
-
-
-# Liste des champs NON MODIFIABLES APRÈS la demande d'ACHAT (c'est à dire APRÈS avoir fait la "COMMANDE")
-# Attention, les champs UNEDITABLE_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-#UNEDITABLE_FIELDS_AFTER_LOT1: []
-# - Au moins un champ
-UNEDITABLE_FIELDS_AFTER_LOT1:
-
- # #### CHAMPS GÉNÉRAUX ####
-
- #- designation
-
- #- will_stay
-
- #- description
-
- #- hors_service
-
- # On ne devrait pas pouvoir changer la NATURE du bien
- # Domaine & Catégorie
- - sur_categorie_id (sauf Administration) # Domaine
- - categorie_id (sauf Administration) # Catégorie
- #- sous_categorie_id
-
- #- groupes_thematique_id
-
- #- groupes_metier_id
-
- #- projet_id
-
- #- materiel_technique
- #- materiel_administratif
-
- #- metrologie
-
- #- etiquette
-
- #- site_id
-
- #- lieu_detail
-
- #- date_acquisition
-
- #- date_reception
-
- # Garantie
- #- duree_garantie
- #- unite_duree_garantie
- #- date_fin_garantie
-
- # Super Administrateur only
- #- status
-
- #- numero_serie
-
- # Utilisateur du materiel (destinataire du bien)
- #- nom_user
-
- # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même
- #- nom_responsable (sauf Responsable, Administration)
-
- #- nom_ancien_responsable
-
- # (par défaut = acheteur)
- - resp_credit (sauf Administration)
-
- - gestionnaire_id (sauf Administration)
-
- # Fournisseur
- - fournisseur_id (sauf Administration)
-
- - organisme_id (sauf Administration)
-
- - prix_ht (sauf Administration)
-
- # Utilisé par la Gestion pour remplir le champ eotp
- - budgets (sauf Administration)
-
-
- # #### CHAMPS VIRTUELS : doc attachés ####
- # Ces champs virtuels n'existent pas physiquement (sauf dans la table Documents)
- # On indique ici les documents attachés à la fiche matériel, qui ne peuvent plus être ni modifiés ni supprimés
- # - Devis
- # Le devis attaché au matériel commandé n'est ni modifiable ni supprimable
- - DOC_DEVIS
- # - Bon de Commande (si un BC a été joint à la fiche, on ne peut plus le modifier ni le supprimer)
- - DOC_BC (sauf Administration)
- # - Bon de Livraison
- #- DOC_BL
- # - Facture
- #- DOC_FACTURE
-
-
- # #### CHAMPS ADMINISTRATIFS : ####
- #- eotp (sauf Administration)
- #- numero_commande (sauf Administration)
- #- numero_laboratoire # READONLY toujours car généré automatiquement
- #- numero_inventaire_organisme (sauf Administration)
- #- numero_inventaire_old (sauf Administration)
-
-
-
-# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS COMMANDE
-# Ces champs ne seront pas demandés à la saisie, mais un simple rappel sera affiché sur la vue détaillée du matériel (tant que ces éléments sont absents)
-# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-RECOMMENDED_FIELDS_AFTER_LOT1: []
-#RECOMMENDED_FIELDS_AFTER_LOT1:
- # - Etiquette posée sur le matériel
- #etiquette: "d'imprimer l'étiquette associée et de la coller sur le matériel"
-
-
-
-
-
-
-
-
-# ***************************************************************************
-# ************** LOT 2 - VALIDATION (matériel livré et payé) ****************
-# ***************************************************************************
-
-# Champs OBLIGATOIRES POUR VALIDER la livraison
-# Attention, les champs MANDATORY_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-#MANDATORY_FIELDS_FOR_LOT2: []
-# - Au moins un champ
-MANDATORY_FIELDS_FOR_LOT2:
-
- #//'fournisseur_id' => 'Fournisseur',
- #//'fournisseur' => 'Fournisseur',
-
- date_acquisition: "Date d'achat"
-
- date_reception: 'Date de livraison'
-
- site_id: 'Site'
-
- #TODO: seulement si prix > 10K€
- lieu_detail: 'Lieu de stockage'
- #numero_serie: 'S/N'
-
- #// INFOS ADMINISTRATIVES :
-
- #// La Gestion doit remplir ce champ a partir des infos qui sont dans le champ "budget" (rempli par acheteur)
- #// ligne budgétaire (sur quel(s) budget(s)) ou entité(s) dépensière(s)
- eotp: 'Entité(s) dépensière(s) (budget(s))'
-
- numero_commande: 'Num. BC'
-
- # Docs attachés obligatoires pour valider
- DOC_DEVIS: 'Devis'
- #DOC_BC: "Bon de Commande"
- #DOC_BL: "Bon de Livraison"
- #DOC_FACTURE: "Facture"
-
-
- # ******* END OF $MANDATORY_FIELDS_LOT2 ********
-
-
-
-
-# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS VALIDATION de la livraison
-# Ces champs ne seront pas demandés à la saisie, mais un simple rappel sera affiché sur la vue détaillée du matériel (tant que ces éléments sont absents)
-# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter)
-# - Aucun champ
-#RECOMMENDED_FIELDS_AFTER_LOT2: []
-# - Au moins un champ
-RECOMMENDED_FIELDS_AFTER_LOT2:
-
-
- # - Etiquette posée sur le matériel
- etiquette: "d'imprimer l'étiquette associée et de la coller sur le matériel"
-
- # - Numéro inventaire tutelles
- # On aurait pu rendre cet élément obligatoire mais on ne peut pas l'exiger au moment de la livraison
- # car le gestionnaire n'a cette info que lorsque "Service fait CNRS" (il récupère alors le n° inventaire "Tutelle" sur GESLAB)
- numero_inventaire_organisme: "de renseigner le champ 'N° inventaire comptable/tutelles (Organisme)'"
-
-
- # DOCS ATTACHÉS recommandés après validation
- #DOC_DEVIS: "d'ajouter un Devis"
- DOC_BC: "d'ajouter le Bon de Commande"
- DOC_BL: "d'ajouter le Bon de Livraison"
- DOC_FACTURE: "d'ajouter la Facture"
-
-
-
-
-
-# Liste des champs qui sont NON MODIFIABLES APRÈS la VALIDATION (livraison)
-# Attention, les champs UNEDITABLE_FIELDS_XXX définis plus haut sont aussi pris en compte
-# - Aucun champ
-#UNEDITABLE_FIELDS_AFTER_LOT2: []
-# - Au moins un champ
-UNEDITABLE_FIELDS_AFTER_LOT2:
-
- # #### CHAMPS GÉNÉRAUX ####
-
- #- designation
-
- #- will_stay
-
- #- description
-
- #- hors_service
-
- - sur_categorie_id
- - categorie_id
-
- #- sous_categorie_id
-
- #- groupes_thematique_id
-
- #- groupes_metier_id
-
- #- projet_id
-
- #- materiel_technique
- #- materiel_administratif
-
- #- metrologie
-
- #- etiquette
-
- #- site_id
-
- #- lieu_detail
-
- - date_acquisition
- - date_reception
-
- # Garantie
- #- duree_garantie
- #- unite_duree_garantie
- #- date_fin_garantie
-
- # Super Administrateur only
- #- status
-
- #- numero_serie
-
- # Utilisateur du materiel (destinataire du bien)
- #- nom_user
-
- # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même
- #- nom_responsable (sauf Responsable, Administration)
-
- #- nom_ancien_responsable
-
- #- resp_credit
-
- #- gestionnaire_id
-
- #- fournisseur_id
-
- #- organisme_id
-
- #- prix_ht
-
- #- budgets
-
-
- # #### CHAMPS ADMINISTRATIFS ####
-
- - eotp
- - numero_commande
- # READONLY toujours car généré automatiquement
- #- numero_laboratoire
- #- numero_inventaire_organisme
- #- numero_inventaire_old
-
-
- # DOCS ATTACHÉS qui ne sont plus ni supprimables ni modifiables
- # - Devis
- #- DOC_DEVIS
- # - Bon de Commande
- - DOC_BC
- # - Bon de Livraison
- - DOC_BL
- # - Facture
- - DOC_FACTURE
-
-
-
-
-# ******************************************************************************
-# ************** LOT 3 - ARCHIVAGE (matériel à sortir ou sorti) ****************
-# ******************************************************************************
-
-# (TODO) Ce 3e niveau n'est pas encore implémenté, il est pour l'instant codé en dur dans le code
-
-# - Aucun champ
-MANDATORY_FIELDS_FOR_LOT3: []
-
-# - Aucun champ
-UNEDITABLE_FIELDS_AFTER_LOT3: []
-# En fait, TOUS LES CHAMPS SONT READONLY SAUF : description, ...
-
-
-
-
-
-
-
-
-
-
-# Astuce utilisable :
-# Pour faire : MANDATORY_FIELDS_LOT2 = MANDATORY_FIELDS_LOT1
-# On fait comme ceci :
-#MANDATORY_FIELDS_LOT1: &lot1
-#MANDATORY_FIELDS_LOT2: *lot1
-
diff --git a/config/bootstrap.php b/config/bootstrap.php
index bee9fa5..dcd39f3 100755
--- a/config/bootstrap.php
+++ b/config/bootstrap.php
@@ -36,6 +36,10 @@ use Yaml\Configure\Engine\YamlConfig;
*/
require __DIR__ . '/paths.php';
+/* EP 2021-11 : mes propres constantes */
+define('CONFIG_MATERIEL_FIELDS_FILE_NAME', 'app_labinvent_mandatory_fields');
+
+
// Use composer to load the autoloader.
require ROOT . DS . 'vendor' . DS . 'autoload.php';
@@ -106,17 +110,31 @@ try {
}
// (EP 2021 09 Ajout nouveaux fichiers config pour les champs obligatoires (et les autorisations))
-$config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields';
+//$config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields';
// Si le fichier de conf n'existe pas, on le crée en copiant le fichier par défaut
-if ( !file_exists(CONFIG.DS.$config_mandatory_fields_file_name.'.yml') )
- copy(CONFIG.DS.$config_mandatory_fields_file_name.'.default.yml', CONFIG.DS.$config_mandatory_fields_file_name.'.yml');
+//if ( !file_exists(CONFIG.DS.$config_mandatory_fields_file_name.'.yml') )
+//$config_matos_full_file_name = $config_matos_full_file_name_default = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME;
+$config_matos_full_file_name = $config_matos_full_file_name_default = CONFIG_MATERIEL_FIELDS_FILE_NAME;
+//$config_matos_full_file_name_default = $config_matos_full_file_name;
+$config_matos_full_file_name .= '.yml';
+$config_matos_full_file_name_default .= '.default.yml';
+//if ( !file_exists($config_matos_full_file_name) ) copy($config_matos_full_file_name_default, $config_matos_full_file_name);
try {
- Configure::config('yaml', new YamlConfig());
- Configure::load($config_mandatory_fields_file_name, 'yaml');
+ Configure::config('my_yaml_engine', new YamlConfig());
+ //Configure::load($config_mandatory_fields_file_name, 'yaml', true);
+ Configure::load(CONFIG_MATERIEL_FIELDS_FILE_NAME, 'my_yaml_engine');
//Configure::load('app_labinvent_mandatory_fields_IP2I', 'yaml');
//Configure::load('app_labinvent_authorizations', 'yaml');
} catch (\Exception $e) {
- die('config/bootstrap.php: Unable to load yaml config file');
+ echo("
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 "