Commit 4a0780a92b1d8f25d10955ee4579e2721e012a46
Exists in
master
and in
1 other branch
Merge dev branch into master branch (vv3.7.9.65)
Showing
4 changed files
with
181 additions
and
17 deletions
Show diff stats
CHANGES.txt
@@ -13,7 +13,7 @@ TODO: - Nouvelle page web "Statistiques mensuelles" (/pages/stats) | @@ -13,7 +13,7 @@ TODO: - Nouvelle page web "Statistiques mensuelles" (/pages/stats) | ||
13 | 13 | ||
14 | 14 | ||
15 | ------- | 15 | ------- |
16 | -16/07/2020 NEWS#2 : | 16 | +17/07/2020 NEWS#2 : |
17 | 17 | ||
18 | - Nouvelle page web pour visualiser les changements faits sur le logiciel (cette même page que vous visualisez actuellement) : /pages/changes | 18 | - Nouvelle page web pour visualiser les changements faits sur le logiciel (cette même page que vous visualisez actuellement) : /pages/changes |
19 | 19 | ||
@@ -70,12 +70,15 @@ Outre ces changements, voici d'autres changements importants : | @@ -70,12 +70,15 @@ Outre ces changements, voici d'autres changements importants : | ||
70 | ======= CHANGES ======= | 70 | ======= CHANGES ======= |
71 | 71 | ||
72 | ------- | 72 | ------- |
73 | +20/07/2020 v3.7.9.65 (EP) | ||
74 | + - (i) Ajouts important de TESTS sur les dates d'un matériel (achat, livraison, fin garantie) | ||
75 | + | ||
76 | +------- | ||
73 | 17/07/2020 v3.7.9.63-64 (EP) | 77 | 17/07/2020 v3.7.9.63-64 (EP) |
74 | - (i) Renforcement important des controles sur les dates d'un matériel (achat, livraison, fin garantie) | 78 | - (i) Renforcement important des controles sur les dates d'un matériel (achat, livraison, fin garantie) |
75 | - (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 !!! | 79 | - (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 !!! |
76 | - (b) bugfixes et renforcement des tests (date reception doit maintenant etre >= date achat, et test sur message flash était insuffisant et laissait passer des cas...) | 80 | - (b) bugfixes et renforcement des tests (date reception doit maintenant etre >= date achat, et test sur message flash était insuffisant et laissait passer des cas...) |
77 | 81 | ||
78 | - | ||
79 | ------- | 82 | ------- |
80 | 16/07/2020 v3.7.9.61-62 (EP) | 83 | 16/07/2020 v3.7.9.61-62 (EP) |
81 | - (e) Amélioration importante de la nouvelle page web "Changements" (/pages/changes) | 84 | - (e) Amélioration importante de la nouvelle page web "Changements" (/pages/changes) |
README.md
@@ -42,8 +42,8 @@ Logiciel testé et validé sur les configurations suivantes : | @@ -42,8 +42,8 @@ Logiciel testé et validé sur les configurations suivantes : | ||
42 | 42 | ||
43 | -------------------------------------------------------------------------------------------- | 43 | -------------------------------------------------------------------------------------------- |
44 | 44 | ||
45 | -Date: 17/07/2020 | ||
46 | -Version: 3.7.9.64 | 45 | +Date: 20/07/2020 |
46 | +Version: 3.7.9.65 | ||
47 | 47 | ||
48 | 48 | ||
49 | HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes) | 49 | HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes) |
src/Model/Table/MaterielsTable.php
@@ -37,6 +37,11 @@ use Cake\ORM\Association\BelongsTo; | @@ -37,6 +37,11 @@ use Cake\ORM\Association\BelongsTo; | ||
37 | * @mixin \Cake\ORM\Behavior\TimestampBehavior | 37 | * @mixin \Cake\ORM\Behavior\TimestampBehavior |
38 | * | 38 | * |
39 | */ | 39 | */ |
40 | + | ||
41 | + | ||
42 | +// Max 10 ans entre 2 dates | ||
43 | +const MAX_DIFF_YEARS = 10; | ||
44 | + | ||
40 | class MaterielsTable extends AppTable | 45 | class MaterielsTable extends AppTable |
41 | { | 46 | { |
42 | 47 | ||
@@ -195,6 +200,18 @@ class MaterielsTable extends AppTable | @@ -195,6 +200,18 @@ class MaterielsTable extends AppTable | ||
195 | //return ($today >= $date); | 200 | //return ($today >= $date); |
196 | return ($date<=$today && $date>$date_too_old); | 201 | return ($date<=$today && $date>$date_too_old); |
197 | }; | 202 | }; |
203 | + /* | ||
204 | + $dateIsNotTooFarAway = function ($date_string) { | ||
205 | + $tz = new \DateTimeZone('Europe/Paris'); | ||
206 | + $date = ( new \DateTime(strtr($date_string,'/','-'),$tz) )->format('Ymd'); | ||
207 | + $today = new \DateTime('now',$tz); | ||
208 | + $date_too_far = $today; | ||
209 | + $today = $today->format('Ymd'); | ||
210 | + // today + 50 ans = trop vieux ! | ||
211 | + $date_too_far = $date_too_far->add(new \DateInterval('P50Y'))->format('Ymd'); | ||
212 | + return ($date < $date_too_far); | ||
213 | + }; | ||
214 | + */ | ||
198 | 215 | ||
199 | $validator->integer('id')->allowEmpty('id', 'create'); | 216 | $validator->integer('id')->allowEmpty('id', 'create'); |
200 | $validator->notEmpty('designation', 'Ce champ doit être rempli')->add('designation', 'valid', [ | 217 | $validator->notEmpty('designation', 'Ce champ doit être rempli')->add('designation', 'valid', [ |
@@ -270,6 +287,12 @@ class MaterielsTable extends AppTable | @@ -270,6 +287,12 @@ class MaterielsTable extends AppTable | ||
270 | 'message' => "La date n'est pas valide (JJ/MM/AAAA)", | 287 | 'message' => "La date n'est pas valide (JJ/MM/AAAA)", |
271 | 'provider' => 'table', | 288 | 'provider' => 'table', |
272 | ]); | 289 | ]); |
290 | + /* | ||
291 | + ->add($f, 'acceptable2', [ | ||
292 | + 'rule' => $dateIsNotTooFarAway, | ||
293 | + 'message' => "La date est trop loin dans le futur" | ||
294 | + ]); | ||
295 | + */ | ||
273 | 296 | ||
274 | // - Date fin garantie | 297 | // - Date fin garantie |
275 | $f = 'date_fin_garantie'; | 298 | $f = 'date_fin_garantie'; |
@@ -281,7 +304,13 @@ class MaterielsTable extends AppTable | @@ -281,7 +304,13 @@ class MaterielsTable extends AppTable | ||
281 | 'message' => "La date n'est pas valide (JJ/MM/AAAA)", | 304 | 'message' => "La date n'est pas valide (JJ/MM/AAAA)", |
282 | 'provider' => 'table', | 305 | 'provider' => 'table', |
283 | ]); | 306 | ]); |
284 | - | 307 | + /* |
308 | + ->add($f, 'acceptable3', [ | ||
309 | + 'rule' => $dateIsNotTooFarAway, | ||
310 | + 'message' => "La date est trop loin dans le futur" | ||
311 | + ]); | ||
312 | + */ | ||
313 | + | ||
285 | 314 | ||
286 | 315 | ||
287 | /* | 316 | /* |
@@ -459,25 +488,44 @@ class MaterielsTable extends AppTable | @@ -459,25 +488,44 @@ class MaterielsTable extends AppTable | ||
459 | //return ($entity->prix_ht !== null); | 488 | //return ($entity->prix_ht !== null); |
460 | return true; | 489 | return true; |
461 | }; | 490 | }; |
491 | + | ||
462 | 492 | ||
463 | // Check dates | 493 | // Check dates |
464 | - $dateIsAfterDateAchat = function ($entity) { | 494 | + $dateIsAfterDateAchatAndNotTooFar = function ($entity) { |
495 | + // Si une des 2 dates est nulle => return true | ||
496 | + if (!$entity->date_reception || !$entity->date_acquisition) return true; | ||
465 | $tz = new \DateTimeZone('Europe/Paris'); | 497 | $tz = new \DateTimeZone('Europe/Paris'); |
466 | // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) | 498 | // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) |
467 | - $d1 = ( new \DateTime(strtr($entity->date_acquisition,'/','-'),$tz) )->format('Ymd'); | ||
468 | - $d2 = ( new \DateTime(strtr($entity->date_reception,'/','-'),$tz) )->format('Ymd'); | 499 | + //$d1 = ( new \DateTime(strtr($entity->date_acquisition,'/','-'),$tz) )->format('Ymd'); |
500 | + $d1 = new \DateTime(strtr($entity->date_acquisition,'/','-'),$tz); | ||
501 | + //$d1_text = $d1->format('Ymd'); | ||
502 | + $d2 = new \DateTime(strtr($entity->date_reception,'/','-'),$tz); | ||
503 | + //$d2_text = $d2->format('Ymd'); | ||
469 | //date_default_timezone_set('Europe/Paris'); | 504 | //date_default_timezone_set('Europe/Paris'); |
470 | //$today = (new \DateTime('now',$tz))->format('Ymd'); | 505 | //$today = (new \DateTime('now',$tz))->format('Ymd'); |
471 | - return ($d2 >= $d1); | 506 | + //$ok = ($d2_text >= $d1_text); |
507 | + if ($d2 < $d1) return false; | ||
508 | + // $d2 > $d1 oui mais pas trop... | ||
509 | + $diff = $d2->diff($d1); | ||
510 | + //debug($diff->y); | ||
511 | + return $diff->y < MAX_DIFF_YEARS; | ||
472 | }; | 512 | }; |
473 | - $dateIsAfterDateReception = function ($entity) { | 513 | + $dateIsAfterDateReceptionAndNotTooFar = function ($entity) { |
514 | + // Si une des 2 dates est nulle => return true | ||
515 | + if (!$entity->date_reception || !$entity->date_fin_garantie) return true; | ||
474 | $tz = new \DateTimeZone('Europe/Paris'); | 516 | $tz = new \DateTimeZone('Europe/Paris'); |
475 | // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) | 517 | // DateTime lit les dates au format JJ-MM-YYYY (et non pas JJ/MM/YYYY) |
476 | - $d1 = ( new \DateTime(strtr($entity->date_reception,'/','-'),$tz) )->format('Ymd'); | ||
477 | - $d2 = ( new \DateTime(strtr($entity->date_fin_garantie,'/','-'),$tz) )->format('Ymd'); | 518 | + //debug($entity->date_reception); |
519 | + //$d1 = ( new \DateTime(strtr($entity->date_reception,'/','-'),$tz) )->format('Ymd'); | ||
520 | + $d1 = new \DateTime(strtr($entity->date_reception,'/','-'),$tz); | ||
521 | + $d2 = new \DateTime(strtr($entity->date_fin_garantie,'/','-'),$tz); | ||
478 | //date_default_timezone_set('Europe/Paris'); | 522 | //date_default_timezone_set('Europe/Paris'); |
479 | //$today = (new \DateTime('now',$tz))->format('Ymd'); | 523 | //$today = (new \DateTime('now',$tz))->format('Ymd'); |
480 | - return ($d2 >= $d1); | 524 | + if ($d2 < $d1) return false; |
525 | + // $d2 > $d1 oui mais pas trop... | ||
526 | + $diff = $d2->diff($d1); | ||
527 | + //debug($diff->y); | ||
528 | + return $diff->y < MAX_DIFF_YEARS; | ||
481 | }; | 529 | }; |
482 | 530 | ||
483 | /* | 531 | /* |
@@ -541,13 +589,13 @@ class MaterielsTable extends AppTable | @@ -541,13 +589,13 @@ class MaterielsTable extends AppTable | ||
541 | ///$rules->add($rules->existsIn(['fournisseur_id'], 'Fournisseurs')); | 589 | ///$rules->add($rules->existsIn(['fournisseur_id'], 'Fournisseurs')); |
542 | 590 | ||
543 | // Check dates reception et fin garantie | 591 | // Check dates reception et fin garantie |
544 | - $rules->add($dateIsAfterDateAchat, [ | 592 | + $rules->add($dateIsAfterDateAchatAndNotTooFar, [ |
545 | 'errorField' => 'date_reception', | 593 | 'errorField' => 'date_reception', |
546 | - 'message' => "La date doit être postérieure à la date d'achat" | 594 | + 'message' => "La date doit être postérieure à la date d'achat (et pas trop loin)" |
547 | ]); | 595 | ]); |
548 | - $rules->add($dateIsAfterDateReception, [ | 596 | + $rules->add($dateIsAfterDateReceptionAndNotTooFar, [ |
549 | 'errorField' => 'date_fin_garantie', | 597 | 'errorField' => 'date_fin_garantie', |
550 | - 'message' => "La date doit être postérieure à la date de livraison" | 598 | + 'message' => "La date doit être postérieure à la date de livraison (et pas trop loin)" |
551 | ]); | 599 | ]); |
552 | 600 | ||
553 | 601 |
tests/TestCase/Controller/MaterielsControllerTest.php
@@ -2649,6 +2649,119 @@ class MaterielsControllerTest extends General { | @@ -2649,6 +2649,119 @@ class MaterielsControllerTest extends General { | ||
2649 | 2649 | ||
2650 | } | 2650 | } |
2651 | 2651 | ||
2652 | + | ||
2653 | + /** | ||
2654 | + * (EP 20200720) | ||
2655 | + * | ||
2656 | + * Test des controles sur les dates | ||
2657 | + * | ||
2658 | + */ | ||
2659 | + public function testMaterielDatesValidation() { | ||
2660 | + | ||
2661 | + // On teste avec le profil SUPERADMIN car il a (presque) tous les droits | ||
2662 | + $this->authAs('SUPER'); | ||
2663 | + | ||
2664 | + // On récupère un matériel qcq qu'on va modifier à souhait pour faire les tests | ||
2665 | + $id = $this->_getEntityIdOkForTesting(); | ||
2666 | + $m = $this->Materiels->get($id); | ||
2667 | + $format = 'd/m/Y'; | ||
2668 | + | ||
2669 | + | ||
2670 | + // 1) Test edit date acquisition correct format => OK | ||
2671 | + $f = 'date_acquisition'; | ||
2672 | + | ||
2673 | + $new_data = [ | ||
2674 | + $f => '19/04/'.yyyy0, | ||
2675 | + 'date_reception' => '', | ||
2676 | + ]; | ||
2677 | + $action = 'edit'; | ||
2678 | + //$this->_doActionAndCheckResult($action, $id, $SUCCESS=true, $new_data); | ||
2679 | + $this->_doActionAndCheckResult($action, $id, TRUE, $new_data); | ||
2680 | + | ||
2681 | + | ||
2682 | + // 2) Test edit date acquisition wrong format => KO | ||
2683 | + | ||
2684 | + // - date (achat) mauvais format => KO | ||
2685 | + $new_data = [ | ||
2686 | + $f => '19-04-'.yyyy0, | ||
2687 | + //'date_reception' => '', | ||
2688 | + ]; | ||
2689 | + //$action = 'edit'; | ||
2690 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2691 | + | ||
2692 | + // - date (achat) incorrecte => KO | ||
2693 | + $new_data = [ $f => '31/04/'.yyyy0 ]; | ||
2694 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2695 | + | ||
2696 | + // - date (achat) today => OK... | ||
2697 | + $tz = new \DateTimeZone('Europe/Paris'); | ||
2698 | + $date = $today = new \DateTime('now',$tz); | ||
2699 | + //debug($date); | ||
2700 | + $new_data = [ $f => $date->format('d/m/Y') ]; | ||
2701 | + $this->_doActionAndCheckResult($action, $id, TRUE, $new_data); | ||
2702 | + | ||
2703 | + // - ... mais date future (demain) => KO | ||
2704 | + $tomorrow = new \DateTime('now',$tz); | ||
2705 | + $date = $tomorrow->add(new \DateInterval('P1D')); | ||
2706 | + //debug($date); | ||
2707 | + $new_data = [ $f => $date->format('d/m/Y') ]; | ||
2708 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2709 | + | ||
2710 | + // - date (achat) loin dans le passé (-40 ans) => OK... | ||
2711 | + $old = new \DateTime('now',$tz); | ||
2712 | + $date = $old->sub(new \DateInterval('P40Y')); | ||
2713 | + $new_data = [ $f => $date->format('d/m/Y') ]; | ||
2714 | + $this->_doActionAndCheckResult($action, $id, TRUE, $new_data); | ||
2715 | + // - mais pas trop loin dans le passé (-50 ans) => KO | ||
2716 | + $date = $old->sub(new \DateInterval('P10Y')); | ||
2717 | + //debug($date); | ||
2718 | + $new_data = [ $f => $date->format('d/m/Y') ]; | ||
2719 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2720 | + | ||
2721 | + | ||
2722 | + // 3) Test Date reception >= date acq, mais pas trop loin | ||
2723 | + $f = 'date_reception'; | ||
2724 | + | ||
2725 | + // - date (reception) < date acq => KO | ||
2726 | + $yesterday = new \DateTime('now',$tz); | ||
2727 | + $date = $yesterday->sub(new \DateInterval('P1D')); | ||
2728 | + $new_data = [ | ||
2729 | + 'date_acquisition' => $today->format($format), | ||
2730 | + $f => $date->format($format) | ||
2731 | + ]; | ||
2732 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2733 | + | ||
2734 | + // - date (reception) = date acq => OK | ||
2735 | + $date = $today; | ||
2736 | + $new_data = [ | ||
2737 | + 'date_acquisition' => $today->format($format), | ||
2738 | + $f => $date->format($format) | ||
2739 | + ]; | ||
2740 | + $this->_doActionAndCheckResult($action, $id, TRUE, $new_data); | ||
2741 | + | ||
2742 | + // - date (reception) > date_acq (jqa MAX_DIFF - 1 jour) => OK... | ||
2743 | + $MAX_DIFF = 10; | ||
2744 | + $far = new \DateTime('now',$tz); | ||
2745 | + $far->add(new \DateInterval('P'.$MAX_DIFF.'Y')); | ||
2746 | + $date = $far->sub(new \DateInterval('P1D')); | ||
2747 | + debug($date); | ||
2748 | + $new_data = [ | ||
2749 | + 'date_acquisition' => $today->format('d/m/Y'), | ||
2750 | + $f => $date->format('d/m/Y') | ||
2751 | + ]; | ||
2752 | + $this->_doActionAndCheckResult($action, $id, TRUE, $new_data); | ||
2753 | + // - ...mais pas trop loin dans le futur (MAX_DIFF) => KO | ||
2754 | + $date = $far->add(new \DateInterval('P1D')); | ||
2755 | + debug($date); | ||
2756 | + $new_data = [ $f => $date->format('d/m/Y') ]; | ||
2757 | + $this->_doActionAndCheckResult($action, $id, FALSE, $new_data); | ||
2758 | + | ||
2759 | + | ||
2760 | + // 4) Test Date fin garantie >= date reception, mais pas trop loin | ||
2761 | + // C'est la meme chose que le point precedent (3), on suppose donc que c'est ok... | ||
2762 | + } | ||
2763 | + | ||
2764 | + | ||
2652 | /** | 2765 | /** |
2653 | * (EP 20200629) | 2766 | * (EP 20200629) |
2654 | * | 2767 | * |