Commit 3c4f9138ae3fe491f92fab3e26e1955555a21faf
1 parent
cf782ac0
Exists in
master
and in
1 other branch
BIG NEW FEATURE: Config des champs obligatoires et readonly via page web
=> plus besoin de modifier manuellement le fichier de config texte yaml et aussi : - ajout lien vers stats utilisateurs depuis page accueil superadmin - modif page Apropos v5.3.1-3.7.9
Showing
19 changed files
with
899 additions
and
891 deletions
Show diff stats
CHANGELOG
... | ... | @@ -373,12 +373,6 @@ Par contre, ok avec FPDF |
373 | 373 | |
374 | 374 | *) LDAP trou sécu (autres labos) : user se connecte avec bad mdp |
375 | 375 | |
376 | - *) | |
377 | - Rendre modifiable la config via page web "Gérer les champs obligatoires" | |
378 | - - OFF_nom_du_champ : 'libellé' | |
379 | - - Restaurer la config par défaut | |
380 | - - Réactiver une variable : OFF_nom_du_champ => nom_du_champ | |
381 | - | |
382 | 376 | *) => update matos lifecycle diag |
383 | 377 | |
384 | 378 | |
... | ... | @@ -541,11 +535,19 @@ TODO : |
541 | 535 | |
542 | 536 | - add_edit generic |
543 | 537 | |
544 | -- fusionner groupe thematique et metier (et projet ?) | |
538 | +- fusionner groupe thematique et metier (et projet ?) : | |
539 | + => faire hériter les Controller et les Table d'une meme superclasse GroupController et GroupTable | |
540 | + => avoir un seul template | |
541 | + => c'est vraiment stupide d'avoir 2 classes qui font la meme chose... | |
545 | 542 | |
546 | 543 | - Utiliser les vues "index" des entités associées pour la vue "view" de materiel (et suivi) : |
547 | 544 | => éviter la redondance, le contenu est pratiquement le meme (???, sauf que les colonnes ne sont pas triables) |
548 | 545 | |
546 | +- Bien préciser quels sont les champs obligatoires avec une asterisque (et pour chaque LOT) | |
547 | + | |
548 | +- S/N à renseigner (recommended) ssi > 10000€ | |
549 | + Ajouter champ attributes.condition = "prix > 10000" | |
550 | + | |
549 | 551 | ======= NEXT ======= |
550 | 552 | |
551 | 553 | print etiquette pour les 2 serveurs + tester fin garantie orange |
... | ... | @@ -563,9 +565,45 @@ Vues génériques (index et view) : |
563 | 565 | - Suivis.statut => "en cours" ou "à terminer" => à calculer auto |
564 | 566 | |
565 | 567 | |
568 | + *) | |
569 | + Rendre modifiable la config via page web "Gérer les champs obligatoires" | |
570 | + - OFF_nom_du_champ : 'libellé' | |
571 | + - Restaurer la config par défaut | |
572 | + - Réactiver une variable : OFF_nom_du_champ => nom_du_champ | |
573 | + | |
574 | + | |
575 | +saisir les personnes du gt2i et de tous les groupes... | |
576 | + | |
577 | +groupe.users associés : ajouter "(responsable)" when relevant | |
578 | + | |
579 | +comment faire un tri sur la dernière colonne des stats (connexDurAvg) ? | |
580 | + | |
581 | +erreur download depuis page documents/ (ou depuis vue du matériel) sur inventirap : erreur 404 (action impossible) | |
582 | + | |
583 | +TODO config fields : | |
584 | +- réadapter lecture config à new file format | |
585 | +- compléter le fichier config avec tous les champs possibles à chaque lot !!! | |
586 | +- fichier read-write par web server | |
587 | +- ./UPDATE cral et ip2i + new config file | |
588 | +- pub | |
589 | +- soigner la présentation du form (peu lisible now) | |
590 | + | |
591 | + | |
592 | + - (b) Bugfix fournisseur perdu (et champ vide qui n'est plus modifiable !) après validation du matos | |
593 | + (quand il manque un champ pour valider), et pourtant bien enregistré dans listes des fournisseurs | |
594 | + | |
595 | + | |
566 | 596 | ======= CHANGES ======= |
567 | 597 | |
568 | 598 | ------- |
599 | +22/11/2021 v5.3.1-3.7.9 | |
600 | + - (e) BIG NEW FEATURE : Configuration des champs obligatoires et readonly se fait maintenant via page WEB !!! | |
601 | + => plus besoin de modifier manuellement le fichier de config texte yaml | |
602 | + - (e) ajout lien vers stats utilisateurs depuis page accueil superadmin | |
603 | + - (e) modif page Apropos | |
604 | + | |
605 | + | |
606 | +------- | |
569 | 607 | 15/11/2021 v5.3.0-3.7.9 |
570 | 608 | - (e) Refactorisation : Vue détaillée users (view) générique avec contenu enrichi ("(responsable)") |
571 | 609 | - (e) Refactorisation : Vue liste users (index) générique avec contenu enrichi ("(responsable)") | ... | ... |
README.md
... | ... | @@ -52,8 +52,8 @@ Logiciel testé et validé sur les configurations suivantes : |
52 | 52 | |
53 | 53 | -------------------------------------------------------------------------------------------- |
54 | 54 | |
55 | -Date: 15/11/2021 | |
56 | -Version: v5.3.0-3.7.9 | |
55 | +Date: 22/11/2021 | |
56 | +Version: v5.3.1-3.7.9 | |
57 | 57 | |
58 | 58 | |
59 | 59 | HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes) | ... | ... |
config/app_labinvent_mandatory_fields.default.yml deleted
... | ... | @@ -1,616 +0,0 @@ |
1 | -# FICHIER DE CONFIGURATION PAR DÉFAUT POUR LES CHAMPS D'UN MATÉRIEL | |
2 | - | |
3 | - | |
4 | -# Activer la possibilité de commander un matériel (au service gestion) en cliquant sur un bouton "Commander" ? | |
5 | -# L'étape "A commander" (status TOBEORDERED) devient alors une étape intermédiaire OPTIONNELLE entre CREATED et VALIDATED | |
6 | -# Les transitions de statut d'un materiel sont alors : CREATED => [ TEBEORDERED (à commander) ] => VALIDATED => TOBEARCHIVED => ARCHIVED | |
7 | -HAS_ORDER_BUTTON: true | |
8 | -#HAS_ORDER_BUTTON: false | |
9 | - | |
10 | - | |
11 | - | |
12 | -# ************************************************************ | |
13 | -# ************** CHAMPS INITIALEMENT READONLY **************** | |
14 | -# ************************************************************ | |
15 | - | |
16 | -# Un champ peut etre readonly pour 3 raisons : | |
17 | -# - soit parce qu’il a une valeur par défaut non modifiable (ex: Acheteur = celui qui crée la fiche), | |
18 | -# - soit parce qu’il est réservé à l’Administration (champs administratifs, « Admin only »), | |
19 | -# - soit parce qu’il a servi à valider une étape et ne doit donc plus être changé (sous peine d’invalider l’étape) | |
20 | - | |
21 | -UNEDITABLE_FIELDS: | |
22 | - | |
23 | - # #### CHAMPS GÉNÉRAUX #### | |
24 | - | |
25 | - #- designation | |
26 | - | |
27 | - #- will_stay | |
28 | - | |
29 | - #- description | |
30 | - | |
31 | - #- hors_service | |
32 | - | |
33 | - #- sur_categorie_id | |
34 | - | |
35 | - #- categorie_id | |
36 | - | |
37 | - #- sous_categorie_id | |
38 | - | |
39 | - #- groupes_thematique_id | |
40 | - | |
41 | - #- groupes_metier_id | |
42 | - | |
43 | - #- projet_id | |
44 | - | |
45 | - #- materiel_technique | |
46 | - #- materiel_administratif | |
47 | - | |
48 | - #- metrologie | |
49 | - | |
50 | - #- etiquette | |
51 | - | |
52 | - #- site_id | |
53 | - | |
54 | - #- lieu_detail | |
55 | - | |
56 | - #- date_acquisition | |
57 | - | |
58 | - #- date_reception | |
59 | - | |
60 | - # Garantie | |
61 | - #- duree_garantie | |
62 | - #- unite_duree_garantie | |
63 | - #- date_fin_garantie | |
64 | - | |
65 | - # Super Administrateur only | |
66 | - #- status | |
67 | - | |
68 | - #- numero_serie | |
69 | - | |
70 | - # Utilisateur du materiel (destinataire du bien) | |
71 | - #- nom_user | |
72 | - | |
73 | - # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même | |
74 | - - nom_responsable (sauf Responsable, Administration) | |
75 | - | |
76 | - #- nom_ancien_responsable | |
77 | - | |
78 | - #- resp_credit | |
79 | - | |
80 | - #- gestionnaire_id | |
81 | - | |
82 | - #- fournisseur_id | |
83 | - | |
84 | - #- organisme_id | |
85 | - | |
86 | - #- prix_ht | |
87 | - | |
88 | - #- budgets | |
89 | - | |
90 | - | |
91 | - # #### CHAMPS ADMINISTRATIFS : #### | |
92 | - | |
93 | - # Entité(s) dépensière(s) (budget(s)) // ligne budgétaire (sur quel(s) budget(s)) ou entité(s) dépensière(s) ?) | |
94 | - - eotp (sauf Administration) | |
95 | - - numero_commande (sauf Administration) | |
96 | - - numero_inventaire_organisme (sauf Administration) | |
97 | - - numero_inventaire_old (sauf Administration) | |
98 | - - numero_laboratoire # READONLY toujours car généré automatiquement | |
99 | - | |
100 | - | |
101 | - | |
102 | - | |
103 | - | |
104 | - | |
105 | -# *************************************************************** | |
106 | -# ************** LOT 0 - CRÉATION FICHE MATÉRIEL **************** | |
107 | -# *************************************************************** | |
108 | - | |
109 | -# Champs OBLIGATOIRES pour CRÉER une fiche Matériel | |
110 | -# - Aucun champ | |
111 | -#MANDATORY_FIELDS_FOR_LOT0: [] | |
112 | -# - Au moins un champ | |
113 | -MANDATORY_FIELDS_FOR_LOT0: | |
114 | - | |
115 | - # Infos toujours obligatoires (cachées car calculées automatiquement) | |
116 | - #'status', | |
117 | - #'tobeordered', | |
118 | - | |
119 | - designation: 'Désignation' | |
120 | - | |
121 | - description: 'Description' | |
122 | - | |
123 | - sur_categorie_id: 'Domaine' | |
124 | - categorie_id: 'Catégorie' | |
125 | - | |
126 | - # - Acheteur (le Créateur de la fiche) | |
127 | - nom_responsable: "Nom de l'Acheteur" | |
128 | - #// (rempli automatiquement) | |
129 | - email_responsable: "Email de l'Acheteur" | |
130 | - | |
131 | - # - Utilisateur | |
132 | - nom_user: "Nom de l'utilisateur" | |
133 | - | |
134 | - # Calculé auto au moment du save() | |
135 | - #'numero_laboratoire', | |
136 | - | |
137 | - # ******* END OF MANDATORY_FIELDS_LOT0 ******** | |
138 | - | |
139 | - | |
140 | -# Liste des champs qui sont NON MODIFIABLES APRÈS la CRÉATION d'une fiche | |
141 | -# Attention, les champs UNEDITABLE_FIELDS (voir au début du fichier) sont aussi pris en compte (donc, inutile de les répéter) | |
142 | - | |
143 | -# - Aucun champ | |
144 | -UNEDITABLE_FIELDS_AFTER_LOT0: [] | |
145 | - | |
146 | -# - Au moins un champ | |
147 | -#UNEDITABLE_FIELDS_AFTER_LOT0: | |
148 | - | |
149 | - # #### CHAMPS GÉNÉRAUX #### | |
150 | - | |
151 | - #- designation | |
152 | - | |
153 | - #- will_stay | |
154 | - | |
155 | - #- description | |
156 | - | |
157 | - #- hors_service | |
158 | - | |
159 | - #- sur_categorie_id | |
160 | - | |
161 | - #- categorie_id | |
162 | - | |
163 | - #- sous_categorie_id | |
164 | - | |
165 | - #- groupes_thematique_id | |
166 | - | |
167 | - #- groupes_metier_id | |
168 | - | |
169 | - #- projet_id | |
170 | - | |
171 | - #- materiel_technique | |
172 | - #- materiel_administratif | |
173 | - | |
174 | - #- metrologie | |
175 | - | |
176 | - #- etiquette | |
177 | - | |
178 | - #- site_id | |
179 | - | |
180 | - #- lieu_detail | |
181 | - | |
182 | - #- date_acquisition | |
183 | - | |
184 | - #- date_reception | |
185 | - | |
186 | - # Garantie | |
187 | - #- duree_garantie | |
188 | - #- unite_duree_garantie | |
189 | - #- date_fin_garantie | |
190 | - | |
191 | - # Super Administrateur only | |
192 | - #- status | |
193 | - | |
194 | - #- numero_serie | |
195 | - | |
196 | - # Utilisateur du materiel (destinataire du bien) | |
197 | - #- nom_user | |
198 | - | |
199 | - # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même | |
200 | - #- nom_responsable (sauf Responsable, Administration) | |
201 | - | |
202 | - #- nom_ancien_responsable | |
203 | - | |
204 | - #- resp_credit | |
205 | - | |
206 | - #- gestionnaire_id | |
207 | - | |
208 | - #- fournisseur_id | |
209 | - | |
210 | - #- organisme_id | |
211 | - | |
212 | - #- prix_ht | |
213 | - | |
214 | - #- budgets | |
215 | - | |
216 | - # #### CHAMPS ADMINISTRATIFS : #### | |
217 | - #- eotp (sauf Administration) | |
218 | - #- numero_commande (sauf Administration) | |
219 | - #- numero_laboratoire # READONLY toujours car généré automatiquement | |
220 | - #- numero_inventaire_organisme (sauf Administration) | |
221 | - #- numero_inventaire_old (sauf Administration) | |
222 | - | |
223 | - | |
224 | -# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS COMMANDE | |
225 | -# 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) | |
226 | -# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
227 | -# - Aucun champ | |
228 | -RECOMMENDED_FIELDS_AFTER_LOT0: [] | |
229 | - | |
230 | - | |
231 | - | |
232 | - | |
233 | - | |
234 | - | |
235 | - | |
236 | - | |
237 | -# ****************************************************************************** | |
238 | -# ************** LOT 1 - COMMANDE (DEMANDE D'ACHAT) (optionnel) **************** | |
239 | -# ****************************************************************************** | |
240 | - | |
241 | -# Champs OBLIGATOIRES POUR passer la COMMANDE (La commande est une action optionnelle) | |
242 | -# Attention, les champs MANDATORY_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
243 | -# - Aucun champ | |
244 | -#MANDATORY_FIELDS_FOR_LOT1: [] | |
245 | -# - Au moins un champ | |
246 | -MANDATORY_FIELDS_FOR_LOT1: | |
247 | - | |
248 | - # Infos toujours obligatoires (cachées car calculées automatiquement) | |
249 | - #'status', | |
250 | - #'tobeordered', | |
251 | - | |
252 | - #'hors_service', // O/N | |
253 | - | |
254 | - ##designation: 'Désignation' | |
255 | - | |
256 | - ##description: 'Description' | |
257 | - | |
258 | - #'permanent', | |
259 | - #'will_stay', // O/N | |
260 | - | |
261 | - ##sur_categorie_id: 'Domaine' | |
262 | - ##categorie_id: 'Catégorie' | |
263 | - | |
264 | - # - Utilisateur | |
265 | - #nom_user: "Nom de l'utilisateur de ce matériel" | |
266 | - | |
267 | - # - Acheteur | |
268 | - #nom_responsable: 'Nom du responsable' | |
269 | - # (rempli automatiquement) | |
270 | - #email_responsable: 'Email du responsable' | |
271 | - | |
272 | - # Calculé auto au moment du save() | |
273 | - #'numero_laboratoire', | |
274 | - | |
275 | - organisme_id: 'Organisme' | |
276 | - | |
277 | - prix_ht: 'Prix HT' | |
278 | - | |
279 | - # (par défaut = acheteur) | |
280 | - resp_credit: 'Responsable du crédit' | |
281 | - | |
282 | - # Gestionnaire de référence (recevra la commande) | |
283 | - gestionnaire_id: 'Gestionnaire de référence' | |
284 | - | |
285 | - # Fournisseur | |
286 | - fournisseur_id: 'Fournisseur' | |
287 | - | |
288 | - # Utilisé par la Gestion pour remplir le champ eotp | |
289 | - budgets: 'Budgets' | |
290 | - | |
291 | - # INFOS ADMINISTRATIVES | |
292 | - # - EOTP : obligatoire seulement dans LOT2 | |
293 | - | |
294 | - # - Devis joint : c'est un champ virtuel, il n'existe pas physiquement (sauf dans la table Documents) | |
295 | - DOC_DEVIS: 'Devis' | |
296 | - #DOC_BC: "Bon de Commande" | |
297 | - #DOC_BL: "Bon de Livraison" | |
298 | - #DOC_FACTURE: "Facture" | |
299 | - | |
300 | - | |
301 | - # ******* END OF MANDATORY_FIELDS_LOT1 ******** | |
302 | - | |
303 | - | |
304 | -# Liste des champs NON MODIFIABLES APRÈS la demande d'ACHAT (c'est à dire APRÈS avoir fait la "COMMANDE") | |
305 | -# Attention, les champs UNEDITABLE_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
306 | -# - Aucun champ | |
307 | -#UNEDITABLE_FIELDS_AFTER_LOT1: [] | |
308 | -# - Au moins un champ | |
309 | -UNEDITABLE_FIELDS_AFTER_LOT1: | |
310 | - | |
311 | - # #### CHAMPS GÉNÉRAUX #### | |
312 | - | |
313 | - #- designation | |
314 | - | |
315 | - #- will_stay | |
316 | - | |
317 | - #- description | |
318 | - | |
319 | - #- hors_service | |
320 | - | |
321 | - # On ne devrait pas pouvoir changer la NATURE du bien | |
322 | - # Domaine & Catégorie | |
323 | - - sur_categorie_id (sauf Administration) # Domaine | |
324 | - - categorie_id (sauf Administration) # Catégorie | |
325 | - #- sous_categorie_id | |
326 | - | |
327 | - #- groupes_thematique_id | |
328 | - | |
329 | - #- groupes_metier_id | |
330 | - | |
331 | - #- projet_id | |
332 | - | |
333 | - #- materiel_technique | |
334 | - #- materiel_administratif | |
335 | - | |
336 | - #- metrologie | |
337 | - | |
338 | - #- etiquette | |
339 | - | |
340 | - #- site_id | |
341 | - | |
342 | - #- lieu_detail | |
343 | - | |
344 | - #- date_acquisition | |
345 | - | |
346 | - #- date_reception | |
347 | - | |
348 | - # Garantie | |
349 | - #- duree_garantie | |
350 | - #- unite_duree_garantie | |
351 | - #- date_fin_garantie | |
352 | - | |
353 | - # Super Administrateur only | |
354 | - #- status | |
355 | - | |
356 | - #- numero_serie | |
357 | - | |
358 | - # Utilisateur du materiel (destinataire du bien) | |
359 | - #- nom_user | |
360 | - | |
361 | - # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même | |
362 | - #- nom_responsable (sauf Responsable, Administration) | |
363 | - | |
364 | - #- nom_ancien_responsable | |
365 | - | |
366 | - # (par défaut = acheteur) | |
367 | - - resp_credit (sauf Administration) | |
368 | - | |
369 | - - gestionnaire_id (sauf Administration) | |
370 | - | |
371 | - # Fournisseur | |
372 | - - fournisseur_id (sauf Administration) | |
373 | - | |
374 | - - organisme_id (sauf Administration) | |
375 | - | |
376 | - - prix_ht (sauf Administration) | |
377 | - | |
378 | - # Utilisé par la Gestion pour remplir le champ eotp | |
379 | - - budgets (sauf Administration) | |
380 | - | |
381 | - | |
382 | - # #### CHAMPS VIRTUELS : doc attachés #### | |
383 | - # Ces champs virtuels n'existent pas physiquement (sauf dans la table Documents) | |
384 | - # On indique ici les documents attachés à la fiche matériel, qui ne peuvent plus être ni modifiés ni supprimés | |
385 | - # - Devis | |
386 | - # Le devis attaché au matériel commandé n'est ni modifiable ni supprimable | |
387 | - - DOC_DEVIS | |
388 | - # - Bon de Commande (si un BC a été joint à la fiche, on ne peut plus le modifier ni le supprimer) | |
389 | - - DOC_BC (sauf Administration) | |
390 | - # - Bon de Livraison | |
391 | - #- DOC_BL | |
392 | - # - Facture | |
393 | - #- DOC_FACTURE | |
394 | - | |
395 | - | |
396 | - # #### CHAMPS ADMINISTRATIFS : #### | |
397 | - #- eotp (sauf Administration) | |
398 | - #- numero_commande (sauf Administration) | |
399 | - #- numero_laboratoire # READONLY toujours car généré automatiquement | |
400 | - #- numero_inventaire_organisme (sauf Administration) | |
401 | - #- numero_inventaire_old (sauf Administration) | |
402 | - | |
403 | - | |
404 | - | |
405 | -# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS COMMANDE | |
406 | -# 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) | |
407 | -# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
408 | -# - Aucun champ | |
409 | -RECOMMENDED_FIELDS_AFTER_LOT1: [] | |
410 | -#RECOMMENDED_FIELDS_AFTER_LOT1: | |
411 | - # - Etiquette posée sur le matériel | |
412 | - #etiquette: "d'imprimer l'étiquette associée et de la coller sur le matériel" | |
413 | - | |
414 | - | |
415 | - | |
416 | - | |
417 | - | |
418 | - | |
419 | - | |
420 | - | |
421 | -# *************************************************************************** | |
422 | -# ************** LOT 2 - VALIDATION (matériel livré et payé) **************** | |
423 | -# *************************************************************************** | |
424 | - | |
425 | -# Champs OBLIGATOIRES POUR VALIDER la livraison | |
426 | -# Attention, les champs MANDATORY_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
427 | -# - Aucun champ | |
428 | -#MANDATORY_FIELDS_FOR_LOT2: [] | |
429 | -# - Au moins un champ | |
430 | -MANDATORY_FIELDS_FOR_LOT2: | |
431 | - | |
432 | - #//'fournisseur_id' => 'Fournisseur', | |
433 | - #//'fournisseur' => 'Fournisseur', | |
434 | - | |
435 | - date_acquisition: "Date d'achat" | |
436 | - | |
437 | - date_reception: 'Date de livraison' | |
438 | - | |
439 | - site_id: 'Site' | |
440 | - | |
441 | - #TODO: seulement si prix > 10K€ | |
442 | - lieu_detail: 'Lieu de stockage' | |
443 | - #numero_serie: 'S/N' | |
444 | - | |
445 | - #// INFOS ADMINISTRATIVES : | |
446 | - | |
447 | - #// La Gestion doit remplir ce champ a partir des infos qui sont dans le champ "budget" (rempli par acheteur) | |
448 | - #// ligne budgétaire (sur quel(s) budget(s)) ou entité(s) dépensière(s) | |
449 | - eotp: 'Entité(s) dépensière(s) (budget(s))' | |
450 | - | |
451 | - numero_commande: 'Num. BC' | |
452 | - | |
453 | - # Docs attachés obligatoires pour valider | |
454 | - DOC_DEVIS: 'Devis' | |
455 | - #DOC_BC: "Bon de Commande" | |
456 | - #DOC_BL: "Bon de Livraison" | |
457 | - #DOC_FACTURE: "Facture" | |
458 | - | |
459 | - | |
460 | - # ******* END OF $MANDATORY_FIELDS_LOT2 ******** | |
461 | - | |
462 | - | |
463 | - | |
464 | - | |
465 | -# Champs NON OBLIGATOIRES MAIS FORTEMENT RECOMMANDÉS APRÈS VALIDATION de la livraison | |
466 | -# 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) | |
467 | -# Attention, les champs RECOMMENDED_FIELDS_XXX définis plus haut sont aussi pris en compte (donc, inutile de les répéter) | |
468 | -# - Aucun champ | |
469 | -#RECOMMENDED_FIELDS_AFTER_LOT2: [] | |
470 | -# - Au moins un champ | |
471 | -RECOMMENDED_FIELDS_AFTER_LOT2: | |
472 | - | |
473 | - | |
474 | - # - Etiquette posée sur le matériel | |
475 | - etiquette: "d'imprimer l'étiquette associée et de la coller sur le matériel" | |
476 | - | |
477 | - # - Numéro inventaire tutelles | |
478 | - # On aurait pu rendre cet élément obligatoire mais on ne peut pas l'exiger au moment de la livraison | |
479 | - # car le gestionnaire n'a cette info que lorsque "Service fait CNRS" (il récupère alors le n° inventaire "Tutelle" sur GESLAB) | |
480 | - numero_inventaire_organisme: "de renseigner le champ 'N° inventaire comptable/tutelles (Organisme)'" | |
481 | - | |
482 | - | |
483 | - # DOCS ATTACHÉS recommandés après validation | |
484 | - #DOC_DEVIS: "d'ajouter un Devis" | |
485 | - DOC_BC: "d'ajouter le Bon de Commande" | |
486 | - DOC_BL: "d'ajouter le Bon de Livraison" | |
487 | - DOC_FACTURE: "d'ajouter la Facture" | |
488 | - | |
489 | - | |
490 | - | |
491 | - | |
492 | - | |
493 | -# Liste des champs qui sont NON MODIFIABLES APRÈS la VALIDATION (livraison) | |
494 | -# Attention, les champs UNEDITABLE_FIELDS_XXX définis plus haut sont aussi pris en compte | |
495 | -# - Aucun champ | |
496 | -#UNEDITABLE_FIELDS_AFTER_LOT2: [] | |
497 | -# - Au moins un champ | |
498 | -UNEDITABLE_FIELDS_AFTER_LOT2: | |
499 | - | |
500 | - # #### CHAMPS GÉNÉRAUX #### | |
501 | - | |
502 | - #- designation | |
503 | - | |
504 | - #- will_stay | |
505 | - | |
506 | - #- description | |
507 | - | |
508 | - #- hors_service | |
509 | - | |
510 | - - sur_categorie_id | |
511 | - - categorie_id | |
512 | - | |
513 | - #- sous_categorie_id | |
514 | - | |
515 | - #- groupes_thematique_id | |
516 | - | |
517 | - #- groupes_metier_id | |
518 | - | |
519 | - #- projet_id | |
520 | - | |
521 | - #- materiel_technique | |
522 | - #- materiel_administratif | |
523 | - | |
524 | - #- metrologie | |
525 | - | |
526 | - #- etiquette | |
527 | - | |
528 | - #- site_id | |
529 | - | |
530 | - #- lieu_detail | |
531 | - | |
532 | - - date_acquisition | |
533 | - - date_reception | |
534 | - | |
535 | - # Garantie | |
536 | - #- duree_garantie | |
537 | - #- unite_duree_garantie | |
538 | - #- date_fin_garantie | |
539 | - | |
540 | - # Super Administrateur only | |
541 | - #- status | |
542 | - | |
543 | - #- numero_serie | |
544 | - | |
545 | - # Utilisateur du materiel (destinataire du bien) | |
546 | - #- nom_user | |
547 | - | |
548 | - # - Acheteur (le Créateur de la fiche) - Un role "Utilisateur" ne peut pas changer ça, c'est par défaut lui-même | |
549 | - #- nom_responsable (sauf Responsable, Administration) | |
550 | - | |
551 | - #- nom_ancien_responsable | |
552 | - | |
553 | - #- resp_credit | |
554 | - | |
555 | - #- gestionnaire_id | |
556 | - | |
557 | - #- fournisseur_id | |
558 | - | |
559 | - #- organisme_id | |
560 | - | |
561 | - #- prix_ht | |
562 | - | |
563 | - #- budgets | |
564 | - | |
565 | - | |
566 | - # #### CHAMPS ADMINISTRATIFS #### | |
567 | - | |
568 | - - eotp | |
569 | - - numero_commande | |
570 | - # READONLY toujours car généré automatiquement | |
571 | - #- numero_laboratoire | |
572 | - #- numero_inventaire_organisme | |
573 | - #- numero_inventaire_old | |
574 | - | |
575 | - | |
576 | - # DOCS ATTACHÉS qui ne sont plus ni supprimables ni modifiables | |
577 | - # - Devis | |
578 | - #- DOC_DEVIS | |
579 | - # - Bon de Commande | |
580 | - - DOC_BC | |
581 | - # - Bon de Livraison | |
582 | - - DOC_BL | |
583 | - # - Facture | |
584 | - - DOC_FACTURE | |
585 | - | |
586 | - | |
587 | - | |
588 | - | |
589 | -# ****************************************************************************** | |
590 | -# ************** LOT 3 - ARCHIVAGE (matériel à sortir ou sorti) **************** | |
591 | -# ****************************************************************************** | |
592 | - | |
593 | -# (TODO) Ce 3e niveau n'est pas encore implémenté, il est pour l'instant codé en dur dans le code | |
594 | - | |
595 | -# - Aucun champ | |
596 | -MANDATORY_FIELDS_FOR_LOT3: [] | |
597 | - | |
598 | -# - Aucun champ | |
599 | -UNEDITABLE_FIELDS_AFTER_LOT3: [] | |
600 | -# En fait, TOUS LES CHAMPS SONT READONLY SAUF : description, ... | |
601 | - | |
602 | - | |
603 | - | |
604 | - | |
605 | - | |
606 | - | |
607 | - | |
608 | - | |
609 | - | |
610 | - | |
611 | -# Astuce utilisable : | |
612 | -# Pour faire : MANDATORY_FIELDS_LOT2 = MANDATORY_FIELDS_LOT1 | |
613 | -# On fait comme ceci : | |
614 | -#MANDATORY_FIELDS_LOT1: &lot1 | |
615 | -#MANDATORY_FIELDS_LOT2: *lot1 | |
616 | - |
config/bootstrap.php
... | ... | @@ -36,6 +36,10 @@ use Yaml\Configure\Engine\YamlConfig; |
36 | 36 | */ |
37 | 37 | require __DIR__ . '/paths.php'; |
38 | 38 | |
39 | +/* EP 2021-11 : mes propres constantes */ | |
40 | +define('CONFIG_MATERIEL_FIELDS_FILE_NAME', 'app_labinvent_mandatory_fields'); | |
41 | + | |
42 | + | |
39 | 43 | // Use composer to load the autoloader. |
40 | 44 | require ROOT . DS . 'vendor' . DS . 'autoload.php'; |
41 | 45 | |
... | ... | @@ -106,17 +110,31 @@ try { |
106 | 110 | } |
107 | 111 | |
108 | 112 | // (EP 2021 09 Ajout nouveaux fichiers config pour les champs obligatoires (et les autorisations)) |
109 | -$config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields'; | |
113 | +//$config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields'; | |
110 | 114 | // Si le fichier de conf n'existe pas, on le crée en copiant le fichier par défaut |
111 | -if ( !file_exists(CONFIG.DS.$config_mandatory_fields_file_name.'.yml') ) | |
112 | - copy(CONFIG.DS.$config_mandatory_fields_file_name.'.default.yml', CONFIG.DS.$config_mandatory_fields_file_name.'.yml'); | |
115 | +//if ( !file_exists(CONFIG.DS.$config_mandatory_fields_file_name.'.yml') ) | |
116 | +//$config_matos_full_file_name = $config_matos_full_file_name_default = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME; | |
117 | +$config_matos_full_file_name = $config_matos_full_file_name_default = CONFIG_MATERIEL_FIELDS_FILE_NAME; | |
118 | +//$config_matos_full_file_name_default = $config_matos_full_file_name; | |
119 | +$config_matos_full_file_name .= '.yml'; | |
120 | +$config_matos_full_file_name_default .= '.default.yml'; | |
121 | +//if ( !file_exists($config_matos_full_file_name) ) copy($config_matos_full_file_name_default, $config_matos_full_file_name); | |
113 | 122 | try { |
114 | - Configure::config('yaml', new YamlConfig()); | |
115 | - Configure::load($config_mandatory_fields_file_name, 'yaml'); | |
123 | + Configure::config('my_yaml_engine', new YamlConfig()); | |
124 | + //Configure::load($config_mandatory_fields_file_name, 'yaml', true); | |
125 | + Configure::load(CONFIG_MATERIEL_FIELDS_FILE_NAME, 'my_yaml_engine'); | |
116 | 126 | //Configure::load('app_labinvent_mandatory_fields_IP2I', 'yaml'); |
117 | 127 | //Configure::load('app_labinvent_authorizations', 'yaml'); |
118 | 128 | } catch (\Exception $e) { |
119 | - die('config/bootstrap.php: Unable to load yaml config file'); | |
129 | + echo("<br>config/bootstrap.php: Impossible de charger le fichier de configuration des champs matériels (".CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.".yml)"); | |
130 | + echo("<br>- soit ce fichier n'est pas accessible en lecture par le serveur web (attention, il faut aussi qu'il soit accessible en écriture)"); | |
131 | + echo("<br>- soit il n'existe pas => dans ce cas, créez le en faisant une copie du fichier de configuration par défaut :"); | |
132 | + echo("<br> cd ".CONFIG); | |
133 | + echo("<br> cp $config_matos_full_file_name_default $config_matos_full_file_name"); | |
134 | + echo("<br> chown webserver_user_name $config_matos_full_file_name"); | |
135 | + echo("<br> chmod 600 $config_matos_full_file_name"); | |
136 | + echo("<br> (si vous ne voulez pas faire le chown, faite plutot un chmod 666, moins propre, mais marche aussi)"); | |
137 | + die(); | |
120 | 138 | } |
121 | 139 | |
122 | 140 | // Load an environment local configuration file. | ... | ... |
... | ... | @@ -0,0 +1,308 @@ |
1 | +<?php | |
2 | +namespace App\Controller; | |
3 | + | |
4 | +use App\Controller\AppController; | |
5 | +use App\Form\ConfigurationFieldsForm; | |
6 | +use Cake\Core\Configure; | |
7 | + | |
8 | +use Symfony\Component\Yaml\Yaml; | |
9 | + | |
10 | + | |
11 | +// modelless form : voir https://book.cakephp.org/3/en/core-libraries/form.html | |
12 | +class ConfigurationFieldsController extends AppController | |
13 | +{ | |
14 | + | |
15 | + /* | |
16 | + * @Override | |
17 | + * | |
18 | + * Initialisation des autorisations pour les actions spécifiques à ce controleur | |
19 | + * | |
20 | + */ | |
21 | + protected function setAuthorizations() { | |
22 | + | |
23 | + // On supprime les autres actions par défaut (add, view, index, find) | |
24 | + //foreach (array_keys($this->is_authorized_action[]) as $a) if ($a != 'display') unset($this->is_authorized_action[$a]); | |
25 | + $this->is_authorized_action = []; | |
26 | + | |
27 | + // admin (+) only | |
28 | + $this->setAuthorizationsForAction('index', -1, ['admin'=>0, 'super'=>0]); | |
29 | + $this->setAuthorizationsForAction('view', -1, ['admin'=>0, 'super'=>0]); | |
30 | + $this->setAuthorizationsForAction('edit', -1, ['admin'=>0, 'super'=>0]); | |
31 | + $this->setAuthorizationsForAction('resetToDefault', -1, ['admin'=>0, 'super'=>0]); | |
32 | + // tous | |
33 | + //$this->setAuthorizationsForAction('index', 0); | |
34 | + // Superadmin only : | |
35 | + //$this->setAuthorizationsForAction('index', -1, ['super'=>0]); | |
36 | + | |
37 | + } | |
38 | + | |
39 | + public function index() { | |
40 | + $this->view(); | |
41 | + } | |
42 | + | |
43 | + public function view() { | |
44 | + | |
45 | + $this->edit(true); | |
46 | + // Lecteurs configurés : 'default', 'yaml' | |
47 | + //debug(Configure::configured()); | |
48 | + | |
49 | + //$fields = Configure::readOrFail('MANDATORY_FIELDS_FOR_LOT'.$lot_num); | |
50 | + /* | |
51 | + $fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS'); | |
52 | + $this->set(compact('fields')); | |
53 | + */ | |
54 | + } | |
55 | + | |
56 | + public function resetToDefault() { | |
57 | + $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml'; | |
58 | + $config_mandatory_fields_file_name_default = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.default.yml'; | |
59 | + | |
60 | + $config_default = Yaml::parse(file_get_contents($config_mandatory_fields_file_name_default)); //parse le fichier | |
61 | + $config_default_as_yaml = Yaml::dump($config_default); //remet en yaml | |
62 | + if (! file_put_contents($config_mandatory_fields_file_name, $config_default_as_yaml) ) | |
63 | + 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"); | |
64 | + | |
65 | + $this->Flash->success("La configuration des champs de matériel a bien été réinitialisée aux valeurs par défaut"); | |
66 | + return $this->redirect(['action' => 'view']); | |
67 | + } | |
68 | + | |
69 | + | |
70 | + public function edit($READONLY=false) { | |
71 | + | |
72 | + $contact = new ConfigurationFieldsForm(); | |
73 | + //debug($contact); | |
74 | + | |
75 | + // - En mode POST | |
76 | + if ($this->request->is('post')) { | |
77 | + /* | |
78 | + * We use the execute() method to run our form’s _execute() method only when the data is valid, | |
79 | + * and set flash messages accordingly. | |
80 | + * We could have also used the validate() method to only validate the request data: | |
81 | + * $isValid = $form->validate($this->request->getData()); | |
82 | + */ | |
83 | + //debug($this->request->getData()); | |
84 | + | |
85 | + // - OK | |
86 | + if ($contact->execute($this->request->getData())) { | |
87 | + $fieldsets = $this->request->getData(); | |
88 | + //debug($data); | |
89 | + $contact->setData($fieldsets); | |
90 | + | |
91 | + // On sauvegarde le contenu de $fieldsets dans le fichier de config (array => yaml) | |
92 | + | |
93 | + //debug($contact); | |
94 | + // See : https://book.cakephp.org/3/en/development/configuration.html#writing-configuration-data | |
95 | + /* | |
96 | + Configure::write('Company.name','Pizza, Inc.'); | |
97 | + Configure::write('Company.slogan','Pizza for your body and soul'); | |
98 | + // idem : | |
99 | + Configure::write('Company', [ | |
100 | + 'name' => 'Pizza, Inc.', | |
101 | + 'slogan' => 'Pizza for your body and soul' | |
102 | + ]); | |
103 | + */ | |
104 | + //$data1 = Configure::read('MANDATORY_AND_READONLY_FIELDS'); | |
105 | + //debug($data1); | |
106 | + /* | |
107 | + Configure::write('MANDATORY_AND_READONLY_FIELDS',$data); | |
108 | + $data2 = Configure::read('MANDATORY_AND_READONLY_FIELDS'); | |
109 | + */ | |
110 | + //debug($data2); | |
111 | + //$name = $contact->getData('name'); | |
112 | + /* NE MARCHE PAS, WHY ??? | |
113 | + $config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields'; | |
114 | + if ( Configure::dump($config_mandatory_fields_file_name, 'my_yaml', ['MANDATORY_AND_READONLY_FIELDS']) ) | |
115 | + $this->Flash->success("La configuration des champs matériels a bien été sauvegardée"); | |
116 | + */ | |
117 | + //$config_mandatory_fields_file_name = CONFIG.DS.'app_labinvent_mandatory_fields'.'.yml'; | |
118 | + $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml'; | |
119 | + // Symfony YAML component : https://symfony.com/doc/current/components/yaml.html | |
120 | + /* | |
121 | + $array = Yaml::parse(file_get_contents($config_mandatory_fields_file_name)); //parse le fichier | |
122 | + debug($array); | |
123 | + $res = Yaml::dump($array); //remet en yaml | |
124 | + */ | |
125 | + $fieldsets_new = []; | |
126 | + $fieldsets_new['MANDATORY_AND_READONLY_FIELDS']=$fieldsets; | |
127 | + //debug($fieldsets_new); | |
128 | + | |
129 | + $fieldsets_as_yaml = Yaml::dump($fieldsets_new); //remet en yaml | |
130 | + //debug($res); exit; | |
131 | + if (! file_put_contents($config_mandatory_fields_file_name, $fieldsets_as_yaml) ) | |
132 | + 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"); | |
133 | + $this->Flash->success("La configuration des champs de matériel a bien été sauvegardée"); | |
134 | + return $this->redirect(['action' => 'view']); | |
135 | + } | |
136 | + | |
137 | + // - KO | |
138 | + else { | |
139 | + // Once a form has been validated you can retrieve the errors from it: | |
140 | + $errors = $form->getErrors(); // $form->errors(); // prior to 3.7.0 | |
141 | + debug($errors); | |
142 | + /* $errors contains | |
143 | + [ | |
144 | + 'email' => ['A valid email address is required'] | |
145 | + ] | |
146 | + */ | |
147 | + $this->Flash->error("La configuration n'a pas pu être enregistrée"); | |
148 | + } | |
149 | + } | |
150 | + | |
151 | + // - En mode GET (ou POST avec erreur) | |
152 | + | |
153 | + if ($this->request->is('get')) { | |
154 | + /* | |
155 | + $contact->setData([ | |
156 | + 'name' => 'John Doe', | |
157 | + 'email' => 'john.doe@example.com' | |
158 | + ]); | |
159 | + */ | |
160 | + } | |
161 | + | |
162 | + $this->set('contact', $contact); | |
163 | + | |
164 | + $fieldsets = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS'); | |
165 | + $this->set(compact('READONLY', 'fieldsets')); | |
166 | + | |
167 | + } // edit() | |
168 | + | |
169 | + | |
170 | + public function OLD_edit($READONLY=false) | |
171 | + { | |
172 | + $contact = new ConfigurationFieldsForm(); | |
173 | + //debug($contact); | |
174 | + | |
175 | + // - En mode POST | |
176 | + if ($this->request->is('post')) { | |
177 | + /* | |
178 | + * We use the execute() method to run our form’s _execute() method only when the data is valid, | |
179 | + * and set flash messages accordingly. | |
180 | + * We could have also used the validate() method to only validate the request data: | |
181 | + * $isValid = $form->validate($this->request->getData()); | |
182 | + */ | |
183 | + //debug($this->request->getData()); | |
184 | + | |
185 | + // - OK | |
186 | + if ($contact->execute($this->request->getData())) { | |
187 | + $fieldsets = $this->request->getData(); | |
188 | + //debug($data); | |
189 | + $contact->setData($fieldsets); | |
190 | + | |
191 | + /* | |
192 | + * 1) On retouche $fieldsets pour qu'il puisse être sauvegardé au format fichier texte (yaml) : | |
193 | + * | |
194 | + * Ex: | |
195 | + 'designation' => [ | |
196 | + 'selected' => '0', | |
197 | + 'labl' => 'commentaire', | |
198 | + 'roles' => [ | |
199 | + (int) 0 => 'Responsable', | |
200 | + (int) 1 => 'Administration' | |
201 | + ] | |
202 | + ], | |
203 | + * | |
204 | + * - '.selected' : si = 0 => on préfixe le nom du champ par "OFF_" | |
205 | + * => 'OFF_designation' | |
206 | + * - '.labl' : on l'ajoute entre parenthèse à la suite du nom du champ | |
207 | + * => 'OFF_designation (commentaire)' | |
208 | + * - '.roles' : on les ajoute entre parenthèse à la fin du nom du champ => | |
209 | + * => 'OFF_designation (commentaire) (sauf Responsable, Administration)' | |
210 | + */ | |
211 | + $fieldsets_new = []; | |
212 | + $fieldsets_new['MANDATORY_AND_READONLY_FIELDS']=[]; | |
213 | + //$fn = &$fieldsets_new['MANDATORY_AND_READONLY_FIELDS']; | |
214 | + foreach ($fieldsets as $fieldset_name=>$fields) { | |
215 | + $fieldsets_new['MANDATORY_AND_READONLY_FIELDS'][$fieldset_name] = []; | |
216 | + foreach ($fields as $field_name=>$attributes) { | |
217 | + $field_name_new = $field_name; | |
218 | + // - selected | |
219 | + if (! $attributes['selected'] ) | |
220 | + $field_name_new = 'OFF_'.$field_name_new; | |
221 | + // - labl | |
222 | + if ($attributes['labl']) | |
223 | + $field_name_new .= ' ('. $attributes['labl'] .')'; | |
224 | + // - roles | |
225 | + if (isset($attributes['except_roles']) && $attributes['except_roles']) | |
226 | + $field_name_new .= ' (sauf '. implode(',',$attributes['except_roles']) .')'; | |
227 | + //debug($field_name_new); | |
228 | + $fieldsets_new['MANDATORY_AND_READONLY_FIELDS'][$fieldset_name][] = $field_name_new; | |
229 | + } | |
230 | + } | |
231 | + //debug($fieldsets_new); exit; | |
232 | + | |
233 | + // 2) On sauvegarde le contenu de $fieldsets dans le fichier de config (array => yaml) | |
234 | + | |
235 | + //debug($contact); | |
236 | + // See : https://book.cakephp.org/3/en/development/configuration.html#writing-configuration-data | |
237 | + /* | |
238 | + Configure::write('Company.name','Pizza, Inc.'); | |
239 | + Configure::write('Company.slogan','Pizza for your body and soul'); | |
240 | + // idem : | |
241 | + Configure::write('Company', [ | |
242 | + 'name' => 'Pizza, Inc.', | |
243 | + 'slogan' => 'Pizza for your body and soul' | |
244 | + ]); | |
245 | + */ | |
246 | + //$data1 = Configure::read('MANDATORY_AND_READONLY_FIELDS'); | |
247 | + //debug($data1); | |
248 | + /* | |
249 | + Configure::write('MANDATORY_AND_READONLY_FIELDS',$data); | |
250 | + $data2 = Configure::read('MANDATORY_AND_READONLY_FIELDS'); | |
251 | + */ | |
252 | + //debug($data2); | |
253 | + //$name = $contact->getData('name'); | |
254 | + /* NE MARCHE PAS, WHY ??? | |
255 | + $config_mandatory_fields_file_name = 'app_labinvent_mandatory_fields'; | |
256 | + if ( Configure::dump($config_mandatory_fields_file_name, 'my_yaml', ['MANDATORY_AND_READONLY_FIELDS']) ) | |
257 | + $this->Flash->success("La configuration des champs matériels a bien été sauvegardée"); | |
258 | + */ | |
259 | + //$config_mandatory_fields_file_name = CONFIG.DS.'app_labinvent_mandatory_fields'.'.yml'; | |
260 | + $config_mandatory_fields_file_name = CONFIG.DS.CONFIG_MATERIEL_FIELDS_FILE_NAME.'.yml'; | |
261 | + // Symfony YAML component : https://symfony.com/doc/current/components/yaml.html | |
262 | + /* | |
263 | + $array = Yaml::parse(file_get_contents($config_mandatory_fields_file_name)); //parse le fichier | |
264 | + debug($array); | |
265 | + $res = Yaml::dump($array); //remet en yaml | |
266 | + */ | |
267 | + $fieldsets_new_as_yaml = Yaml::dump($fieldsets_new); //remet en yaml | |
268 | + //debug($res); exit; | |
269 | + if ( file_put_contents($config_mandatory_fields_file_name, $fieldsets_new_as_yaml) ) | |
270 | + $this->Flash->success("La configuration des champs matériels a bien été sauvegardée"); | |
271 | + return $this->redirect(['action' => 'view']); | |
272 | + } | |
273 | + | |
274 | + // - KO | |
275 | + else { | |
276 | + // Once a form has been validated you can retrieve the errors from it: | |
277 | + $errors = $form->getErrors(); // $form->errors(); // prior to 3.7.0 | |
278 | + debug($errors); | |
279 | + /* $errors contains | |
280 | + [ | |
281 | + 'email' => ['A valid email address is required'] | |
282 | + ] | |
283 | + */ | |
284 | + $this->Flash->error("La configuration n'a pas pu être enregistrée"); | |
285 | + } | |
286 | + } | |
287 | + | |
288 | + // - En mode GET (ou POST avec erreur) | |
289 | + | |
290 | + if ($this->request->is('get')) { | |
291 | + /* | |
292 | + $contact->setData([ | |
293 | + 'name' => 'John Doe', | |
294 | + 'email' => 'john.doe@example.com' | |
295 | + ]); | |
296 | + */ | |
297 | + } | |
298 | + | |
299 | + $this->set('contact', $contact); | |
300 | + | |
301 | + $fieldsets = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS'); | |
302 | + $this->set(compact('READONLY', 'fieldsets')); | |
303 | + | |
304 | + } // edit() | |
305 | + | |
306 | + | |
307 | + | |
308 | +} // end of class | |
0 | 309 | \ No newline at end of file | ... | ... |
src/Controller/MaterielsController.php
... | ... | @@ -1913,8 +1913,40 @@ class MaterielsController extends AppController { |
1913 | 1913 | } |
1914 | 1914 | */ |
1915 | 1915 | $recommended_fields = $this->Materiels->getRecommendedFieldsForMaterielStatus($materiel->status); |
1916 | - foreach ($recommended_fields as $fname => $msg) { | |
1917 | - | |
1916 | + //debug($recommended_fields); | |
1917 | + /* | |
1918 | + * Ex : | |
1919 | + [ | |
1920 | + 'etiquette' => [ | |
1921 | + 'selected' => '1', | |
1922 | + 'comment' => 'd'imprimer l'étiquette associée et de la coller sur le matériel', | |
1923 | + 'roles' => '' | |
1924 | + ], | |
1925 | + 'numero_inventaire_organisme' => [ | |
1926 | + 'selected' => '1', | |
1927 | + 'comment' => 'de renseigner le champ 'N° inventaire comptable/tutelles _Organisme_'', | |
1928 | + 'roles' => '' | |
1929 | + ], | |
1930 | + 'DOC_BC' => [ | |
1931 | + 'selected' => '1', | |
1932 | + 'comment' => 'd'ajouter le Bon de Commande', | |
1933 | + 'roles' => '' | |
1934 | + ], | |
1935 | + 'DOC_BL' => [ | |
1936 | + 'selected' => '1', | |
1937 | + 'comment' => 'd'ajouter le Bon de Livraison', | |
1938 | + 'roles' => '' | |
1939 | + ], | |
1940 | + 'DOC_FACTURE' => [ | |
1941 | + 'selected' => '1', | |
1942 | + 'comment' => 'd'ajouter la Facture', | |
1943 | + 'roles' => '' | |
1944 | + ] | |
1945 | + */ | |
1946 | + //foreach ($recommended_fields as $fname => $msg) { | |
1947 | + //foreach ($recommended_fields as $fname => $attributes) { | |
1948 | + foreach ( array_keys($recommended_fields) as $fname ) { | |
1949 | + | |
1918 | 1950 | //debug($fname); |
1919 | 1951 | // - Documents attachés (champs virtuels) |
1920 | 1952 | // DOC_DEVIS, DOC_BC, ... |
... | ... | @@ -1937,8 +1969,8 @@ class MaterielsController extends AppController { |
1937 | 1969 | |
1938 | 1970 | } |
1939 | 1971 | // Les champs restants sont les champs manquants => message flash de rappel |
1940 | - foreach ($recommended_fields as $fname => $reminder_msg) | |
1941 | - $this->Flash->set("Ce matériel est '".$entity->getNiceStatus()."' mais n'oubliez pas $reminder_msg"); | |
1972 | + foreach ($recommended_fields as $fname => $attributes) | |
1973 | + $this->Flash->set("Ce matériel est '".$entity->getNiceStatus()."' mais n'oubliez pas ".$attributes['comment']); | |
1942 | 1974 | |
1943 | 1975 | |
1944 | 1976 | } // view |
... | ... | @@ -1974,7 +2006,6 @@ class MaterielsController extends AppController { |
1974 | 2006 | // uniquement à cause de parent::add_or_edit() : |
1975 | 2007 | $entity_name=null, array $associated_entities=[], $with_parent=false) { |
1976 | 2008 | |
1977 | - //debug("ici"); exit; | |
1978 | 2009 | $this->myDebug("step 3: MaterielsController.add_or_edit()"); |
1979 | 2010 | $IS_EDIT = !$IS_ADD; |
1980 | 2011 | |
... | ... | @@ -2080,72 +2111,11 @@ class MaterielsController extends AppController { |
2080 | 2111 | $materiel->numero_laboratoire = null; |
2081 | 2112 | } |
2082 | 2113 | } |
2083 | - //debug($materiel); exit; | |
2084 | - /* | |
2085 | - // ADD | |
2086 | - if ($IS_ADD) { | |
2087 | - // 1) on crée un materiel vide | |
2088 | - $materiel = $this->Materiels->newEntity(); | |
2089 | - // - add_by_copy : COPIE de materiel (on a cliqué sur "Copier ce materiel") => id passé en argument | |
2090 | - if (isset($this->request->getAttribute('params')['pass'][0])) { | |
2091 | - // On récupère le materiel à copier et on le copie dans $materiel | |
2092 | - /S | |
2093 | - $materiel_to_copy = $this->Materiels->get($this->request->getAttribute('params')['pass'][0]); | |
2094 | - $materiel_to_copy = $materiel_to_copy->toArray(); | |
2095 | - S/ | |
2096 | - $materiel_to_copy = $this->e->toArray(); | |
2097 | - //var_dump($materiel_to_copy); | |
2098 | - ///foreach ($materiel_to_copy as $key=>$value) $materiel->$key = $value; | |
2099 | - // IMPORTANT: validate=False car sinon, les données sont validées avant la copie, | |
2100 | - // et le numero_laboratoire est vu comme invalide car déjà utilisé et doit etre unique !!! | |
2101 | - // et on a pour résultat : "le matériel n'a pas pu être ajouté" (sans savoir pourquoi !!!) | |
2102 | - $materiel = $this->Materiels->patchEntity($materiel, $materiel_to_copy, ['validate' => false]); | |
2103 | - //TODO: On pourrait traiter les erreurs de validation déjà ici | |
2104 | - if ($materiel->errors()) { | |
2105 | - // traitement | |
2106 | - } | |
2107 | - // Du coup, on supprime le champ numero_laboratoire car il va être généré automatiquement | |
2108 | - unset($materiel->numero_laboratoire); | |
2109 | - // IMPORTANT: on ne doit pas laisser l'id égal à celui du matériel copié !!! il en faut un nouveau | |
2110 | - $materiel->id = NULL; | |
2111 | - //$materiel->id = False; | |
2112 | - //unset($materiel->id); | |
2113 | - | |
2114 | - /S | |
2115 | - $attribute="[original]"; | |
2116 | - $materiel->$attribute = []; | |
2117 | - S/ | |
2118 | - //$materiel->id = FALSE; | |
2119 | - //$materiel->'[new]' => true, | |
2120 | - } | |
2121 | - // - NOUVEAU materiel (on a cliqué sur "Nouveau materiel") | |
2122 | - else { | |
2123 | - //$materiel = $this->Materiels->newEntity(); | |
2124 | - /S (EP 20200505 plus nécessaire car on utilise désormais NULL) | |
2125 | - // Set default values : "N/A" | |
2126 | - $materiel->groupes_thematique_id = 1; | |
2127 | - $materiel->groupes_metier_id = 1; | |
2128 | - $materiel->site_id = 9; | |
2129 | - S/ | |
2130 | - } | |
2131 | - } | |
2132 | - // EDIT | |
2133 | - else { | |
2134 | - /S | |
2135 | - $this->log("Edit a doc1 !", 'debug'); | |
2136 | - Log::write('debug',"Edit a doc2 !"); | |
2137 | - $this->dlog("Edit a doc1 !"); | |
2138 | - S/ | |
2139 | - $materiel = $this->Materiels->get($id, [ | |
2140 | - 'contain' => [] // load associated entities | |
2141 | - ]); | |
2142 | - //$this->myDebug($materiel); | |
2143 | - //debug($materiel); | |
2144 | - } | |
2145 | - */ | |
2146 | 2114 | |
2147 | 2115 | |
2148 | - /* SI POST... | |
2116 | + /* | |
2117 | + * SI POST... | |
2118 | + * | |
2149 | 2119 | * Les données ont été saisies et postées |
2150 | 2120 | * On va donc les sauvegarder (si ok) |
2151 | 2121 | */ |
... | ... | @@ -2154,123 +2124,32 @@ class MaterielsController extends AppController { |
2154 | 2124 | $authorized_actions = $IS_ADD ? ['post'] : ['post','patch','put']; |
2155 | 2125 | if ( $this->request->is($authorized_actions) ) { |
2156 | 2126 | |
2157 | - //debug($this->request->getData()); | |
2158 | - //exit; | |
2159 | - | |
2160 | - /* | |
2161 | - // ADD | |
2162 | - // Nouveau materiel saisi et posted | |
2163 | - ($is_add && $this->request->is('post')) | |
2164 | - | |
2165 | - || | |
2166 | - | |
2167 | - // EDIT | |
2168 | - // materiel modifié et posted | |
2169 | - ( (!$is_add) && $this->request->is(['patch','post','put']) ) | |
2170 | - */ | |
2127 | + //debug($this->request->getData()); exit; | |
2171 | 2128 | |
2172 | 2129 | // (1) On remplit $materiel avec les données de ce materiel |
2173 | 2130 | $materiel = $this->Materiels->patchEntity($materiel, $this->request->getData()); |
2174 | - | |
2175 | - /* | |
2176 | - // AVIRER | |
2177 | - // BUGFIX temporaire pour php5 !!! | |
2178 | - if ($this->isLabinventDebugMode()) { | |
2179 | - $d2 = $materiel->date_reception; | |
2180 | - $d1 = $materiel->date_acquisition; | |
2181 | - debug("d1 achat avant:"); debug($d1); | |
2182 | - debug("d2 recep avant:"); debug($d2); | |
2183 | - /S | |
2184 | - $tz = new \DateTimeZone('Europe/Paris'); | |
2185 | - $d1 = new \DateTime(strtr($d1,'/','-'),$tz); | |
2186 | - $d2 = new \DateTime(strtr($d2,'/','-'),$tz); | |
2187 | - debug("d1 achat après:"); debug($d1); | |
2188 | - debug("d2 recep après:"); debug($d2); | |
2189 | - S/ | |
2190 | - if ($d2 < $d1) debug("d2 < d1 !!!"); | |
2191 | - // $d2 > $d1 oui mais pas trop... | |
2192 | - $diff = $d2->diff($d1); | |
2193 | - //debug($diff->y); | |
2194 | - debug("diff:"); debug($diff); | |
2195 | - debug("diff->y:"); debug($diff->y); | |
2196 | - debug("diff->days:"); debug($diff->days); | |
2197 | - exit; | |
2198 | - } | |
2199 | - // FIN BUGFIX | |
2200 | - */ | |
2201 | - | |
2202 | - // ADD : Set the user_id from the session. | |
2203 | - //$materiel->user_id = $this->Auth->user('id'); | |
2204 | - // EDIT : Added: Disable modification of user_id. | |
2205 | - //'accessibleFields' => ['user_id' => false] | |
2206 | - | |
2207 | - /* (EP 7/12/20 : déjà fait dans la vue, donc inutile !!!) | |
2208 | - // (2) Si l'utilisateur courant est un "administratif" => le mettre comme gestionnaire du materiel | |
2209 | - // (tout ça pour ça !!! Faudra réduire ce bazar !) | |
2210 | - $current_user_name = $_SESSION['Auth']['User']['sn'][0]; | |
2211 | - if (in_array( | |
2212 | - $current_user_name, | |
2213 | - $usersTable | |
2214 | - ->find('list', [ | |
2215 | - 'keyField' => 'id', | |
2216 | - 'valueField' => 'nom' | |
2217 | - ]) | |
2218 | - ->where([ | |
2219 | - 'role =' => 'Administration' | |
2220 | - ]) | |
2221 | - ->toArray() | |
2222 | - )) { | |
2223 | - $materiel->gestionnaire_id = $usersTable | |
2224 | - ->find() | |
2225 | - ->where([ | |
2226 | - 'nom' => $current_user_name | |
2227 | - ]) | |
2228 | - ->first()->id; | |
2229 | - } | |
2230 | - */ | |
2231 | - | |
2232 | - | |
2131 | + //debug($materiel); | |
2132 | + | |
2233 | 2133 | /* |
2234 | 2134 | * \AV1 : Attributs OBLIGATOIRES |
2235 | 2135 | * On définit les infos obligatoires et on vérifie qu'elles sont bien présentes dans le POST |
2236 | 2136 | */ |
2237 | 2137 | |
2238 | - /* | |
2239 | - // Attributs obligatoires pour la phase COMMANDE | |
2240 | - //$LOT1 = $this->Materiels->MANDATORY_FIELDS_FOR_LOT1; | |
2241 | - $LOT1 = $this->Materiels->getMandatoryFieldsForLot(1); | |
2242 | - | |
2243 | - // Attributs obligatoires pour la phase VALIDATION (livré et payé) | |
2244 | - //$LOT2 = $this->Materiels->MANDATORY_FIELDS_FOR_LOT2; | |
2245 | - $LOT2 = $this->Materiels->getMandatoryFieldsForLot(2); | |
2246 | - | |
2247 | - //TODO 202109 | |
2248 | - // Seulement si prix > 10K€ : exiger la facture jointe et le n° série | |
2249 | - if ($materiel->prix_ht > 10000) { | |
2250 | - //$LOT2[] = 'facture jointe'; | |
2251 | - $LOT2['numero_serie'] = 'S/N'; | |
2252 | - } | |
2253 | - // LOT2 = LOT1 + LOT2; | |
2254 | - ////$LOT2 = array_merge($LOT1, $LOT2); | |
2255 | - //debug($LOT2);exit; | |
2256 | - // Champs obligatoires = LOT1 si CREATED, LOT2 sinon (>CREATED, c'est à dire VALIDATED ou plus) | |
2257 | - $mandatory_fields = ($materiel->status == 'CREATED') ? $LOT1 : $LOT2; | |
2258 | - //debug($mandatory_fields); exit; | |
2259 | - */ | |
2260 | 2138 | //$mandatory_fields = MaterielsTable::getMandatoryFieldsForMaterielStatus($materiel->status); |
2261 | 2139 | $mandatory_fields = $this->Materiels->getMandatoryFieldsForMateriel($materiel); |
2140 | + //debug($mandatory_fields); | |
2262 | 2141 | //$mandatory_fields = $this->Materiels->getMandatoryFieldsForMaterielStatus($materiel->status); |
2263 | - //debug($mandatory_fields); exit; | |
2264 | 2142 | |
2265 | 2143 | $verb = $IS_ADD ? "ajouté" : "modifié"; |
2266 | 2144 | |
2267 | 2145 | // On vérifie que les infos obligatoires sont présentes |
2268 | 2146 | // Si au moins un champ obligatoire est nul ou vide => ERROR |
2269 | - $ALL_MANDATORY_FIELDS_FOR_GIVEN = true; | |
2147 | + $ALL_MANDATORY_FIELDS_GIVEN = true; | |
2270 | 2148 | //foreach ($mandatory_fields as $fname => $fval) { |
2271 | 2149 | //print_r($materiel); |
2272 | - foreach ($mandatory_fields as $fname=>$fname_nice) { | |
2273 | - | |
2150 | + //foreach ($mandatory_fields as $fname=>$fname_nice) { | |
2151 | + foreach ($mandatory_fields as $fname=>$attributes) { | |
2152 | + | |
2274 | 2153 | /* |
2275 | 2154 | * Champs obligatoires à ignorer : |
2276 | 2155 | * - champs virtuels (n'existent pas physiquement) => DOC_XXX (DOC_DEVIS, DOC_BC, ...) |
... | ... | @@ -2282,7 +2161,7 @@ class MaterielsController extends AppController { |
2282 | 2161 | //if ( in_array($fname, ['DOC_DEVIS', 'fournisseur_id', 'etiquette', 'numero_inventaire_organisme']) ) continue; |
2283 | 2162 | |
2284 | 2163 | if ($materiel->$fname === null || $materiel->$fname == '') { |
2285 | - $ALL_MANDATORY_FIELDS_FOR_GIVEN = false; | |
2164 | + $ALL_MANDATORY_FIELDS_GIVEN = false; | |
2286 | 2165 | /* (EP 2020 03) |
2287 | 2166 | * Ce genre de ligne ($this->Flash->...) affichant un message flash en haut de page, |
2288 | 2167 | * ne fonctionnait plus à cause de bootstrap (css). |
... | ... | @@ -2292,7 +2171,8 @@ class MaterielsController extends AppController { |
2292 | 2171 | * de bootstrap, ou bootsrap-ui, ou cakephp..., à surveiller donc) |
2293 | 2172 | */ |
2294 | 2173 | //$msgError1 = "Le champ suivant est obligatoire : ".$fname_nice.' du matériel'; |
2295 | - $error_msg = "Le champ suivant est obligatoire : ".$fname_nice; | |
2174 | + //$error_msg = "Le champ suivant est obligatoire : ".$fname_nice; | |
2175 | + $error_msg = "Le champ suivant est obligatoire : ".$attributes['comment']; | |
2296 | 2176 | /////debug($msgError1); |
2297 | 2177 | $this->Flash->error($error_msg); |
2298 | 2178 | /* MARCHE PAS POURQUOI ? |
... | ... | @@ -2307,10 +2187,11 @@ class MaterielsController extends AppController { |
2307 | 2187 | ///////////////$this->Flash->error(__("Le matériel n'a pas pu être $verb")); |
2308 | 2188 | //return false; |
2309 | 2189 | break; |
2310 | - } | |
2311 | - } | |
2190 | + } // si champ obligatoire pas rempli | |
2191 | + | |
2192 | + } // foreach $mandatory_fields | |
2312 | 2193 | |
2313 | - if ($ALL_MANDATORY_FIELDS_FOR_GIVEN) { | |
2194 | + if ($ALL_MANDATORY_FIELDS_GIVEN) { | |
2314 | 2195 | |
2315 | 2196 | // (3) On l'ajoute en BD, on envoie un email, et on affiche ok sur page accueil |
2316 | 2197 | //$verb = $IS_ADD ? "ajouté" : "modifié"; |
... | ... | @@ -2342,7 +2223,8 @@ class MaterielsController extends AppController { |
2342 | 2223 | foreach ($materiel->getErrors() as $f=>$e) |
2343 | 2224 | foreach($e as $k=>$v) $this->Flash->error(__($v.' : '.$f)); |
2344 | 2225 | |
2345 | - } | |
2226 | + } // save KO | |
2227 | + | |
2346 | 2228 | else { |
2347 | 2229 | //debug($this->getCurrentEntity()); exit; |
2348 | 2230 | //debug($this->Materiels->current_entity); exit; |
... | ... | @@ -2380,7 +2262,7 @@ class MaterielsController extends AppController { |
2380 | 2262 | 'action' => 'view', |
2381 | 2263 | $id |
2382 | 2264 | ]); |
2383 | - } | |
2265 | + } // save KO | |
2384 | 2266 | |
2385 | 2267 | } // $ALL_MANDATORY_FIELDS_FOR_GIVEN |
2386 | 2268 | |
... | ... | @@ -2388,11 +2270,12 @@ class MaterielsController extends AppController { |
2388 | 2270 | |
2389 | 2271 | |
2390 | 2272 | |
2391 | - | |
2392 | - /* SINON (PAS POST) | |
2273 | + /* SINON (GET, PAS POST) | |
2393 | 2274 | * C'est la première fois qu'on vient sur cette vue, |
2394 | 2275 | * donc on va préparer le formulaire de saisie) |
2395 | 2276 | */ |
2277 | + //debug($materiel); exit; | |
2278 | + | |
2396 | 2279 | |
2397 | 2280 | |
2398 | 2281 | /* |
... | ... | @@ -2709,6 +2592,7 @@ class MaterielsController extends AppController { |
2709 | 2592 | 'ARCHIVED' => 'ARCHIVED' |
2710 | 2593 | ]; |
2711 | 2594 | $entity = $materiel; |
2595 | + //debug($entity); | |
2712 | 2596 | $this->set(compact( |
2713 | 2597 | 'IS_ADD', |
2714 | 2598 | 'mail_responsable', |
... | ... | @@ -2738,8 +2622,10 @@ class MaterielsController extends AppController { |
2738 | 2622 | 'gestionnaires' |
2739 | 2623 | )); |
2740 | 2624 | |
2741 | - | |
2742 | - $this->set('readonlyFields', $this->getUneditableFieldsForMaterielStatus($materiel->status)); | |
2625 | + $readonlyFields = $this->getUneditableFieldsForMaterielStatus($materiel->status); | |
2626 | + $this->set(compact('readonlyFields')); | |
2627 | + //debug($materiel->status); | |
2628 | + //debug($readonlyFields); | |
2743 | 2629 | //$this->set('readonlyFields', $IS_ADD ? [] : $this->getUneditableFieldsForMaterielStatus($materiel->status)); |
2744 | 2630 | //debug($this->Materiels->getUneditableFieldsForMaterielStatus($status)); exit; |
2745 | 2631 | //$this->set('readonlyFields', $IS_ADD ? [] : $this->Materiels->getUneditableFieldsForMaterielStatus($materiel->status)); |
... | ... | @@ -2767,11 +2653,12 @@ class MaterielsController extends AppController { |
2767 | 2653 | if ($this->USER_IS_SUPERADMIN()) return []; |
2768 | 2654 | |
2769 | 2655 | $uneditable_fields = $this->Materiels->getUneditableFieldsForMaterielStatus($materiel_status); |
2770 | - foreach ($uneditable_fields as $fname=>$except_list) { | |
2656 | + //foreach ($uneditable_fields as $fname=>$except_list) { | |
2657 | + foreach ($uneditable_fields as $fname=>$attributes) { | |
2771 | 2658 | // S'il y a une exception, voir si elle concerne le USER courant, sinon supprimer ce champ $fname |
2772 | - if ($except_list) { | |
2659 | + if ($attributes['except_roles']) { | |
2773 | 2660 | //debug($except_list); |
2774 | - if ($this->currentUserRoleInList($except_list)) unset($uneditable_fields[$fname]); | |
2661 | + if ($this->currentUserRoleInList($attributes['except_roles'])) unset($uneditable_fields[$fname]); | |
2775 | 2662 | //debug("remove $fname"); |
2776 | 2663 | } |
2777 | 2664 | } |
... | ... | @@ -3051,10 +2938,11 @@ class MaterielsController extends AppController { |
3051 | 2938 | |
3052 | 2939 | // Attributs obligatoires pour la phase COMMANDE (LOT1) |
3053 | 2940 | $mandatoryFields = $this->Materiels->getMandatoryFieldsForLot(1); |
2941 | + //debug($mandatoryFields); | |
3054 | 2942 | $ACTION = 'ordonner la commande de'; |
3055 | 2943 | |
3056 | 2944 | // Si au moins un champ obligatoire est nul ou vide => ERROR |
3057 | - foreach ($mandatoryFields as $fname => $fnicename) { | |
2945 | + foreach ($mandatoryFields as $fname => $attributes) { | |
3058 | 2946 | |
3059 | 2947 | // Doc attaché obligatoire ? (champ virtuel) |
3060 | 2948 | //if (strtoupper($fname) == 'DOC_DEVIS') { |
... | ... | @@ -3085,7 +2973,7 @@ class MaterielsController extends AppController { |
3085 | 2973 | $fval = $materiel->$fname; |
3086 | 2974 | if ($fval === null || $fval == '') { |
3087 | 2975 | //$msgError1 = "Pour $ACTION ce matériel, le champ suivant ne doit pas être vide : ".$fnicename.' du matériel'; |
3088 | - $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $fnicename); | |
2976 | + $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $attributes['comment']); | |
3089 | 2977 | $this->Flash->error($error_msg); |
3090 | 2978 | // Utile ??? (plante les tests) |
3091 | 2979 | ////$this->e->setError($fname, 'Ce champ ne doit pas être vide'); |
... | ... | @@ -3108,6 +2996,7 @@ class MaterielsController extends AppController { |
3108 | 2996 | if ($newStatus == 'VALIDATED') { |
3109 | 2997 | // Attributs obligatoires pour la phase VALIDATION (livré et payé) (LOT2) |
3110 | 2998 | $mandatoryFields = $this->Materiels->getMandatoryFieldsForLot(2); |
2999 | + //$mandatoryFields = $this->Materiels->getCategoryFieldsForLot('MANDATORY_FIELDS_FOR_LOT', 2) | |
3111 | 3000 | //$mandatoryFields = $this->Materiels->MANDATORY_FIELDS_FOR_LOT2; |
3112 | 3001 | //debug($mandatoryFields);exit; |
3113 | 3002 | /* |
... | ... | @@ -3142,7 +3031,7 @@ class MaterielsController extends AppController { |
3142 | 3031 | */ |
3143 | 3032 | |
3144 | 3033 | // Si au moins un champ obligatoire est nul ou vide => ERROR |
3145 | - foreach ($mandatoryFields as $fname => $fnicename) { | |
3034 | + foreach ($mandatoryFields as $fname => $attributes) { | |
3146 | 3035 | |
3147 | 3036 | $ACTION = 'valider'; |
3148 | 3037 | |
... | ... | @@ -3184,7 +3073,8 @@ class MaterielsController extends AppController { |
3184 | 3073 | * de bootstrap, ou bootsrap-ui, ou cakephp..., à surveiller donc) |
3185 | 3074 | */ |
3186 | 3075 | //$msgError1 = "Pour $ACTION ce matériel, le champ suivant ne doit pas être vide : ".$fnicename.' du matériel'; |
3187 | - $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $fnicename); | |
3076 | + //debug($fname); | |
3077 | + $error_msg = sprintf($ERROR_MSG_EMPTY_FIELD, $ACTION, $attributes['comment']); | |
3188 | 3078 | $this->Flash->error($error_msg); |
3189 | 3079 | //debug($error_msg); |
3190 | 3080 | ... | ... |
src/Controller/PagesController.php
... | ... | @@ -70,6 +70,7 @@ class PagesController extends AppController |
70 | 70 | { |
71 | 71 | $this->myDebug("step 0A (specific): PagesController.initialize()"); |
72 | 72 | parent::initialize(); |
73 | + $this->modelClass = false; | |
73 | 74 | // On autorise l'action add SANS authentification (unauthenticated) |
74 | 75 | //$this->Auth->allow(['add']); |
75 | 76 | //$this->LdapAuth->allow(['display']); | ... | ... |
src/Controller/StatsController.php
... | ... | @@ -61,7 +61,7 @@ class StatsController extends AppController |
61 | 61 | 'nice_name'=>"Temps connexion cumulé (h)", 'f'=>'getHourMnSecForDuration'], |
62 | 62 | 'connex_nb'=>['nice_name'=>"Nb connexions"], |
63 | 63 | 'connexDurAvg'=>[ |
64 | - 'nice_name'=>"Durée connexion moyenne (sur année)", 'f'=>'getHourMnSecForDuration'] | |
64 | + 'nice_name'=>"Durée connexion moyenne (sur 1 an)", 'f'=>'getHourMnSecForDuration'] | |
65 | 65 | ], |
66 | 66 | ['Users'], |
67 | 67 | false, false, | ... | ... |
src/Controller/SurCategoriesController.php
... | ... | @@ -256,6 +256,8 @@ class SurCategoriesController extends AppController |
256 | 256 | $surCategory = $this->SurCategories->get($id, [ |
257 | 257 | 'contain' => [] |
258 | 258 | ]); |
259 | + | |
260 | + // En mode POST | |
259 | 261 | if ($this->request->is([ |
260 | 262 | 'patch', |
261 | 263 | 'post', |
... | ... | @@ -274,10 +276,14 @@ class SurCategoriesController extends AppController |
274 | 276 | $this->Flash->error(__('Le domaine n\'a pas pu être édité.')); |
275 | 277 | } |
276 | 278 | } |
279 | + | |
280 | + // En mode GET (ou alors POST après une erreur) | |
277 | 281 | $this->set(compact('surCategory')); |
282 | + /* (EP) inutile sauf si json | |
278 | 283 | $this->set('_serialize', [ |
279 | 284 | 'surCategory' |
280 | 285 | ]); |
286 | + */ | |
281 | 287 | } |
282 | 288 | |
283 | 289 | /** | ... | ... |
... | ... | @@ -0,0 +1,47 @@ |
1 | +<?php | |
2 | +// in src/Form/ContactForm.php | |
3 | +namespace App\Form; | |
4 | + | |
5 | +use Cake\Form\Form; | |
6 | +use Cake\Form\Schema; | |
7 | +use Cake\Validation\Validator; | |
8 | +use Cake\Core\Configure; | |
9 | + | |
10 | +// modelless form : voir https://book.cakephp.org/3/en/core-libraries/form.html | |
11 | +class ConfigurationFieldsForm extends Form | |
12 | +{ | |
13 | + /* | |
14 | + protected function _buildSchema(Schema $schema) | |
15 | + { | |
16 | + //$fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS'); | |
17 | + //debug($fields); | |
18 | + //foreach ($fields as $fname=>$val) debug($fname); | |
19 | + | |
20 | + return $schema | |
21 | + ->addField('name', 'string') | |
22 | + ->addField('email', ['type' => 'string']) | |
23 | + ->addField('body', ['type' => 'text']); | |
24 | + } | |
25 | + */ | |
26 | + | |
27 | + /* | |
28 | + public function validationDefault(Validator $validator) | |
29 | + { | |
30 | + $validator->add('name', 'length', [ | |
31 | + 'rule' => ['minLength', 5], | |
32 | + 'message' => 'A name is required' | |
33 | + ])->add('email', 'format', [ | |
34 | + 'rule' => 'email', | |
35 | + 'message' => 'A valid email address is required', | |
36 | + ]); | |
37 | + | |
38 | + return $validator; | |
39 | + } | |
40 | + */ | |
41 | + | |
42 | + protected function _execute(array $data) | |
43 | + { | |
44 | + // Send an email. | |
45 | + return true; | |
46 | + } | |
47 | +} | |
0 | 48 | \ No newline at end of file | ... | ... |
src/Model/Table/MaterielsTable.php
... | ... | @@ -252,60 +252,84 @@ class MaterielsTable extends AppTable |
252 | 252 | * - LOT0 total = [] + LOT0 |
253 | 253 | * - LOT1 total = LOT0 + LOT1 |
254 | 254 | * - LOT2 total = LOT1 + LOT2 |
255 | + * | |
256 | + * Algo RECURSIF | |
255 | 257 | */ |
258 | + public static function getCategoryFieldsForLot($categ, $lot_num, $categ_initial=null) { | |
259 | + //debug($lot_num); | |
260 | + // ex: $categ = RECOMMENDED_FIELDS_AFTER_LOT | |
261 | + //if ($lot_num < 0) return $categ_initial ? Configure::readOrFail('UNEDITABLE_FIELDS') : []; | |
262 | + if ($lot_num < 0) return $categ_initial ? Configure::readOrFail("MANDATORY_AND_READONLY_FIELDS.$categ_initial") : []; | |
263 | + | |
264 | + // Recursive call | |
265 | + $base_fields = self::getCategoryFieldsForLot($categ, $lot_num-1, $categ_initial); | |
266 | + $base_fields = self::removeUnselectedFieldsFrom($base_fields); | |
267 | + //debug($base_fields); | |
268 | + | |
269 | + //$new_fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS.RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num); | |
270 | + $new_fields = Configure::readOrFail("MANDATORY_AND_READONLY_FIELDS.$categ".$lot_num); | |
271 | + $new_fields = self::removeUnselectedFieldsFrom($new_fields); | |
272 | + //debug($new_fields); | |
273 | + | |
274 | + //debug($new_fields); | |
275 | + return array_merge($base_fields, $new_fields); | |
276 | + } | |
277 | + | |
278 | + | |
279 | + | |
280 | + public static function removeUnselectedFieldsFrom($fields) { | |
281 | + /* | |
282 | + * Exemple : | |
283 | + Before remove : | |
284 | + { | |
285 | + designation: { selected: '0', comment: commentaire, roles: '' }, | |
286 | + description: { selected: '0', comment: autre, roles: '' }, | |
287 | + nom_responsable: { selected: '1', comment: 'nom du responsable', | |
288 | + } | |
289 | + After remove : | |
290 | + { | |
291 | + nom_responsable: { selected: '1', comment: 'nom du responsable', | |
292 | + } | |
293 | + */ | |
294 | + //$fields_selected = []; | |
295 | + foreach ($fields as $field_name => $attributes) { | |
296 | + if ( $field_name=='fieldset_comment' || !$attributes['selected'] ) unset($fields[$field_name]); | |
297 | + } | |
298 | + return $fields; | |
299 | + } | |
300 | + | |
256 | 301 | public static function getMandatoryFieldsForLot($lot_num) { |
302 | + return self::getCategoryFieldsForLot('MANDATORY_FIELDS_FOR_LOT', $lot_num); | |
257 | 303 | /* |
258 | 304 | $specific_constant_name = "MANDATORY_FIELDS_FOR_LOT1_".self::getLabName(); |
259 | 305 | $mandatory_fields_lot1 = defined($specific_constant_name) ? constant($specific_constant_name) : MANDATORY_FIELDS_FOR_LOT1; |
260 | 306 | return $mandatory_fields_lot1; |
261 | 307 | */ |
308 | + /* | |
262 | 309 | if ($lot_num < 0) return []; |
263 | 310 | $base_fields = self::getMandatoryFieldsForLot($lot_num-1); |
264 | 311 | $new_fields = Configure::readOrFail('MANDATORY_FIELDS_FOR_LOT'.$lot_num); |
265 | 312 | //debug($new_fields); |
266 | 313 | return array_merge($base_fields, $new_fields); |
314 | + */ | |
267 | 315 | } |
316 | + // RECURSIF | |
268 | 317 | public static function getRecommendedFieldsForLot($lot_num) { |
318 | + return self::getCategoryFieldsForLot('RECOMMENDED_FIELDS_AFTER_LOT', $lot_num); | |
319 | + /* | |
269 | 320 | if ($lot_num < 0) return []; |
270 | 321 | $base_fields = self::getRecommendedFieldsForLot($lot_num-1); |
271 | - $new_fields = Configure::readOrFail('RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num); | |
322 | + $new_fields = Configure::readOrFail('MANDATORY_AND_READONLY_FIELDS.RECOMMENDED_FIELDS_AFTER_LOT'.$lot_num); | |
272 | 323 | //debug($new_fields); |
273 | 324 | return array_merge($base_fields, $new_fields); |
325 | + */ | |
274 | 326 | } |
275 | - | |
276 | - // (EP 2021 10) | |
277 | - public static function list_to_dict($uneditable_fields) { | |
278 | - $dict = []; | |
279 | - foreach ($uneditable_fields as $f) { | |
280 | - $except_roles = []; | |
281 | - $except_str = '(sauf'; | |
282 | - $pos0 = strpos($f, '('); | |
283 | - $pos = strpos($f, $except_str); | |
284 | - // 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 | |
285 | - if ($pos0 !== false) { | |
286 | - $error_msg = "Erreur dans le fichier de configuration des champs non modifiables"; | |
287 | - // EXCEPTION si parenthèse début mais pas suivie du mot-clé 'sauf' | |
288 | - if ($pos === false) | |
289 | - 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'"); | |
290 | - // EXCEPTION si pas de parenthèse finale, ou role mal orthographié | |
291 | - //$except_list = trim( substr($f, $pos + strlen($except_str), -1) ); | |
292 | - if ( substr($f, -1) != ')' ) | |
293 | - throw new \Exception("$error_msg : il manque une parenthèse à la fin de la ligne '$f'"); | |
294 | - $except_roles = str_replace(" ", "", substr($f, $pos + strlen($except_str), -1) ); | |
295 | - $except_roles = explode(',', $except_roles); | |
296 | - foreach ($except_roles as $role) if (! self::isValidRole($role)) | |
297 | - throw new \Exception("$error_msg : le role '$role' est mal orthographié dans la ligne '$f'"); | |
298 | - $f = trim( substr($f,0,$pos) ); | |
299 | - } | |
300 | - $dict[$f] = $except_roles; | |
301 | - } | |
302 | - return $dict; | |
303 | - } | |
304 | - | |
305 | 327 | // (EP 2021 09) fonction récursive : |
306 | 328 | // => champs readonly pour le lot N = champs readonly pour le lot N-1 + champs readonly pour le lot N : |
307 | 329 | public static function getUneditableFieldsForLot($lot_num) { |
308 | - | |
330 | + return self::getCategoryFieldsForLot('UNEDITABLE_FIELDS_AFTER_LOT', $lot_num, 'UNEDITABLE_FIELDS'); | |
331 | + /* | |
332 | + | |
309 | 333 | // Si N = -1 => on retourne la liste initiale de champs readonly (fin de la récursivité) |
310 | 334 | //if ($lot_num < 0) return []; |
311 | 335 | if ($lot_num < 0) return self::list_to_dict( Configure::readOrFail('UNEDITABLE_FIELDS') ); |
... | ... | @@ -323,10 +347,57 @@ class MaterielsTable extends AppTable |
323 | 347 | // => Somme des 2 (champs readonly pour le lot N-1 + champs readonly pour le lot N) |
324 | 348 | //return array_unique(array_merge($base_uneditable_fields, $new_uneditable_fields)); |
325 | 349 | return array_merge($base_uneditable_fields, $new_uneditable_fields); |
350 | + */ | |
326 | 351 | |
327 | 352 | } |
328 | 353 | |
329 | 354 | |
355 | + public static function separateFieldNameAndExceptedRoles($f) { | |
356 | + $except_roles = []; | |
357 | + $except_str = '(sauf'; | |
358 | + $pos0 = strpos($f, '('); | |
359 | + $pos = strpos($f, $except_str); | |
360 | + // 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 | |
361 | + if ($pos0 !== false) { | |
362 | + $error_msg = "Erreur dans le fichier de configuration des champs non modifiables"; | |
363 | + | |
364 | + // EXCEPTION si parenthèse début mais pas suivie du mot-clé 'sauf' | |
365 | + /* | |
366 | + if ($pos === false) | |
367 | + 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'"); | |
368 | + */ | |
369 | + if ($pos !== false) { | |
370 | + | |
371 | + // EXCEPTION si pas de parenthèse finale, ou role mal orthographié | |
372 | + //$except_list = trim( substr($f, $pos + strlen($except_str), -1) ); | |
373 | + if ( substr($f, -1) != ')' ) | |
374 | + throw new \Exception("$error_msg : il manque une parenthèse à la fin de la ligne '$f'"); | |
375 | + | |
376 | + $except_roles = str_replace(" ", "", substr($f, $pos + strlen($except_str), -1) ); | |
377 | + $except_roles = explode(',', $except_roles); | |
378 | + foreach ($except_roles as $role) if (! self::isValidRole($role)) | |
379 | + throw new \Exception("$error_msg : le role '$role' est mal orthographié dans la ligne '$f'"); | |
380 | + | |
381 | + $f = trim( substr($f,0,$pos) ); | |
382 | + } | |
383 | + } | |
384 | + //return [$f=>$except_roles]; | |
385 | + return ['name'=>$f, 'roles'=>$except_roles]; | |
386 | + } | |
387 | + | |
388 | + // (EP 2021 10) | |
389 | + public static function list_to_dict($uneditable_fields) { | |
390 | + $dict = []; | |
391 | + foreach ($uneditable_fields as $f) { | |
392 | + //$dict[$f] = $except_roles; | |
393 | + $fieldNameAndExceptedRoles = self::separateFieldNameAndExceptedRoles($f); | |
394 | + $dict[$fieldNameAndExceptedRoles['name']] = $fieldNameAndExceptedRoles['except_roles']; | |
395 | + } | |
396 | + return $dict; | |
397 | + } | |
398 | + | |
399 | + | |
400 | + | |
330 | 401 | /* |
331 | 402 | public static function getMandatoryFieldsLot1() { |
332 | 403 | /S |
... | ... | @@ -353,7 +424,13 @@ class MaterielsTable extends AppTable |
353 | 424 | $fields = self::getMandatoryFieldsForMaterielStatus($status); |
354 | 425 | // Seulement si prix > 10K€ : exiger la facture jointe et le n° série et lieu de stockage précis |
355 | 426 | if ($status == 'VALIDATED' && $mat->prix_ht && $mat->prix_ht > 10000) { |
356 | - $fields['numero_serie'] = 'S/N'; | |
427 | + //$fields['numero_serie'] = 'S/N'; | |
428 | + /* | |
429 | + $fields['numero_serie'] = [ | |
430 | + //'selected'=>'1', | |
431 | + 'comment'=>'S/N' | |
432 | + ]; | |
433 | + */ | |
357 | 434 | //TODO 202109 |
358 | 435 | //$fields[] = 'lieu stockage'; |
359 | 436 | //$fields[] = 'facture jointe'; |
... | ... | @@ -361,7 +438,9 @@ class MaterielsTable extends AppTable |
361 | 438 | return $fields; |
362 | 439 | } |
363 | 440 | public static function getMandatoryFieldsForMaterielStatus($status) { |
364 | - | |
441 | + //return self::getCategoryFieldsForMaterielStatus('MANDATORY_FIELDS_FOR_LOT', $status); | |
442 | + return self::getCategoryFieldsForMaterielStatus('MANDATORY', $status); | |
443 | + /* | |
365 | 444 | if (is_null($status)) $status='CREATED'; |
366 | 445 | // On recup le LOT qui convient au status courant du matos |
367 | 446 | //$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2); |
... | ... | @@ -375,9 +454,12 @@ class MaterielsTable extends AppTable |
375 | 454 | //debug($fields); |
376 | 455 | |
377 | 456 | return $fields; |
457 | + */ | |
378 | 458 | } |
379 | 459 | public static function getUneditableFieldsForMaterielStatus($status) { |
380 | - | |
460 | + //return self::getCategoryFieldsForMaterielStatus('UNEDITABLE_FIELDS_AFTER_LOT', $status); | |
461 | + return self::getCategoryFieldsForMaterielStatus('UNEDITABLE', $status); | |
462 | + /* | |
381 | 463 | if (is_null($status)) $status='CREATED'; |
382 | 464 | // On recup le LOT qui convient au status courant du matos |
383 | 465 | //$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2); |
... | ... | @@ -390,12 +472,19 @@ class MaterielsTable extends AppTable |
390 | 472 | $fields = self::getUneditableFieldsForLot($lot_num); |
391 | 473 | |
392 | 474 | return $fields; |
475 | + */ | |
393 | 476 | } |
394 | 477 | public static function getRecommendedFieldsForMaterielStatus($status) { |
395 | - return self::getFieldsCategoryForMaterielStatus('RECOMMENDED', $status); | |
478 | + //return self::getCategoryFieldsForMaterielStatus('RECOMMENDED', $status); | |
479 | + //return self::getCategoryFieldsForMaterielStatus('RECOMMENDED_FIELDS_AFTER_LOT', $status); | |
480 | + return self::getCategoryFieldsForMaterielStatus('RECOMMENDED', $status); | |
396 | 481 | } |
397 | - public static function getFieldsCategoryForMaterielStatus($fields_categ, $status) { | |
398 | - $func_name = "get".ucfirst($fields_categ)."FieldsForLot"; // getUneditableFieldsForLot() | |
482 | + | |
483 | + public static function getCategoryFieldsForMaterielStatus($categ, $status) { | |
484 | + //$func_name = "get".ucfirst($fields_categ)."FieldsForLot"; // getUneditableFieldsForLot() | |
485 | + //$func_name = "getCategoryFieldsForLot"; // getUneditableFieldsForLot() | |
486 | + $func_name = "get".ucfirst($categ)."FieldsForLot"; // getUneditableFieldsForLot() | |
487 | + | |
399 | 488 | if (is_null($status)) $status='CREATED'; |
400 | 489 | // On recup le LOT qui convient au status courant du matos |
401 | 490 | //$fields = ($status == 'CREATED') ? self::getMandatoryFieldsForLot(1) : self::getMandatoryFieldsForLot(2); |
... | ... | @@ -1560,6 +1649,9 @@ class MaterielsTable extends AppTable |
1560 | 1649 | $fournisseur_asis = $entity->fournisseur ? $entity->fournisseur['name'] : ''; |
1561 | 1650 | // Enlever les espaces superflus |
1562 | 1651 | $fournisseur = trim($fournisseur_asis); |
1652 | + //debug($fournisseur); | |
1653 | + //debug($entity); | |
1654 | + | |
1563 | 1655 | |
1564 | 1656 | // Si champ fournisseur obligatoire, vérification qu'il est bien rempli (ou emission d'une erreur) |
1565 | 1657 | //if (IP2I && $entity->fournisseur && $fournisseur == '') { |
... | ... | @@ -1688,6 +1780,7 @@ class MaterielsTable extends AppTable |
1688 | 1780 | } // ssi changement |
1689 | 1781 | // Finalement, on supprime les champs 'fournisseur' car sinon erreur de sauvegarde, |
1690 | 1782 | // (normal ces champs n'existent pas dans materiel) |
1783 | + //debug($entity); exit; | |
1691 | 1784 | unset($entity->fournisseur_orig); |
1692 | 1785 | unset($entity->fournisseur); |
1693 | 1786 | //debug($entity); exit; | ... | ... |
... | ... | @@ -0,0 +1,149 @@ |
1 | +<?php | |
2 | + | |
3 | +use App\Model\Table\MaterielsTable; | |
4 | + | |
5 | +$DEBUG = false; | |
6 | +//$DEBUG = true; | |
7 | + | |
8 | + | |
9 | +// Variables générales cakephp | |
10 | +$_REQUEST = $_REQUEST; | |
11 | +$_COOKIE = $_COOKIE; | |
12 | +$_ENV = $_ENV; | |
13 | +//debug($_COOKIE); | |
14 | +/* | |
15 | +[ | |
16 | + 'CAKEPHP' => 'hiraigc02eb46spa06iiog6tvh' | |
17 | +] | |
18 | +*/ | |
19 | +//debug($_ENV); | |
20 | +//debug($_REQUEST); | |
21 | + | |
22 | +// Variables passées par le controleur | |
23 | +$CAN_EDIT = true; | |
24 | +$CAN_EDIT = $CAN_EDIT; | |
25 | +$READONLY = $READONLY; | |
26 | +$contact = $contact; | |
27 | +$fieldsets = $fieldsets; | |
28 | +//debug($fieldsets); | |
29 | + | |
30 | +$icon = $READONLY ? '' : "<i class='icon-edit'></i>"; | |
31 | +//$icon = $READONLY ? '' : "<i class='icon-pencil'></i>"; | |
32 | +//$end = $READONLY ? "(Visualisation)" : "(Modification)"; | |
33 | +//$title = "Configuration des champs obligatoires ou non modifiables de la fiche Matériel $end"; | |
34 | +$title = "Configuration des champs obligatoires ou non modifiables de la fiche Matériel"; | |
35 | +echo "<br><h2>$icon $title</h2><br><br>"; | |
36 | +/* | |
37 | + Autres icones possibles : | |
38 | +echo "<br><h2><i class='icon-edit'></i> $title</h2><br><br>"; | |
39 | +echo "<br><h2><i class='icon-list'></i> $title</h2><br><br>"; | |
40 | +echo "<br><h2><i class='icon-plus'></i> $title</h2><br><br>"; | |
41 | +echo "<br><h2><i class='icon-pencil'></i> $title</h2><br><br>"; | |
42 | +echo "<br><h2><i class='icon-trash'></i> $title</h2><br><br>"; | |
43 | +*/ | |
44 | + | |
45 | +if ($READONLY && $CAN_EDIT) $this->MyHelper->echoEditButton(); | |
46 | +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); | |
47 | + | |
48 | +//echo $this->Html->icon('pencil'); | |
49 | + | |
50 | +echo $this->Form->create($contact); | |
51 | + | |
52 | + if (!$READONLY) { | |
53 | + echo $this->Form->button('Enregistrer', ['class'=>'btn btn-outline-success', 'type'=>'submit']); | |
54 | + //echo $this->Form->button('Submit'); | |
55 | + echo '<br><br>'; | |
56 | + } | |
57 | + | |
58 | + //echo $this->Form->button($this->Html->icon('pencil'), ['escape' => false]); | |
59 | + // ...can be easily rewritten as: | |
60 | + //echo $this->Form->button('i:pencil'); | |
61 | + | |
62 | + foreach ($fieldsets as $fieldset_name => $fields) { | |
63 | + $controls = []; | |
64 | + | |
65 | + //foreach ($fields as $field) { | |
66 | + foreach ($fields as $field_name => $attributes) { | |
67 | + | |
68 | + if ($field_name=='fieldset_comment') continue; | |
69 | + | |
70 | + // champ activé ou désactivé | |
71 | + $checked = $attributes['selected']; | |
72 | + $comment = $attributes['comment']; | |
73 | + $except_roles = isset($attributes['except_roles']) ? $attributes['except_roles'] : []; | |
74 | + | |
75 | + $name = "$fieldset_name.$field_name"; | |
76 | + | |
77 | + // - CHAMP de la table materiel : Checkbox pour le dé/sélectionner | |
78 | + $label = $field_name; | |
79 | + if ($READONLY) { | |
80 | + if ($comment) $label .= ' ('.$comment.')'; | |
81 | + if ($except_roles) $label .= ' (sauf '.implode(', ',$except_roles).')'; | |
82 | + } | |
83 | + $controls["$name.selected"] = [ | |
84 | + 'type' => 'checkbox', | |
85 | + //'hiddenField' => true, | |
86 | + 'label' => $label, | |
87 | + 'checked' => $checked, | |
88 | + 'disabled' => $READONLY, | |
89 | + //'readonly' =>$READONLY, | |
90 | + //'readonly' => 'readonly', | |
91 | + ]; | |
92 | + | |
93 | + // (EDIT ONLY) | |
94 | + // - Label associé au champ (entre parenthèses) doit pouvoir être modifié | |
95 | + if (!$READONLY) $controls["$name.comment"] = [ | |
96 | + //'type' => 'input', | |
97 | + 'label' => false, | |
98 | + 'val' => $comment, | |
99 | + //'size' => 20, | |
100 | + //'disabled' => $READONLY, | |
101 | + //'readonly' => $READONLY, | |
102 | + ]; | |
103 | + | |
104 | + // (EDIT ONLY) | |
105 | + $fieldsets_with_roles = ['UNEDITABLE_FIELDS','UNEDITABLE_FIELDS_AFTER_LOT0', 'UNEDITABLE_FIELDS_AFTER_LOT1', 'UNEDITABLE_FIELDS_AFTER_LOT2']; | |
106 | + // - ROLES exceptés (select multiple list) | |
107 | + //if (!$READONLY && $field_name!='HAS_ORDER_BUTTON') | |
108 | + if ( !$READONLY && in_array($fieldset_name, $fieldsets_with_roles) ) $controls["$name.except_roles"] = [ | |
109 | + 'type' => 'select', | |
110 | + 'label' => '(excepté pour les rôles)', | |
111 | + //'options' => ['<aucune exception>', 'user', 'admin', 'resp'], | |
112 | + //'options' => ['Utilisateur', 'Responsable', 'Administration'], | |
113 | + 'options' => [ | |
114 | + ['text' => 'Utilisateur', 'value' => 'Utilisateur'], | |
115 | + ['text' => 'Responsable', 'value' => 'Responsable'], | |
116 | + ['text' => 'Administration', 'value' => 'Administration'], | |
117 | + ], | |
118 | + //'val' => ['Responsable', 'Utilisateur'], | |
119 | + 'val' => $except_roles, | |
120 | + 'multiple' => 'checkbox', | |
121 | + //'size' => 20, | |
122 | + 'disabled' => $READONLY, | |
123 | + ]; | |
124 | + | |
125 | + } // foreach $fields | |
126 | + | |
127 | + // https://api.cakephp.org/3.5/class-Cake.View.Helper.FormHelper.html#_controls | |
128 | + $DEBUG && debug($controls); | |
129 | + $fieldset_name_with_comment = $fieldset_name; | |
130 | + if ( isset($fields['fieldset_comment']) ) $fieldset_name_with_comment .= ' ('. $fields['fieldset_comment'] .')'; | |
131 | + echo $this->Form->controls($controls, ['legend' => $fieldset_name_with_comment.' :']); | |
132 | + | |
133 | + } // foreach $fieldsets | |
134 | + | |
135 | + /* | |
136 | + echo $this->Form->control('name'); | |
137 | + echo $this->Form->control('email'); | |
138 | + echo $this->Form->control('body'); | |
139 | + */ | |
140 | + | |
141 | + if (!$READONLY) | |
142 | + echo $this->Form->button('Enregistrer', ['class'=>'btn btn-outline-success', 'type'=>'submit']); | |
143 | + //echo $this->Form->button('Submit'); | |
144 | + | |
145 | + | |
146 | +echo $this->Form->end(); | |
147 | + | |
148 | +if ($READONLY && $CAN_EDIT) $this->MyHelper->echoEditButton(); | |
149 | + | ... | ... |
src/Template/Materiels/index.ctp
... | ... | @@ -525,7 +525,7 @@ $displayLegend = function() { |
525 | 525 | <i style='color:black'>noir=livré (validé)</i> ;" |
526 | 526 | //<i style='color:red'>rouge=à sortir</i> ; |
527 | 527 | ." <i style='color:blue'>bleu=archivé</i> ; |
528 | - (couleur date : <i style='color:red'>rouge=fin garantie</i>, <i style='color:orange'>orange=< 1 an</i>) | |
528 | + (couleur date : <i style='color:red'>rouge=fin garantie</i>, <i style='color:orange'>orange=<1 an</i>) | |
529 | 529 | </i></p>"; |
530 | 530 | }; |
531 | 531 | ... | ... |
src/Template/Pages/about.ctp
1 | 1 | <div class="index col-lg-12"> |
2 | + | |
2 | 3 | <?php |
3 | 4 | $softwareName = "LABINVENT"; |
4 | 5 | |
6 | +echo '<br/>'; | |
5 | 7 | echo '<h2><i class="icon-idea"></i> A PROPOS DU LOGICIEL ' . $softwareName . '</h2>'; |
6 | 8 | |
9 | +echo '<br/>'; | |
10 | +echo '<a href="/pages/changes">Changements faits sur le logiciel (nouveautés et historique)</a>'; | |
11 | + | |
12 | +echo '<br/><br/>'; | |
13 | +echo '<a href="https://tinyurl.com/labinvent">Documentation générale</a>'; | |
14 | + | |
15 | +echo '<br/><br/>'; | |
16 | +echo '<a href="' . $this->request->webroot . 'doc/userguide/labinvent2_userguide.pdf">Guide utilisateur</a>'; | |
17 | +echo '<br/><br/>'; | |
18 | + | |
19 | + | |
20 | + | |
7 | 21 | /* |
8 | 22 | echo <<<"EOD" |
9 | 23 | <section id="cadre" class="col-lg-12"> |
... | ... | @@ -34,8 +48,12 @@ Licence GPL (http://www.gnu.org/copyleft/gpl.html)<br><br> |
34 | 48 | EOD; |
35 | 49 | */ |
36 | 50 | |
51 | +?> | |
37 | 52 | |
38 | -echo '<section id="cadre" class="col-lg-12">'; | |
53 | + | |
54 | +<section id="cadre" class="col-lg-12"> | |
55 | + | |
56 | +<?php | |
39 | 57 | |
40 | 58 | // On lit le fichier /WWWROOT/../LICENSE |
41 | 59 | $wwwroot_dir = new Cake\Filesystem\Folder(WWW_ROOT); |
... | ... | @@ -75,7 +93,7 @@ $lines = new LimitIterator($f, $line_num_from); |
75 | 93 | //$lines_reversed = array_reverse(iterator_to_array($lines)); |
76 | 94 | $lines = iterator_to_array($lines); |
77 | 95 | foreach ($lines as $line) { |
78 | - echo $line.'<br><br>'; | |
96 | + echo $line.'<br>'; | |
79 | 97 | //if (mb_strpos($line, "$level: ") !== FALSE) echo $line.'<br><br>'; |
80 | 98 | //if (mb_strpos($line, 'Info: ') !== FALSE) echo $line.'<br><br>'; |
81 | 99 | //if (mb_strpos($line, '/materiels/edit/') !== FALSE) echo $line.'<br><br>'; |
... | ... | @@ -84,18 +102,10 @@ foreach ($lines as $line) { |
84 | 102 | // Close file |
85 | 103 | $f=null; |
86 | 104 | |
87 | -echo '</section>'; | |
88 | - | |
89 | - | |
90 | -echo '<br/>'; | |
91 | -echo '<a href="/pages/changes">Changements faits sur le logiciel (nouveautés et historique)</a>'; | |
105 | +?> | |
92 | 106 | |
93 | -echo '<br/><br/>'; | |
94 | -echo '<a href="https://tinyurl.com/labinvent">Documentation générale</a>'; | |
107 | +</section> | |
95 | 108 | |
96 | -echo '<br/><br/>'; | |
97 | -echo '<a href="' . $this->request->webroot . 'doc/userguide/labinvent2_userguide.pdf">Guide utilisateur</a>'; | |
98 | -?> | |
99 | 109 | </div> |
100 | 110 | |
101 | 111 | <!-- | ... | ... |
src/Template/Pages/home_app.ctp
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | //debug($this->viewVars); |
5 | 5 | $configuration = $configuration; |
6 | 6 | $USER_IS_RESPONSABLE = $USER_IS_RESPONSABLE; |
7 | +$USER_IS_SUPERADMIN = $USER_IS_SUPERADMIN; | |
7 | 8 | $HAS_ORDER_BUTTON = $HAS_ORDER_BUTTON; |
8 | 9 | |
9 | 10 | |
... | ... | @@ -123,6 +124,12 @@ echo $SEP; |
123 | 124 | echo '<a href="/pages/stats">Statistiques sur les matériels</a>'; |
124 | 125 | echo '</td></tr>'; |
125 | 126 | |
127 | + if ($USER_IS_SUPERADMIN) { | |
128 | + echo '<tr><td>'; | |
129 | + echo '<a href="/stats">Statistiques sur les connexions utilisateurs</a>'; | |
130 | + echo '</td></tr>'; | |
131 | + } | |
132 | + | |
126 | 133 | echo $TABLE_END; |
127 | 134 | |
128 | 135 | ... | ... |
src/Template/Pages/tools.ctp
... | ... | @@ -52,7 +52,7 @@ $no_limit_mode = $no_limit_mode; |
52 | 52 | |
53 | 53 | |
54 | 54 | |
55 | - // - Page configuration | |
55 | + // - Page configuration Générale | |
56 | 56 | //if ($role == 'Super Administrateur') : |
57 | 57 | if ($USER_IS_SUPERADMIN) |
58 | 58 | $this->MyHelper->echoMenuItemWithIcon("config.png", "Configuration générale", 'configurations','view'); |
... | ... | @@ -66,7 +66,13 @@ $no_limit_mode = $no_limit_mode; |
66 | 66 | echo '</td></tr>'; |
67 | 67 | */ |
68 | 68 | //endif; |
69 | - | |
69 | + | |
70 | + // - Page configuration des champs obligatoires et readonly | |
71 | + if ($USER_IS_ADMIN_OR_MORE) | |
72 | + $this->MyHelper->echoMenuItemWithIcon("config.png", "Configuration des champs obligatoires et readonly", 'configuration-fields','index'); | |
73 | + | |
74 | + | |
75 | + // Configuration des listes | |
70 | 76 | if ($USER_IS_ADMIN_OR_MORE) |
71 | 77 | $this->MyHelper->echoMenuItemWithIcon("config2.png", "Gérer le contenu variable de l'application", 'pages','tools_sm'); |
72 | 78 | ... | ... |
src/View/Helper/MyHelperHelper.php
... | ... | @@ -203,7 +203,9 @@ class MyHelperHelper extends Helper { |
203 | 203 | public function echoActionButton ( |
204 | 204 | $icon_class, $buttonStyle, $title, |
205 | 205 | $action, $id, $controller=null, // si controleur null =>controleur par défaut |
206 | - $other_args=[], $tip='', $confirmMessage='', $moreButtonStyle='' | |
206 | + $other_args=[], $tip='', | |
207 | + $confirmMessage='', $moreButtonStyle='', | |
208 | + $with_confirm=false | |
207 | 209 | ) { |
208 | 210 | |
209 | 211 | //if ($controller=='') $controller='materiels'; |
... | ... | @@ -212,28 +214,67 @@ class MyHelperHelper extends Helper { |
212 | 214 | $controllerArgs['action'] = $action; |
213 | 215 | $controllerArgs[] = $id; |
214 | 216 | foreach ($other_args as $other_arg) $controllerArgs[] = $other_arg; |
215 | - echo $this->Html->link( | |
216 | - __("<i class=$icon_class></i>$title"), | |
217 | - $controllerArgs, | |
218 | - /* | |
219 | - [ | |
220 | - 'controller' => $controller, | |
221 | - 'action' => $action, | |
222 | - $id, | |
223 | - $other_args | |
224 | - ], | |
225 | - */ | |
226 | - [ | |
227 | - 'title' => $tip, | |
228 | - 'escape' => false, | |
229 | - 'onclick' => 'return true;', | |
230 | - //'style' => 'margin-right: 10px'.$moreButtonStyle, | |
231 | - 'style' => $buttonStyle, | |
232 | - 'confirm' => $confirmMessage | |
233 | - ] | |
217 | + | |
218 | + // Avec confirmation (avant de déclencher l'action) | |
219 | + if ($with_confirm) { | |
220 | + if (!$confirmMessage) $confirmMessage = __("Êtes-vous sur de vouloir $title cette entité ?"); | |
221 | + echo $this->Form->postLink(__("<i class='$icon_class'></i>$title"), | |
222 | + $controllerArgs, | |
223 | + [ | |
224 | + 'title' => $title, | |
225 | + //'style' => $buttonStyle, | |
226 | + 'style' => 'margin-left: 10px', | |
227 | + 'escape' => false, | |
228 | + 'confirm' => $confirmMessage, | |
229 | + //'confirm' => $confirmMessage | |
230 | + //'confirm' => __("Êtes-vous sur de vouloir $title cette entité ?"), | |
231 | + //'confirm' => __('Êtes-vous sur de vouloir supprimer # {0}?', $suivi->id) | |
232 | + ]); | |
233 | + } | |
234 | + | |
235 | + // Sans confirmation (action directe) | |
236 | + else { | |
237 | + echo $this->Html->link( | |
238 | + __("<i class=$icon_class></i>$title"), | |
239 | + $controllerArgs, | |
240 | + /* | |
241 | + [ | |
242 | + 'controller' => $controller, | |
243 | + 'action' => $action, | |
244 | + $id, | |
245 | + $other_args | |
246 | + ], | |
247 | + */ | |
248 | + [ | |
249 | + 'title' => $tip, | |
250 | + 'escape' => false, | |
251 | + 'onclick' => 'return true;', | |
252 | + //'style' => 'margin-right: 10px'.$moreButtonStyle, | |
253 | + 'style' => $buttonStyle, | |
254 | + //'confirm' => $confirmMessage ? $confirmMessage : $tip, | |
255 | + ] | |
256 | + ); | |
257 | + } | |
258 | + | |
259 | + } | |
260 | + | |
261 | + | |
262 | + public function echoEditButton () { $this->echoButtonForAction('icon-pencil', 'edit', 'Editer', 'Modifier'); } | |
263 | + | |
264 | + public function echoButtonForAction ($icon_class, $action, $label, $tooltip, $with_confirm=false) { | |
265 | + //$icon_class = 'icon-pencil'; | |
266 | + $buttonStyle = 'margin-right: 10px'; | |
267 | + echo '<div id="boutons" class="actions" style="margin-bottom:20px; width:100%; float:none; padding:5px 0;">'; | |
268 | + $this->echoActionButton($icon_class, $buttonStyle, | |
269 | + " $label", $action, null, null, [], $tooltip, | |
270 | + '', '', | |
271 | + $with_confirm | |
234 | 272 | ); |
273 | + echo "</div>"; | |
235 | 274 | } |
236 | 275 | |
276 | + | |
277 | + | |
237 | 278 | public function echoDeleteButton ( |
238 | 279 | $title, |
239 | 280 | $id, $controller=null, // si controleur null =>controleur par défaut | ... | ... |