From 8fe06187d2f742a840af36c6cb16e63a2fcaf84f Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Fri, 17 Jul 2020 17:37:53 +0200 Subject: [PATCH] Renforcement important controles sur les dates d'un matériel... --- CHANGES.txt | 6 ++++++ README.md | 4 ++-- src/Controller/MaterielsController.php | 5 +++++ src/Model/Table/MaterielsTable.php | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ src/Template/Materiels/add_edit.ctp | 9 ++++++--- webroot/js/Verifications_dates_materiels.js | 6 +++--- 6 files changed, 199 insertions(+), 32 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 2bca9f4..714a171 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -65,6 +65,12 @@ Outre ces changements, voici d'autres changements importants : ======= CHANGES ======= ------- +17/07/2020 v3.7.9.63 (EP) + - (i) Renforcement important des controles sur les dates d'un matériel (achat, livraison, fin garantie) + - (i) Le numero d'inventaire généré automatiquement en fonction de l'année d'achat est désormais MIS À JOUR à chaque fois qu'on change la date d'achat !!! + + +------- 16/07/2020 v3.7.9.61-62 (EP) - (e) Amélioration importante de la nouvelle page web "Changements" (/pages/changes) - (b) Bugfix "sauf ARCHIVED" dans materiels/index/ (pour profils user et resp) diff --git a/README.md b/README.md index 56d83c0..eefd092 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ Logiciel testé et validé sur les configurations suivantes : -------------------------------------------------------------------------------------------- -Date: 16/07/2020 -Version: 3.7.9.62 +Date: 17/07/2020 +Version: 3.7.9.63 HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes) diff --git a/src/Controller/MaterielsController.php b/src/Controller/MaterielsController.php index 8cfb524..75f3052 100755 --- a/src/Controller/MaterielsController.php +++ b/src/Controller/MaterielsController.php @@ -1349,6 +1349,10 @@ class MaterielsController extends AppController { // et le numero_laboratoire est vu comme invalide car déjà utilisé et doit etre unique !!! // et on a pour résultat : "le matériel n'a pas pu être ajouté" (sans savoir pourquoi !!!) $materiel = $this->Materiels->patchEntity($materiel, $materiel_to_copy, ['validate' => false]); + //TODO: On pourrait traiter les erreurs de validation déjà ici + if ($materiel->errors()) { + // traitement + } // Du coup, on supprime le champ numero_laboratoire car il va être généré automatiquement unset($materiel->numero_laboratoire); // IMPORTANT: on ne doit pas laisser l'id égal à celui du matériel copié !!! il en faut un nouveau @@ -3904,6 +3908,7 @@ class MaterielsController extends AppController { break; } */ + //debug("toto".$date_next->format('d/m/Y')."toto"); exit; //$this->set('date', date_format($date_next, 'd-m-Y')); //$this->set('date', date_format($date_next, 'd/m/Y')); diff --git a/src/Model/Table/MaterielsTable.php b/src/Model/Table/MaterielsTable.php index 73ce70d..2fb2fc0 100755 --- a/src/Model/Table/MaterielsTable.php +++ b/src/Model/Table/MaterielsTable.php @@ -129,27 +129,59 @@ class MaterielsTable extends AppTable } + + public function dateIsValid($value, array $context) { + //debug($entity); + // /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g + //$valid = preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([1-2][0-9]{3})$/",$entity); + //debug((bool)$valid); + return (bool) preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([1-2][0-9]{3})$/",$value); + } + + /** * Default validation rules. * + * (EP 2020) + * NIVEAU 1 DE VALIDATION : au moment où les données sont converties en Entity avec newEntity(), patchEntity()... + * On vérifie ici seulement le format des données, indépendamment de leur sens (ce que l'application va en faire) + * Le niveau 2 "Application Rules" est appliqué par la fonction buildRules() ci-après + * * @param \Cake\Validation\Validator $validator * Validator instance. * @return \Cake\Validation\Validator */ - public function validationDefault(Validator $validator) + // php7 + //public function validationDefault(Validator $validator) : Validator + public function validationDefault(Validator $validator) //: Validator { - - $dateValide = function ($entity) { - //date_default_timezone_set('Europe/Paris'); + // Check date is dd/mm/yyyy + /* + $dateIsValid = function ($entity) { + //debug($entity); + // /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g + //$valid = preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([1-2][0-9]{3})$/",$entity); + //debug((bool)$valid); + return (bool) preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([1-2][0-9]{3})$/",$entity); + }; + */ + // return true si date n'est pas future (maxi = today) + $dateIsNotFutureAndNotTooOld = function ($date_string) { $tz = new \DateTimeZone('Europe/Paris'); - $today = (new \DateTime('now',$tz))->format('Ymd'); + // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) + $date = ( new \DateTime(strtr($date_string,'/','-'),$tz) )->format('Ymd'); + //date_default_timezone_set('Europe/Paris'); + //$today = (new \DateTime('now',$tz))->format('Ymd'); + $today = new \DateTime('now',$tz); + $date_too_old = $today; + $today = $today->format('Ymd'); + // today - 50 ans = trop vieux ! + $date_too_old = $date_too_old->sub(new \DateInterval('P50Y'))->format('Ymd'); /* $time = Time::now(); // On récupère la date et l'heure actuelles $today = (new date("$time->year-$time->month-$time->day"))->format('Ymd'); // On extrait la date on la formatte en un format comparable de type 20171231 */ - // DateTume lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) - $date = ( new \DateTime(strtr($entity,'/','-'),$tz) )->format('Ymd'); /* $timeEntity = new time($entity); $dateEntity = (new date("$timeEntity->year-$timeEntity->month-$timeEntity->day"))->format('Ymd'); @@ -160,7 +192,11 @@ class MaterielsTable extends AppTable debug($date); exit; */ - return ($today >= $date); + debug($today); // '20200717' + debug($date); // '20200718' => pas bon + debug($date_too_old); + //return ($today >= $date); + return ($date<=$today && $date>$date_too_old); }; $validator->integer('id')->allowEmpty('id', 'create'); @@ -194,22 +230,90 @@ class MaterielsTable extends AppTable 'message' => 'Le statut doit prendre une des 4 valeurs CREATED, VALIDATED, TOBEARCHIVED, ou ARCHIVED', 'provider' => 'table' ]); + /* $configuration = TableRegistry::get('Configurations')->find() ->where([ 'id =' => 1 ]) - ->first(); - if ($configuration->date_commande_facultative) { - $validator->allowEmpty('date_acquisition')->add('date_acquisition', 'custom', [ - 'rule' => $dateValide, - 'message' => "La date n'est pas valide (car trop lointaine)" + ->first(); + */ + $configuration = TableRegistry::get('Configurations')->get(1); + + + + // Validation des DATES + + // - Date achat + $f = 'date_acquisition'; + $validator + ->allowEmptyString($f, $configuration->date_commande_facultative, 'Ce champ doit être rempli') + ->date($f, 'dmy', 'Date invalide') // https://api.cakephp.org/3.8/class-Cake.Validation.Validation.html#_date + ->add($f, 'valide', [ + // 2 façons d'appeler une règle de validation locale : + // - par son nom de fonction définie LOCALEMENT (ici dans CETTE fonction) comme une variable (avec un $) + //'rule' => $dateIsValid, + // - mieux, par son nom, la fonction étant définie n'importe où dans CETTE classe + 'rule' => 'dateIsValid', + 'message' => "La date n'est pas valide (JJ/MM/AAAA)", + 'provider' => 'table', + ]) + ->add($f, 'acceptable', [ + 'rule' => $dateIsNotFutureAndNotTooOld, + 'message' => "La date ne doit être ni future ni trop ancienne" ]); - } else { - $validator->notEmpty('date_acquisition', 'Ce champ doit être rempli')->add('date_acquisition', 'custom', [ - 'rule' => $dateValide, - 'message' => "La date n'est pas valide (car trop lointaine)" + + // - Date livraison + $f = 'date_reception'; + $validator + ->allowEmptyString($f) + ->date($f, 'dmy', 'Date invalide') // https://api.cakephp.org/3.8/class-Cake.Validation.Validation.html#_date + //->add('date_reception', 'valid', ['rule' => 'date', 'message' => 'Date invalide']); + ->add($f, 'valide-JJslashMMslashAAAA', [ + 'rule' => 'dateIsValid', + 'message' => "La date n'est pas valide (JJ/MM/AAAA)", + 'provider' => 'table', + ]); + + // - Date fin garantie + $f = 'date_fin_garantie'; + $validator + ->allowEmptyString($f) + ->date($f, 'dmy', 'Date invalide') // https://api.cakephp.org/3.8/class-Cake.Validation.Validation.html#_date + ->add($f, 'valide-JJslashMMslashAAAA', [ + 'rule' => 'dateIsValid', + 'message' => "La date n'est pas valide (JJ/MM/AAAA)", + 'provider' => 'table', ]); + + + + /* + if ($configuration->date_commande_facultative) { + //$validator->allowEmpty('date_acquisition')->add('date_acquisition', 'custom', [ + $validator + ->allowEmptyString('date_acquisition') + ->add('date_acquisition', 'custom1', [ + 'rule' => $dateIsValid, + 'message' => "La date n'est pas valide (JJ/MM/AAAA)" + ]) + ->add('date_acquisition', 'custom2', [ + 'rule' => $dateIsNotFuture, + 'message' => "La date ne doit pas être future" + ]); + } else { + $validator + //->notEmpty('date_acquisition', 'Ce champ doit être rempli') + ->allowEmptyString('date_acquisition', false, 'Ce champ doit être rempli') + ->add('date_acquisition', 'custom1', [ + 'rule' => $dateIsValid, + 'message' => "La date n'est pas valide (JJ/MM/AAAA)" + ]) + ->add('date_acquisition', 'custom2', [ + 'rule' => $dateIsNotFutureAndNotTooOld, + 'message' => "La date ne doit être ni future ni trop ancienne" + ]); } + */ /* // Attention, configuration désactivée, cela ne génère pas ne num de labo, voir dans config/edit.ctp $validator->allowEmpty('fournisseur')->add('fournisseur', 'valid', [ @@ -218,6 +322,9 @@ class MaterielsTable extends AppTable 'provider' => 'table' ]); */ + + + $validator->numeric('prix_ht') ->allowEmpty('prix_ht') ->add('prix_ht', 'valid', [ @@ -286,10 +393,11 @@ class MaterielsTable extends AppTable ->allowEmpty('nom_modificateur'); */ - $validator->allowEmpty('date_reception'); - $validator->allowEmpty('date_fin_garantie'); + //$validator->allowEmpty('date_reception'); + //$validator->allowEmpty('date_fin_garantie'); $validator->allowEmpty('duree_garantie'); $validator->allowEmpty('unite_duree_garantie'); + return $validator; } @@ -298,12 +406,18 @@ class MaterielsTable extends AppTable /** * Returns a rules checker object that will be used for validating * application integrity. + * + * (EP 2020) + * NIVEAU 2 DE VALIDATION : au moment où les Entity sont persistées dans la BD + * On vérifie ici le sens des données (ce que l'application va en faire) + * Le niveau 1 "Validation Rules" est appliqué par la fonction validationDefault() ci-dessus + * * @param \Cake\ORM\RulesChecker $rules * The rules object to be modified. * @return \Cake\ORM\RulesChecker */ - public function buildRules(RulesChecker $rules) + public function buildRules(RulesChecker $rules) //: RulesChecker { //$configuration = TableRegistry::get('Configurations')->find() /* @@ -348,6 +462,27 @@ class MaterielsTable extends AppTable //return ($entity->prix_ht !== null); return true; }; + + // Check dates + $dateIsAfterDateAchat = function ($entity) { + $tz = new \DateTimeZone('Europe/Paris'); + // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) + $d1 = ( new \DateTime(strtr($entity->date_acquisition,'/','-'),$tz) )->format('Ymd'); + $d2 = ( new \DateTime(strtr($entity->date_reception,'/','-'),$tz) )->format('Ymd'); + //date_default_timezone_set('Europe/Paris'); + //$today = (new \DateTime('now',$tz))->format('Ymd'); + return ($d2 >= $d1); + }; + $dateIsAfterDateReception = function ($entity) { + $tz = new \DateTimeZone('Europe/Paris'); + // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) + $d1 = ( new \DateTime(strtr($entity->date_reception,'/','-'),$tz) )->format('Ymd'); + $d2 = ( new \DateTime(strtr($entity->date_fin_garantie,'/','-'),$tz) )->format('Ymd'); + //date_default_timezone_set('Europe/Paris'); + //$today = (new \DateTime('now',$tz))->format('Ymd'); + return ($d2 >= $d1); + }; + /* $rules->add($checkAtLeastOneChecked, [ 'errorField' => 'materiel_administratif', @@ -408,6 +543,17 @@ class MaterielsTable extends AppTable //$rules->add($rules->existsIn(['photo_id'], 'Photos')); ///$rules->add($rules->existsIn(['fournisseur_id'], 'Fournisseurs')); + // Check dates reception et fin garantie + $rules->add($dateIsAfterDateAchat, [ + 'errorField' => 'date_reception', + 'message' => "La date doit être postérieure à la date d'achat" + ]); + $rules->add($dateIsAfterDateReception, [ + 'errorField' => 'date_fin_garantie', + 'message' => "La date doit être postérieure à la date de livraison" + ]); + + return $rules; } @@ -427,20 +573,27 @@ class MaterielsTable extends AppTable $entity->set('nom_ancien_responsable', $entity->get('nom_responsable')); } */ - // numero_laboratoire generator (QC changed this in Jan 2015) + /* $configuration = TableRegistry::get('Configurations')->find() ->where([ 'id =' => 1 ]) -> first(); - + */ + $configuration = TableRegistry::get('Configurations')->get(1); + + // numero_laboratoire generator (QC changed this in Jan 2015) // (EP) Set new $labNumber (laboratory number) for this new materiel $WITH_YEAR = FALSE; $DATE_GIVEN = TRUE; - if (!$configuration->numero_labo_sans_annee) { + if (! $configuration->numero_labo_sans_annee) { $WITH_YEAR = TRUE; $DATE_GIVEN = !empty($entity->get('date_acquisition')); } - if ( empty($entity->get('numero_laboratoire')) && $DATE_GIVEN ) { + // (EP 202007) + // Numero inventaire généré 1 seule fois (la toute première) + //if ( empty($entity->get('numero_laboratoire')) && $DATE_GIVEN ) { + // Numero inventaire regénéré A CHAQUE FOIS + if ( $DATE_GIVEN ) { if ($WITH_YEAR) { $year=substr($entity->get('date_acquisition'), 6, 4); if (strlen($year) == 2) { diff --git a/src/Template/Materiels/add_edit.ctp b/src/Template/Materiels/add_edit.ctp index d2e8934..40cd540 100644 --- a/src/Template/Materiels/add_edit.ctp +++ b/src/Template/Materiels/add_edit.ctp @@ -550,12 +550,13 @@ if (isset($cpMateriel)) { Form->control('date_acquisition', [ 'type' => 'text', 'label' => 'Date commande (BC)', 'class' => 'datepicker', - 'placeholder' => 'Cliquez pour une date (JJ/MM/AAAA)', + 'placeholder' => $comment, // ADD only //'default' => $Date_acquisition //'default' => $materiel->date_acquisition, @@ -569,7 +570,7 @@ if (isset($cpMateriel)) { 'type' => 'text', 'label' => 'Date de réception', 'class' => 'datepicker', - 'placeholder' => 'A éditer lors de la réception uniquement.', + 'placeholder' => $comment, 'empty' => true, // ADD only //'default' => $Date_reception @@ -613,7 +614,7 @@ if (isset($cpMateriel)) { echo $this->Form->control('date_fin_garantie', [ 'type' => 'text', 'label' => 'Date fin de garantie', - 'placeholder' => 'Cliquez pour selectionner une date', + 'placeholder' => $comment, 'class' => 'datepicker', 'default' => NULL ]); @@ -1111,6 +1112,7 @@ $(document).ready(function() { /** * OnChange durée garantie OU unité => calcul date fin de garantie */ + /* function calcul_date_fin_garantie(event) { if($("#date-reception").val() != "" && $("#duree-garantie").val() != "") { var url = document.URL; @@ -1125,6 +1127,7 @@ $(document).ready(function() { } $("#duree-garantie").bind("change", calcul_date_fin_garantie(event)); $("#unite-duree-garantie").bind("change", calcul_date_fin_garantie(event)); + */ /* TODO: factoriser, c'est 2 fois la MEME fonction !!! // - OnChange durée diff --git a/webroot/js/Verifications_dates_materiels.js b/webroot/js/Verifications_dates_materiels.js index fe36738..3653cfd 100644 --- a/webroot/js/Verifications_dates_materiels.js +++ b/webroot/js/Verifications_dates_materiels.js @@ -209,12 +209,12 @@ $(document).ready(function () { // (EP 20200410) Vérification date cde <= date réception function check_date_acq_inf_date_rec() { - return check_dates_d1_inf_d2("#date-acquisition", "#date-reception", "La date de réception doit être postérieure à la date d'acquisition"); + return check_dates_d1_inf_d2("#date-acquisition", "#date-reception", "La date de réception doit être postérieure à la date d'achat"); } //(EP 20200410) Vérification date rec <= date garantie function check_date_rec_inf_date_gar() { - return check_dates_d1_inf_d2("#date-reception", "#date-fin-garantie", "La date de fin de garantie doit être supérieure à la date de réception"); + return check_dates_d1_inf_d2("#date-reception", "#date-fin-garantie", "La date de fin de garantie doit être supérieure à la date de livraison"); } @@ -257,7 +257,7 @@ function date_fin_garantie_update() { $.ajax({ url: dateUrl + $("#date-reception").val() + "/" + $("#duree-garantie").val() + "/" + $("#unite-duree-garantie").val() }).done(function(data) { - $("#date-fin-garantie").val(data) + $("#date-fin-garantie").val(data.trim()) }); } } -- libgit2 0.21.2