Commit 997b1d412d96597b784a63809bfdf472aea47102

Authored by Etienne Pallier
1 parent 42151650
Exists in master and in 1 other branch dev

/pages/stats migré dans /materiels/stats et transformé en simple alias

- et aussi bugfix pour IRAP seulement (vieux mysql et vieux php5 !)

v5.4.1-3.7.9
@@ -13,6 +13,12 @@ CHANGEMENTS @@ -13,6 +13,12 @@ CHANGEMENTS
13 13
14 14
15 ------- 15 -------
  16 +29/11/2021 NEWS#7 (v5.4) :
  17 +
  18 +- Partitionnement possible des matériels par site
  19 +
  20 +
  21 +-------
16 22/11/2021 NEWS#6 (v5.3.4) : 22 22/11/2021 NEWS#6 (v5.3.4) :
17 23
18 - Champs obligatoires, modifiables, et readonly, désormais configurables via page web 24 - Champs obligatoires, modifiables, et readonly, désormais configurables via page web
@@ -367,8 +373,6 @@ Commencer à implémenter le nouveau workflow v5 : @@ -367,8 +373,6 @@ Commencer à implémenter le nouveau workflow v5 :
367 *) 373 *)
368 Relance auto lors de suivis périodiques 374 Relance auto lors de suivis périodiques
369 375
370 - *) Validation multiple ne marche plus  
371 -  
372 *) DOMPDF : pb Qrcode absent sur fiche pdf (mais présent sur page web), alors que le QrCode est bien généré et que le chemin dans le pdf est OK !!! 376 *) DOMPDF : pb Qrcode absent sur fiche pdf (mais présent sur page web), alors que le QrCode est bien généré et que le chemin dans le pdf est OK !!!
373 Par contre, ok avec FPDF 377 Par contre, ok avec FPDF
374 378
@@ -503,26 +507,10 @@ Warning (2): Cannot modify header information - headers already sent by (output @@ -503,26 +507,10 @@ Warning (2): Cannot modify header information - headers already sent by (output
503 TODO : 507 TODO :
504 508
505 - besoin IP2I/LMA : 509 - besoin IP2I/LMA :
506 -=> restreindre l’accès de certains équipements du LMA aux utilisateurs du LMA seulement et qu'ils ne soient pas visibles ou consultables par tous les utilisateurs IP2I  
507 -=> Implémentation possible :  
508 -2 possibilités :  
509 - - Définir LMA dans la liste des "Sites" => mais ça correspond pas vraiment à la notion de site (lieu géographique)  
510 - - Ajouter une nouvelle notion de "Département"  
511 -- Associer les matériels sensibles à ce Site (ou Dépt), et cocher la case "materiel sensible"  
512 -- Associer les utilisateurs du LMA à ce Site (ou Dépt)  
513 -=> Régle : les matériels sensibles ne sont vus que par les utilisateurs du même Site (ou Dépt) (ici LMA) :  
514 - pour materiels/view(/edit/delete) => le user courant ne peut pas voir un materiel "sensible" qui n'est pas du même Site (Dépt) que lui 510 - pour materiels/view(/edit/delete) => le user courant ne peut pas voir un materiel "sensible" qui n'est pas du même Site (Dépt) que lui
515 - pour materiels/index et /find et /export => il faut exclure les matos "sensibles" qui ne sont pas du même site que le user courant 511 - pour materiels/index et /find et /export => il faut exclure les matos "sensibles" qui ne sont pas du même site que le user courant
516 - materiels/index : on peut ajouter un filtre "Site" (et Dépt), et un filtre "tous/matos sensible/matos non sensible" 512 - materiels/index : on peut ajouter un filtre "Site" (et Dépt), et un filtre "tous/matos sensible/matos non sensible"
517 513
518 -- add_or_edit() générique  
519 -  
520 -- fusionner elem/button_add_edit et MyHelper echoActionButton...  
521 -(ne garder que elem/)  
522 -- séparer elem/button_add, button_edit, button_delete, et button_tout_court (générique)  
523 -  
524 -- short_role AppController ligne 819 => généraliser  
525 -  
526 - prévoir une alerte quand on save un champ qui n'est pas dans la BD (genre resp_credit...) 514 - prévoir une alerte quand on save un champ qui n'est pas dans la BD (genre resp_credit...)
527 515
528 - gérer les liens url automatiquement dans champ description (rendre cliquable) 516 - gérer les liens url automatiquement dans champ description (rendre cliquable)
@@ -535,26 +523,30 @@ TODO : @@ -535,26 +523,30 @@ TODO :
535 523
536 524
537 525
  526 +- GENERICITÉ & REFACTORISATION :
538 527
  528 + - add_or_edit() générique
  529 +
  530 + - fusionner elem/button_add_edit et MyHelper echoActionButton...
  531 + (ne garder que elem/)
  532 + - séparer elem/button_add, button_edit, button_delete, et button_tout_court (générique)
539 533
  534 + - short_role AppController ligne 819 => généraliser
540 535
  536 + - emprunts/index generique
  537 + - documents/index generique
541 538
  539 + - ProjetsController minimaliste, doit juste étendre AppController avec un minimum de changement
542 540
  541 + - fusionner groupe thematique et metier (et projet ?) :
  542 + => faire hériter les Controller et les Table d'une meme superclasse GroupController et GroupTable
  543 + => avoir un seul template
  544 + => c'est vraiment stupide d'avoir 2 classes qui font la meme chose...
543 545
544 -- emprunts/index generique  
545 -- documents/index generique  
546 -  
547 -- ProjetsController minimaliste, doit juste étendre AppController avec un minimum de changement  
548 -  
549 -- add_edit generic 546 + - Utiliser les vues "index" des entités associées pour la vue "view" de materiel (et suivi) :
  547 + => éviter la redondance, le contenu est pratiquement le meme (???, sauf que les colonnes ne sont pas triables)
550 548
551 -- fusionner groupe thematique et metier (et projet ?) :  
552 - => faire hériter les Controller et les Table d'une meme superclasse GroupController et GroupTable  
553 - => avoir un seul template  
554 - => c'est vraiment stupide d'avoir 2 classes qui font la meme chose...  
555 549
556 -- Utiliser les vues "index" des entités associées pour la vue "view" de materiel (et suivi) :  
557 - => éviter la redondance, le contenu est pratiquement le meme (???, sauf que les colonnes ne sont pas triables)  
558 550
559 - Bien préciser quels sont les champs obligatoires avec une asterisque (et pour chaque LOT) 551 - Bien préciser quels sont les champs obligatoires avec une asterisque (et pour chaque LOT)
560 552
@@ -578,13 +570,6 @@ Vues génériques (index et view) : @@ -578,13 +570,6 @@ Vues génériques (index et view) :
578 - Suivis.statut => "en cours" ou "à terminer" => à calculer auto 570 - Suivis.statut => "en cours" ou "à terminer" => à calculer auto
579 571
580 572
581 - *)  
582 - Rendre modifiable la config via page web "Gérer les champs obligatoires"  
583 - - OFF_nom_du_champ : 'libellé'  
584 - - Restaurer la config par défaut  
585 - - Réactiver une variable : OFF_nom_du_champ => nom_du_champ  
586 -  
587 -  
588 saisir les personnes du gt2i et de tous les groupes... 573 saisir les personnes du gt2i et de tous les groupes...
589 574
590 groupe.users associés : ajouter "(responsable)" when relevant 575 groupe.users associés : ajouter "(responsable)" when relevant
@@ -593,21 +578,12 @@ comment faire un tri sur la dernière colonne des stats (connexDurAvg) ? @@ -593,21 +578,12 @@ comment faire un tri sur la dernière colonne des stats (connexDurAvg) ?
593 578
594 erreur download depuis page documents/ (ou depuis vue du matériel) sur inventirap : erreur 404 (action impossible) 579 erreur download depuis page documents/ (ou depuis vue du matériel) sur inventirap : erreur 404 (action impossible)
595 580
596 -TODO config fields :  
597 -- réadapter lecture config à new file format  
598 -- compléter le fichier config avec tous les champs possibles à chaque lot !!!  
599 -- fichier read-write par web server  
600 -- ./UPDATE cral et ip2i + new config file  
601 -- pub  
602 -- soigner la présentation du form (peu lisible now)  
603 -  
604 581
605 - - (b) Bugfix fournisseur perdu (et champ vide qui n'est plus modifiable !) après validation du matos 582 +- (b) Bugfix fournisseur perdu (et champ vide qui n'est plus modifiable !) après validation du matos
606 (quand il manque un champ pour valider), et pourtant bien enregistré dans listes des fournisseurs 583 (quand il manque un champ pour valider), et pourtant bien enregistré dans listes des fournisseurs
607 584
608 585
609 586
610 -config + jolie : fieldset dépliable et joli (voir echoSectionStart() de MyHelperHelper)  
611 587
612 Utiliser les champs 'comment' de la config pour les labels des champs dans materiels/view et /add_edit 588 Utiliser les champs 'comment' de la config pour les labels des champs dans materiels/view et /add_edit
613 589
@@ -619,9 +595,16 @@ Ne pas autoriser la commande via url si le bouton order est désactivé dans la @@ -619,9 +595,16 @@ Ne pas autoriser la commande via url si le bouton order est désactivé dans la
619 ... 595 ...
620 596
621 597
  598 +- Quelle est cette action ? le mail est un peu court... (ajout par copie ?)
  599 +Titre "Ajout de matériel(s)"
  600 +Nathalie Oziol a ajouté des matériels (action 'add')
  601 +Vous recevez ce message car vous êtes concerné(e) par cette action effectuée sur l'inventaire des matériels du laboratoire
  602 +(vous êtes l'utilisateur du matériel, ou bien le gestionnaire, ou encore le responsable thématique, métier ou projet)
  603 +(ou alors, vous êtes dans la liste mail spécifique gérée via la page de configuration du logiciel LabInvent).
  604 +
  605 +
622 606
623 Gestion multi-sites : 607 Gestion multi-sites :
624 -- matos.index : doit enlever les matos "sensibles" et qui ont un site différent du user  
625 - matos.view : interdit si matos "sensible" a un site différent du user 608 - matos.view : interdit si matos "sensible" a un site différent du user
626 - find() : par défaut, enlever les matos "sensibles" et qui ont un site différent du user 609 - find() : par défaut, enlever les matos "sensibles" et qui ont un site différent du user
627 - gestionnaires (admin) (et superadmin) continuent d'avoir accès à tout 610 - gestionnaires (admin) (et superadmin) continuent d'avoir accès à tout
@@ -630,6 +613,11 @@ Gestion multi-sites : @@ -630,6 +613,11 @@ Gestion multi-sites :
630 ======= CHANGES ======= 613 ======= CHANGES =======
631 614
632 ------- 615 -------
  616 +29/11/2021 v5.4.1-3.7.9
  617 + - (i) /pages/stats migré dans /materiels/stats et transformé en simple alias
  618 + - (b) bugfix pour IRAP seulement (vieux mysql pourri et vieux php5 pourri !!!)
  619 +
  620 +-------
633 29/11/2021 v5.4.0-3.7.9 621 29/11/2021 v5.4.0-3.7.9
634 - (e) Partitionnement des matériels par site opérationnel (multi-sites) => liste des matériels filtrée 622 - (e) Partitionnement des matériels par site opérationnel (multi-sites) => liste des matériels filtrée
635 - (b) Bugfix action sur plusieurs matos : 623 - (b) Bugfix action sur plusieurs matos :
@@ -53,7 +53,7 @@ Logiciel testé et validé sur les configurations suivantes : @@ -53,7 +53,7 @@ Logiciel testé et validé sur les configurations suivantes :
53 -------------------------------------------------------------------------------------------- 53 --------------------------------------------------------------------------------------------
54 54
55 Date: 29/11/2021 55 Date: 29/11/2021
56 -Version: v5.4.0-3.7.9 56 +Version: v5.4.1-3.7.9
57 57
58 58
59 HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes) 59 HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes)
src/Controller/MaterielsController.php
@@ -457,6 +457,9 @@ class MaterielsController extends AppController { @@ -457,6 +457,9 @@ class MaterielsController extends AppController {
457 * 457 *
458 */ 458 */
459 459
  460 + // - Action 'stats' (bugfix) => autorisée à tous
  461 + $this->setAuthorizationsForAction('stats', 0);
  462 +
460 // - Action 'execSqlRequestForBugfix' (bugfix) => autorisé seulement à superadmin 463 // - Action 'execSqlRequestForBugfix' (bugfix) => autorisé seulement à superadmin
461 $this->setAuthorizationsForAction('execSqlRequestForBugfix (bugfix)', -1, [ 464 $this->setAuthorizationsForAction('execSqlRequestForBugfix (bugfix)', -1, [
462 'super' => 0, 465 'super' => 0,
@@ -1413,7 +1416,11 @@ class MaterielsController extends AppController { @@ -1413,7 +1416,11 @@ class MaterielsController extends AppController {
1413 //debug($current_user->nom); 1416 //debug($current_user->nom);
1414 //debug($current_user->site_id); 1417 //debug($current_user->site_id);
1415 //debug($materiels); exit; 1418 //debug($materiels); exit;
1416 - $materiels = $materiels->find('filteredForUserSite', ['user_site_id' => $current_user->site_id]); 1419 + if ($this->confLabinvent->labNameShort) {
  1420 + $labshortname = $this->confLabinvent->labNameShort;
  1421 + if ($labshortname != 'IRAP')
  1422 + $materiels = $materiels->find('filteredForUserSite', ['user_site_id' => $current_user->site_id]);
  1423 + }
1417 //$materiels = $materiels->find('filteredForUserSite', ['user_site_id' => null]); 1424 //$materiels = $materiels->find('filteredForUserSite', ['user_site_id' => null]);
1418 //foreach ($materiels as $m) debug($m->id); 1425 //foreach ($materiels as $m) debug($m->id);
1419 //debug($materiels->count()); 1426 //debug($materiels->count());
@@ -3315,6 +3322,404 @@ class MaterielsController extends AppController { @@ -3315,6 +3322,404 @@ class MaterielsController extends AppController {
3315 // $this->sendEmail($this->Materiels->get($id)); 3322 // $this->sendEmail($this->Materiels->get($id));
3316 } 3323 }
3317 3324
  3325 + public function stats() {
  3326 +
  3327 + /*
  3328 + return $this->redirect([
  3329 + 'controller' => 'pages',
  3330 + 'action' => 'stats',
  3331 + ]);
  3332 + */
  3333 +
  3334 + // créer des FAKE DATA pour tester la fonctionnalité ?
  3335 + $TEST = true;
  3336 + $TEST = false;
  3337 +
  3338 + // Nb années demandées par l'utilisateur
  3339 + $nbyears = $this->request->getQuery('nbyears');
  3340 +
  3341 + // Initialisation des variables nécessaires
  3342 + // - Données Totales (complètes) (tronquées à $nbyears)
  3343 + $tot = [
  3344 + 'CREATED' => (int) 1,
  3345 + 'VALIDATED' => (int) 0,
  3346 + 'TOBEARCHIVED' => (int) 0,
  3347 + 'ARCHIVED' => (int) 0,
  3348 + 'suivis' => (int) 0,
  3349 + 'prets' => (int) 0
  3350 + ];
  3351 + // - Donées Moyennes
  3352 + $avg = [
  3353 + 'CREATED' => (int) 1,
  3354 + 'VALIDATED' => (int) 0,
  3355 + 'TOBEARCHIVED' => (int) 0,
  3356 + 'ARCHIVED' => (int) 0,
  3357 + 'suivis' => (int) 0,
  3358 + 'prets' => (int) 0
  3359 + ];
  3360 + // - Année en cours
  3361 + $now = new \DateTime('now');
  3362 + //debug($now);
  3363 + // 2020 en 2020
  3364 + $current_year = (int) $now->format('Y');
  3365 + // - Données par Année
  3366 + $years =
  3367 + [
  3368 + $current_year => [
  3369 + 'CREATED' => (int) 1,
  3370 + 'VALIDATED' => (int) 0,
  3371 + 'TOBEARCHIVED' => (int) 0,
  3372 + 'ARCHIVED' => (int) 0,
  3373 + 'suivis' => (int) 0,
  3374 + 'prets' => (int) 0
  3375 + ]
  3376 + ];
  3377 +
  3378 + // Tables
  3379 + $materiels = TableRegistry::getTableLocator()->get('Materiels');
  3380 + $suivis = TableRegistry::getTableLocator()->get('Suivis');
  3381 + $prets = TableRegistry::getTableLocator()->get('Emprunts');
  3382 + $associated_entities = ['suivis','prets'];
  3383 + $fk = 'materiel_id';
  3384 +
  3385 + // Tous les matos qui ont une date d'achat non nulle
  3386 + $all_matos = $materiels->find()->where(['year(date_acquisition) >' => 0]);
  3387 +
  3388 + // On ne fait pas de stats s'il n'y a aucun matériel dans la BD
  3389 + if ($all_matos->count() == 0) {
  3390 + $year_min = $current_year;
  3391 + //$nbyears = 0;
  3392 + $this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'avg', 'years'));
  3393 + return;
  3394 + }
  3395 +
  3396 + // - Année min
  3397 + //$year_min = $materiels->find()->min(['year(date_acquisition)']);
  3398 + //$matos_year_min = $materiels->find()->where(['year(date_acquisition) >' => 0])
  3399 + $matos_year_min = $all_matos->cleanCopy()->min(function($matos) {
  3400 + return $matos->date_acquisition->format('Y');
  3401 + });
  3402 + $year_min = (int) $matos_year_min->date_acquisition->format('Y');
  3403 +
  3404 + // - Nb années au total : au moins 1
  3405 + $nbyears_max = $current_year - $year_min + 1;
  3406 +
  3407 + // $nbyears demandé par l'utilisateur, par défaut TOUTES
  3408 + $nbyears = ( is_numeric($nbyears) && $nbyears>0 ) ? round($nbyears) : $nbyears_max;
  3409 + //debug($nbyears);
  3410 +
  3411 + // - Nb annnées à traiter (entre 1 et $nbyears_max)
  3412 + // ($nbyears=null si pas passé en paramètre)
  3413 + // ($nbyears='' si passé en paramètre mais sans valeur '?nbyears=')
  3414 + //$nbyears = $nbyears ? abs((int)$nbyears) : $nbyears_max;
  3415 + //debug($nbyears);
  3416 + $nbyears = min($nbyears,$nbyears_max);
  3417 + //debug($nbyears);
  3418 + //debug($nbyears);
  3419 + // Si on est au max (avec max>2), on enlève la 1ère et la dernière années (car a priori incomplètes)
  3420 + //sif ($nbyears==$nbyears_max && $nbyears>2) $nbyears -= 2;
  3421 + // Nouvelle année min
  3422 + $year_min = $current_year-$nbyears + 1;
  3423 +
  3424 + // Nouveau $all_matos, en tronquant à $nbyears
  3425 + $all_matos = $materiels->find()
  3426 + ->where(['year(date_acquisition) <=' => $current_year])
  3427 + ->where(['year(date_acquisition) >=' => $year_min]);
  3428 + $all_matos_ids = $all_matos->cleanCopy()->select(['id']);
  3429 +
  3430 + /*
  3431 + $statuses = [
  3432 + 'CREATED' => 'created',
  3433 + 'VALIDATED' => 'date_validated',
  3434 + 'ARCHIVED' => 'date_archived'
  3435 + ];
  3436 + */
  3437 + $statuses = [ 'CREATED', 'VALIDATED', 'TOBEARCHIVED', 'ARCHIVED' ];
  3438 +
  3439 + // - tot : Données Totales (complètes) (tronquées à $nbyears)
  3440 + foreach ($statuses as $status) {
  3441 + $all_matos_copy = $all_matos->cleanCopy();
  3442 + // Tous les matos qui ont une date d'achat non nulle
  3443 + if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]);
  3444 + $tot[$status] = $all_matos_copy->count();
  3445 + }
  3446 + // Suivis et Prets
  3447 + // Nb materiels qui ont des suivis (i.e. qui ont au moins 1 suivi)
  3448 + foreach ($associated_entities as $e) {
  3449 + //$nb_matos_suivis = $suivis->find()
  3450 + $tot[$e] = $$e->find()
  3451 + // materiel_id not null
  3452 + ->where(["$fk >" => 0])
  3453 + ->select([$fk])
  3454 + ->distinct([$fk])
  3455 + ->where(["$fk IN" => $all_matos_ids])
  3456 + ->count();
  3457 + }
  3458 +
  3459 + /*
  3460 + // - tot2 : Données Totales Partielles (= tot sauf 1ère et dernière années)
  3461 + $all_matos2 = $materiels
  3462 + ->find()
  3463 + ->where(['year(date_acquisition) <' => $current_year])
  3464 + ->where(['year(date_acquisition) >' => $current_year-$nbyears]);
  3465 + $all_matos_ids2 = $all_matos2->cleanCopy()->select(['id']);
  3466 +
  3467 + $tot2 = [];
  3468 + foreach ($statuses as $status) {
  3469 + $all_matos_copy = $all_matos2->cleanCopy();
  3470 + // Tous les matos qui ont une date d'achat non nulle
  3471 + if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]);
  3472 + $tot2[$status] = $all_matos_copy->count();
  3473 + }
  3474 + // Suivis et Prets
  3475 + // Nb materiels qui sont suivis (i.e. qui ont au moins 1 suivi)
  3476 + foreach ($associated_entities as $e) {
  3477 + //$nb_matos_suivis = $suivis->find()
  3478 + $tot2[$e] = $$e->find()
  3479 + // materiel_id not null
  3480 + ->where(["$fk >" => 0])
  3481 + ->select([$fk])
  3482 + ->distinct([$fk])
  3483 + ->where(["$fk IN" => $all_matos_ids2])
  3484 + ->count();
  3485 + }
  3486 + */
  3487 +
  3488 + // - Donées Moyennes (avg)
  3489 + /*
  3490 + $avg['CREATED'] = 10;
  3491 + $avg['VALIDATED'] = 7;
  3492 + $avg['TOBEARCHIVED'] = 1;
  3493 + $avg['ARCHIVED'] = 1;
  3494 + */
  3495 + foreach ($statuses as $status) {
  3496 + $avg[$status] = round($tot[$status]/$nbyears, 1);
  3497 + /*
  3498 + * (EP)
  3499 + * J'obtiens pas le meme resultat avec cette methode...
  3500 + * Peut-être que ca compte pas les années où il n'y a rien (0)
  3501 + */
  3502 + /*
  3503 + //$all_matos = $materiels->find();
  3504 + //$all_matos = $materiels->find()->where(['year(date_acquisition) >' => 0]);
  3505 + //->groupBy('year(date_acquisition)');
  3506 + $all_matos_copy = $all_matos->cleanCopy();
  3507 + if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]);
  3508 + $avg[$status] = $all_matos_copy
  3509 + //->groupBy('year(date_acquisition)');
  3510 + ->countBy(function($matos) {
  3511 + return $matos->date_acquisition->format('Y');
  3512 + })
  3513 + ->avg();
  3514 + //->toList();
  3515 + //->toArray();
  3516 + //->count();
  3517 + $avg[$status] = round($avg[$status]);
  3518 + */
  3519 + }
  3520 + // Suivis et Prets
  3521 + // Nb materiels qui sont suivis (i.e. qui ont au moins 1 suivi)
  3522 + foreach ($associated_entities as $e) {
  3523 + $avg[$e] = round($tot[$e]/$nbyears, 1);
  3524 + /*
  3525 + $nb_matos_having_entity = $$e->find()
  3526 + // materiel_id not null
  3527 + ->where(["$fk >" => 0])
  3528 + ->select([
  3529 + 'year' => 'YEAR(created)'
  3530 + ])
  3531 + ->group('year')
  3532 + ->toArray();
  3533 +
  3534 + //->groupBy(function($entity) {
  3535 + ->group(function($entity) {
  3536 + return $entity->created->format('Y');
  3537 + })
  3538 + ->distinct([$fk])
  3539 + ->count()
  3540 + ->avg();
  3541 + $avg[$e] = $nb_matos_having_entity;
  3542 + */
  3543 + //debug($nb_matos_having_entity);
  3544 + }
  3545 +
  3546 +
  3547 + // - Données par Année
  3548 + $all_matos = $materiels->find();
  3549 + for ($y=$current_year ; $y>=$year_min ; $y--) {
  3550 + ////debug($y);
  3551 + $all_matos_for_year = $all_matos->cleanCopy()->where(['year(date_acquisition)' => $y]);
  3552 + ////debug($all_matos_for_year->count());
  3553 + // - statut par année
  3554 + try {
  3555 + foreach ($statuses as $status) {
  3556 + /*
  3557 + $all_matos_for_year = $materiels->find();
  3558 + ->where(['year(date_acquisition)' => $y]);
  3559 + $all_matos_for_year = $all_matos->cleanCopy()->where(['year(date_acquisition)' => $y]);
  3560 + */
  3561 + $all_matos_for_year_and_status = $all_matos_for_year->cleanCopy();
  3562 + if ($status != 'CREATED') $all_matos_for_year_and_status->where(['status' => $status]);
  3563 + $years[$y][$status] = $all_matos_for_year_and_status->count();
  3564 + }
  3565 + } catch (\PDOException $e) {
  3566 + debug("Mauvais format de requete SQL (PagesController/stats statuses), Exception PDO générée !");
  3567 + exit;
  3568 + }
  3569 + ////debug($years);
  3570 + // Suivis et Prets, par année
  3571 + $all_matos_suivis_for_year = $all_matos_for_year->cleanCopy();
  3572 + foreach ($associated_entities as $e)
  3573 + try {
  3574 + ////debug($e);
  3575 + //debug($$e->find()->count());
  3576 + /*
  3577 + * SQL equivalent : à tester...
  3578 + *
  3579 + * SELECT COUNT(DISTINCT(suivis.materiel_id)) FROM suivis LEFT JOIN materiels
  3580 + * ON suivis.materiel_id = materiels.id
  3581 + * WHERE YEAR(materiels.date_acquisition) = $y
  3582 + *
  3583 + * $years[$y]['suivis'] = $suivis->find()...
  3584 + * puis
  3585 + * $years[$y]['prets'] = $prets->find()...
  3586 + */
  3587 + $years[$y][$e] = $$e
  3588 + // Tous les suivis/emprunts...
  3589 + ->find()
  3590 + // ... et leur materiel associé...
  3591 + ->leftJoinWith('Materiels')
  3592 + // ... LEFT JOIN ON (suivis.materiel_id = materiels.id) ... // ou emprunts.materiel_id
  3593 + //->enableAutoFields(true)
  3594 + // ... (uniquement les materiels de l'année $y) ...
  3595 + ->where(['year(date_acquisition)' => $y])
  3596 + // ... en ne gardant qu'1 seul suivi/emprunt par materiel (meme si ce materiel en a plusieurs) ...
  3597 + ->distinct(['materiel_id'])
  3598 + // ... et enfin, on compte le nombre de suivis/emprunts (total pour l'année $y)
  3599 + ->count();
  3600 + //->toArray();
  3601 + //$all_matos_for_year
  3602 + //->contain(['Suivis'])
  3603 + //->select(['id', 'count_suivis => count(suivis)'])
  3604 + //->where(['count_suivis >' => 0])
  3605 + //->count();
  3606 + } catch (\PDOException $ex) {
  3607 + debug("Mauvais format de requete SQL (PagesController/stats suivis/prets), Exception PDO générée !");
  3608 + debug($ex);
  3609 + exit;
  3610 + }
  3611 + //debug($years[$y]['suivis']);
  3612 + //$years[$y]['suivis'] = 3;
  3613 + //$years[$y]['prets'] = 4;
  3614 + } // foreach year
  3615 + //debug($years);
  3616 +
  3617 + // Set all variables pour la vue
  3618 + //$this->set(compact('current_year', 'year_min', 'tot', 'avg', 'years', 'suivis', 'prets'));
  3619 + //$this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'tot2', 'avg', 'years'));
  3620 +
  3621 + // FAKE DATA POUR TEST LOCAL
  3622 + if ($TEST) {
  3623 +
  3624 + $current_year = 2021;
  3625 +
  3626 + $test_nb_years = 0;
  3627 + $test_nb_years = 1;
  3628 + $test_nb_years = 2;
  3629 + $test_nb_years = 3;
  3630 +
  3631 + $i_year = $current_year;
  3632 + $i_nbyears = 0;
  3633 +
  3634 + $years = [];
  3635 + /*
  3636 + $years[2019] = [
  3637 + 'CREATED' => (int) 27,
  3638 + 'VALIDATED' => (int) 8,
  3639 + 'TOBEARCHIVED' => (int) 1,
  3640 + 'ARCHIVED' => (int) 1,
  3641 + 'suivis' => (int) 2,
  3642 + 'prets' => (int) 2
  3643 + ];
  3644 + */
  3645 + // 1 year
  3646 + if ($test_nb_years > $i_nbyears)
  3647 + $years[$i_year] = [
  3648 + 'CREATED' => (int) 27,
  3649 + 'VALIDATED' => (int) 8,
  3650 + 'TOBEARCHIVED' => (int) 1,
  3651 + 'ARCHIVED' => (int) 1,
  3652 + 'suivis' => (int) 2,
  3653 + 'prets' => (int) 2
  3654 + ];
  3655 + // 2 years
  3656 + if ($test_nb_years > $i_nbyears++)
  3657 + $years[--$i_year] = [
  3658 + 'CREATED' => (int) 0,
  3659 + 'VALIDATED' => (int) 0,
  3660 + 'TOBEARCHIVED' => (int) 0,
  3661 + 'ARCHIVED' => (int) 0,
  3662 + 'suivis' => (int) 0,
  3663 + 'prets' => (int) 0
  3664 + ];
  3665 + // 3 years
  3666 + if ($test_nb_years > $i_nbyears++)
  3667 + $years[--$i_year] = [
  3668 + 'CREATED' => (int) 27,
  3669 + 'VALIDATED' => (int) 8,
  3670 + 'TOBEARCHIVED' => (int) 1,
  3671 + 'ARCHIVED' => (int) 1,
  3672 + 'suivis' => (int) 2,
  3673 + 'prets' => (int) 2
  3674 + ];
  3675 + if ($test_nb_years > $i_nbyears++)
  3676 + $years[--$i_year] = [
  3677 + 'CREATED' => (int) 27,
  3678 + 'VALIDATED' => (int) 8,
  3679 + 'TOBEARCHIVED' => (int) 1,
  3680 + 'ARCHIVED' => (int) 1,
  3681 + 'suivis' => (int) 2,
  3682 + 'prets' => (int) 2
  3683 + ];
  3684 +
  3685 + $nbyears = count($years);
  3686 + $year_min = $nbyears>0 ? min(array_keys($years)) : $current_year;
  3687 +
  3688 + $tot = [
  3689 + 'CREATED' => (int) 27,
  3690 + 'VALIDATED' => (int) 8,
  3691 + 'TOBEARCHIVED' => (int) 1,
  3692 + 'ARCHIVED' => (int) 1,
  3693 + 'suivis' => (int) 2,
  3694 + 'prets' => (int) 2
  3695 + ];
  3696 + $avg = [
  3697 + 'CREATED' => (float) 27,
  3698 + 'VALIDATED' => (float) 8,
  3699 + 'TOBEARCHIVED' => (float) 1,
  3700 + 'ARCHIVED' => (float) 1,
  3701 + 'suivis' => (float) 2,
  3702 + 'prets' => (float) 2
  3703 + ];
  3704 +
  3705 + debug($current_year);
  3706 + debug($year_min);
  3707 + debug($years);
  3708 + } // TEST DATA
  3709 +
  3710 + $this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'avg', 'years'));
  3711 + /*
  3712 + debug($tot);
  3713 + //echo json_encode($avg);
  3714 + debug($avg);
  3715 + debug($years);
  3716 + */
  3717 +
  3718 + } // stats()
  3719 +
  3720 +
  3721 +
  3722 +
3318 /** 3723 /**
3319 * StatusArchived method 3724 * StatusArchived method
3320 * 3725 *
src/Controller/PagesController.php
@@ -306,8 +306,12 @@ class PagesController extends AppController @@ -306,8 +306,12 @@ class PagesController extends AppController
306 306
307 307
308 // - Page des STATISTIQUES 308 // - Page des STATISTIQUES
309 - if ($this->page=='stats') $this->page_stats_set_variables();  
310 - 309 + //if ($this->page=='stats') $this->page_stats_set_variables();
  310 + if ($this->page=='stats') return $this->redirect([
  311 + 'controller' => 'materiels',
  312 + 'action' => 'stats',
  313 + ]);
  314 +
311 315
312 // - Page des OUTILS 316 // - Page des OUTILS
313 if ($this->page=='tools') { 317 if ($this->page=='tools') {
@@ -333,7 +337,7 @@ class PagesController extends AppController @@ -333,7 +337,7 @@ class PagesController extends AppController
333 337
334 338
335 339
336 - private function page_stats_set_variables() { 340 + private function OLD_page_stats_set_variables() {
337 341
338 // créer des FAKE DATA pour tester la fonctionnalité ? 342 // créer des FAKE DATA pour tester la fonctionnalité ?
339 $TEST = true; 343 $TEST = true;