Commit 2070d27c3994c03f5c9c82b7bcc432b336f884e9
1 parent
f4d2696b
Exists in
master
and in
1 other branch
GROS Nettoyage de la liste des fournisseurs
- GROSSE requete sql très compliquée de suppression des doublons (et des espaces en trop) - Suppression de la règle technique/inventoriable - prix_ht désormais obligatoire v4.105.24-3.7.9
Showing
10 changed files
with
317 additions
and
17 deletions
Show diff stats
CHANGES.txt
... | ... | @@ -119,8 +119,12 @@ Outre ces changements, voici d'autres changements importants : |
119 | 119 | |
120 | 120 | ======= CHANGES ======= |
121 | 121 | |
122 | -TODO | |
123 | - - (i) Nettoyage de la liste des fournisseurs : GROSSE requete sql compliquée de suppression des doublons (et des espaces en trop) | |
122 | +------- | |
123 | +16/10/2020 v4.105.24-3.7.9 (EP) | |
124 | + - (i) GROS Nettoyage de la liste des fournisseurs : | |
125 | + => GROSSE requete sql très compliquée de suppression des doublons (et des espaces en trop) | |
126 | + - (i) Suppression de la règle technique/inventoriable | |
127 | + - (e) prix_ht désormais obligatoire | |
124 | 128 | |
125 | 129 | ------- |
126 | 130 | 15/10/2020 v4.105.24-3.7.9 (EP) | ... | ... |
src/Controller/AppController.php
... | ... | @@ -3640,7 +3640,8 @@ class AppController extends Controller |
3640 | 3640 | if (!$configuration->envoi_mail && !$configuration->envoi_mail_guests) return null; |
3641 | 3641 | |
3642 | 3642 | // Si notification email pas demandée, on quitte |
3643 | - if (!$DEBUG) if (! $this->isNotifierActionSendingEmail($action) ) return null; | |
3643 | + if (!$DEBUG) | |
3644 | + if (! $this->isNotifierActionSendingEmail($action) ) return null; | |
3644 | 3645 | |
3645 | 3646 | /* |
3646 | 3647 | * 4.A - CRÉATION DU MAIL (sujet et body) |
... | ... | @@ -3757,6 +3758,9 @@ class AppController extends Controller |
3757 | 3758 | * - (TODO:) les responsables (scientifique et chef projet) du projet |
3758 | 3759 | */ |
3759 | 3760 | |
3761 | + // ssi Envoi général activé | |
3762 | + if ($configuration->envoi_mail) { | |
3763 | + | |
3760 | 3764 | if (!$IS_ENTITY_OTHER) { |
3761 | 3765 | |
3762 | 3766 | // - (1) Ajout de l'utilisateur du matériel |
... | ... | @@ -3824,6 +3828,8 @@ class AppController extends Controller |
3824 | 3828 | |
3825 | 3829 | } // uniquement pour entité liée à un matériel |
3826 | 3830 | |
3831 | + } // ssi envoi général activé | |
3832 | + | |
3827 | 3833 | |
3828 | 3834 | /* |
3829 | 3835 | * b) Envoi à la liste spécifique |
... | ... | @@ -3835,7 +3841,8 @@ class AppController extends Controller |
3835 | 3841 | * systématiquement de toutes les actions |
3836 | 3842 | * |
3837 | 3843 | */ |
3838 | - //$specificUsers = []; | |
3844 | + | |
3845 | + // ssi envoi liste spécifique activé | |
3839 | 3846 | //if ($configuration->envoi_mail_guests && $action != 'printLabelRuban') { |
3840 | 3847 | if ($configuration->envoi_mail_guests) { |
3841 | 3848 | // mail aux adresses specifiees dans la config |
... | ... | @@ -3849,7 +3856,8 @@ class AppController extends Controller |
3849 | 3856 | //$specificUsers[] = $specificUser; |
3850 | 3857 | // $mailList[sizeof($mailList)] = $configuration['emailGuest' . $i]; |
3851 | 3858 | } |
3852 | - } | |
3859 | + } // ssi envoi liste spécifique activé | |
3860 | + | |
3853 | 3861 | |
3854 | 3862 | /* |
3855 | 3863 | * c) NETTOYAGE | ... | ... |
src/Controller/FournisseursController.php
... | ... | @@ -12,6 +12,21 @@ use Cake\ORM\TableRegistry; |
12 | 12 | class FournisseursController extends AppController |
13 | 13 | { |
14 | 14 | |
15 | + /* | |
16 | + * @Override | |
17 | + * | |
18 | + * Initialisation des autorisations pour les actions spécifiques à ce controleur | |
19 | + * | |
20 | + */ | |
21 | + protected function setAuthorizations() { | |
22 | + | |
23 | + // - Action 'cleanup' | |
24 | + $this->setAuthorizationsForAction('cleanup (Nettoyage)', -1, [ | |
25 | + 'super' => 0, | |
26 | + ]); | |
27 | + | |
28 | + } | |
29 | + | |
15 | 30 | /** |
16 | 31 | * Give authorization for unite |
17 | 32 | * |
... | ... | @@ -70,6 +85,12 @@ class FournisseursController extends AppController |
70 | 85 | } |
71 | 86 | */ |
72 | 87 | |
88 | + // Page de nettoyage de la liste des fournisseurs | |
89 | + public function cleanup() { | |
90 | + | |
91 | + } | |
92 | + | |
93 | + | |
73 | 94 | /** |
74 | 95 | * Index method |
75 | 96 | * | ... | ... |
src/Controller/MaterielsController.php
... | ... | @@ -11,6 +11,7 @@ use App\Model\Entity\User; |
11 | 11 | use Cake\I18n\FrozenDate; |
12 | 12 | use Cake\Database\Expression\QueryExpression; |
13 | 13 | use Cake\Database\Query; |
14 | +use phpDocumentor\Reflection\Types\True_; | |
14 | 15 | |
15 | 16 | //use App\Controller\DocumentsController; |
16 | 17 | //App::import('Controller', 'Documents'); |
... | ... | @@ -343,10 +344,16 @@ class MaterielsController extends AppController { |
343 | 344 | ]); |
344 | 345 | */ |
345 | 346 | |
347 | + | |
346 | 348 | /* |
347 | 349 | * c) Règles d'accès (ACLs) |
348 | 350 | * |
349 | 351 | */ |
352 | + | |
353 | + // - Action 'execSqlRequestForBugfix' (bugfix) => autorisé seulement à superadmin | |
354 | + $this->setAuthorizationsForAction('execSqlRequestForBugfix (bugfix)', -1, [ | |
355 | + 'super' => 0, | |
356 | + ]); | |
350 | 357 | |
351 | 358 | // - Action 'add' (ajout d'un nouveau matériel) => autorisé pour tous |
352 | 359 | //$this->setAuthorizationsForAction('add', 0); |
... | ... | @@ -1691,7 +1698,177 @@ class MaterielsController extends AppController { |
1691 | 1698 | |
1692 | 1699 | } // view |
1693 | 1700 | |
1701 | + | |
1702 | + public function execSqlRequestForBugfix() { | |
1703 | + debug("START..."); | |
1704 | + $this->execSqlRequestForBugfix_fournisseurs(); | |
1705 | + debug("...STOP"); | |
1706 | + exit; | |
1707 | + /* | |
1708 | + return $this->redirect([ | |
1709 | + 'controller' => 'pages', | |
1710 | + 'action' => 'tools', | |
1711 | + ]); | |
1712 | + */ | |
1713 | + } | |
1694 | 1714 | |
1715 | + // (EP20201016) Bugfix liste fournisseurs en BD | |
1716 | + private function execSqlRequestForBugfix_fournisseurs() { | |
1717 | + | |
1718 | + $DEBUG=false; | |
1719 | + //$DEBUG=true; | |
1720 | + | |
1721 | + $NL = '<br />'; | |
1722 | + $CLEAN = false; | |
1723 | + | |
1724 | + $ftable= $this->Materiels->Fournisseurs; | |
1725 | + // OU ENCORE (même chose) : | |
1726 | + //$ftable= $this->getTableLocator()->get('Fournisseurs'); | |
1727 | + // OU ENCORE (même chose) : | |
1728 | + //$ftable= TableRegistry::getTableLocator()->get('Fournisseurs'); | |
1729 | + | |
1730 | + function show($entities, $AFEW=true) { | |
1731 | + //foreach ($entities as $e) echo("[$e] <br>"); | |
1732 | + $nb = $entities->count(); | |
1733 | + $i=0; | |
1734 | + foreach ($entities as $e) { | |
1735 | + $i++; | |
1736 | + if ($AFEW && $i==10) echo "......................<br>"; | |
1737 | + if ( | |
1738 | + !$AFEW | |
1739 | + || | |
1740 | + ( $AFEW && ($i<10 || $i>($nb-10)) ) | |
1741 | + ) | |
1742 | + echo('['.$e->nom.'] <br/>'); | |
1743 | + } | |
1744 | + } | |
1745 | + | |
1746 | + function getAllFournisseursLike($fname, $table) { | |
1747 | + $fournisseurs = $table | |
1748 | + ->find() | |
1749 | + //->where(['nom =' => $fname]); | |
1750 | + // On cherche le nom du fournisseur avec ou sans espace | |
1751 | + ->where( [ 'nom in' => [ $fname, trim($fname), " $fname", "$fname ", " $fname " ] ] ) | |
1752 | + // avec leurs materiels associés | |
1753 | + ->contain(['Materiels']) | |
1754 | + ; | |
1755 | + return $fournisseurs; | |
1756 | + } | |
1757 | + | |
1758 | + function getFournisseurWithMaxMatos($entities) { | |
1759 | + $feurs_nbmatos = []; | |
1760 | + foreach ($entities as $e) $feurs_nbmatos[$e->nom] = count($e->materiels); | |
1761 | + //$fdoublons_nbmatos = sort($fdoublons_nbmatos); | |
1762 | + //$nbmatos_max = max($feurs_nbmatos); | |
1763 | + dump($feurs_nbmatos); | |
1764 | + $fname_max = array_search( max($feurs_nbmatos), $feurs_nbmatos ); | |
1765 | + //debug($fname_max); | |
1766 | + foreach ($entities as $e) | |
1767 | + if ($e->nom == $fname_max) | |
1768 | + return $e; | |
1769 | + /* | |
1770 | + foreach ($entities as $e) { | |
1771 | + debug($e->nom); | |
1772 | + if ($e->nom == $fname_max) { | |
1773 | + debug($e->nom); | |
1774 | + return $e; | |
1775 | + } | |
1776 | + } | |
1777 | + */ | |
1778 | + } | |
1779 | + | |
1780 | + function cleanup($f, $table, $DEBUG) { | |
1781 | + $fname = trim($f->nom); | |
1782 | + if ($f->nom != trim($f->nom)) { | |
1783 | + $f->nom = trim($f->nom); | |
1784 | + !$DEBUG && $table->save($f); | |
1785 | + } | |
1786 | + } | |
1787 | + | |
1788 | + while (! $CLEAN) { | |
1789 | + // On sortira (et terminera) au prochain tour, sauf si on a trouvé un doublon | |
1790 | + $CLEAN = true; | |
1791 | + $fournisseurs = $ftable->find(); | |
1792 | + $nb = $fournisseurs->count(); | |
1793 | + print "Liste fournisseurs AVANT cleanup ($nb) : $NL $NL"; | |
1794 | + show($fournisseurs, false); | |
1795 | + print "$NL$NL"; | |
1796 | + foreach ($fournisseurs as $f) { | |
1797 | + $fname = trim($f->nom); | |
1798 | + echo $fname; | |
1799 | + // On cherche TOUS les doublons imaginables de ce fournisseur | |
1800 | + // et on les récupère AVEC leurs materiels associés | |
1801 | + $fdoublons = getAllFournisseursLike($fname, $ftable); | |
1802 | + // Pas de doublons => on passe au suivant | |
1803 | + if ( $fdoublons->count() == 1 ) { | |
1804 | + echo '<br><br>'; | |
1805 | + cleanup($f, $ftable, $DEBUG); | |
1806 | + continue; | |
1807 | + /* pour debug | |
1808 | + // VIRER | |
1809 | + $CLEAN = true; | |
1810 | + break; | |
1811 | + */ | |
1812 | + } | |
1813 | + /* Il y a des doublons => on les supprime | |
1814 | + Stratégie : | |
1815 | + - on garde seulement celui qui a le plus de matériels liés (l’élu) | |
1816 | + - on supprime les autres après avoir relié leurs matériels au fournisseur élu | |
1817 | + */ | |
1818 | + echo " (doublons) : <br>"; | |
1819 | + //show($fdoublons); | |
1820 | + //debug($fdoublons->toArray()); | |
1821 | + //dump($fdoublons->toArray()); | |
1822 | + // - a) on trie les fournisseurs selon leur nb de matos associés, et on élit celui qui en a le plus | |
1823 | + $f_max = getFournisseurWithMaxMatos($fdoublons); | |
1824 | + //debug($f_max->nom); | |
1825 | + // - b) on supprime les doublons après avoir mis à jour leurs matos associés | |
1826 | + foreach ($fdoublons as $fdoublon) { | |
1827 | + //debug($fdoublon->nom); | |
1828 | + // tous sauf f_max | |
1829 | + if ($fdoublon->nom != $f_max->nom) { | |
1830 | + //debug("diff"); | |
1831 | + // on associe les matos du doublon à f_max | |
1832 | + echo( '- Relie les matos de ['.$fdoublon->nom.']('.$fdoublon->id.') à ['.$f_max->nom.']('.$f_max->id.') :'.$NL ); | |
1833 | + foreach ($fdoublon->materiels as $m) { | |
1834 | + //debug($m); | |
1835 | + echo('-- matos '.$m->id.' : f_id='.$m->fournisseur_id.', ['.$m->designation.']'.$NL); | |
1836 | + $m->fournisseur_id = $f_max->id; | |
1837 | + //echo($m->id.': f_id='.$m->fournisseur_id.', ['.$m->designation.']'); | |
1838 | + //!$DEBUG && $this->Materiels->save($m); | |
1839 | + if ( !$this->Materiels->save($m) ) { | |
1840 | + debug("Le matériel n'a pas pu être sauvegardé !!"); | |
1841 | + debug($m->getErrors()); | |
1842 | + $host = $this->getCurrentURL(false); | |
1843 | + echo '<a href="'.$host.'/materiels/view/'.$m->id.'">Voir ce materiel pour le corriger</a>'; | |
1844 | + //throw new \ErrorException("Le matériel n'a pas pu être sauvegardé !!"); | |
1845 | + exit; | |
1846 | + } | |
1847 | + } | |
1848 | + // maintenant, on peut supprimer le doublon | |
1849 | + echo( '- Delete ['.$fdoublon->nom.']('.$fdoublon->id.')'.$NL ); | |
1850 | + !$DEBUG && $ftable->delete($fdoublon); | |
1851 | + } | |
1852 | + } | |
1853 | + // On nettoie f si besoin (on peut car maintenant il est unique) | |
1854 | + cleanup($f_max, $ftable, $DEBUG); | |
1855 | + // On quitte la boucle en cours car on a supprimé des éléments de cette boucle => il faut donc recommencer depuis le début | |
1856 | + echo '<br><br>'; | |
1857 | + if (!$DEBUG) { | |
1858 | + $CLEAN = false; | |
1859 | + break; | |
1860 | + } | |
1861 | + } // end foreach | |
1862 | + } // end while not CLEAN | |
1863 | + | |
1864 | + print "$NL$NL"; | |
1865 | + $fournisseurs = $ftable->find(); | |
1866 | + $nb = $fournisseurs->count(); | |
1867 | + print "Liste fournisseurs APRÈS cleanup ($nb) : $NL $NL"; | |
1868 | + show($fournisseurs); | |
1869 | + | |
1870 | + } | |
1871 | + | |
1695 | 1872 | /** |
1696 | 1873 | * Add or Edit method (do either add() or edit()) |
1697 | 1874 | * => Factorisation de add() et edit() | ... | ... |
src/Model/Entity/Fournisseur.php
... | ... | @@ -13,6 +13,9 @@ use Cake\ORM\Entity; |
13 | 13 | class Fournisseur extends Entity |
14 | 14 | { |
15 | 15 | |
16 | + // Ce qui s'affiche quand on fait echo $entity | |
17 | + public function __toString() { return $this->nom; } | |
18 | + | |
16 | 19 | /** |
17 | 20 | * Fields that can be mass assigned using newEntity() or patchEntity(). |
18 | 21 | * | ... | ... |
src/Model/Table/FournisseursTable.php
... | ... | @@ -28,7 +28,8 @@ class FournisseursTable extends AppTable |
28 | 28 | parent::initialize($config); |
29 | 29 | |
30 | 30 | $this->setTable('fournisseurs'); |
31 | - $this->setDisplayField('id'); | |
31 | + //$this->setDisplayField('id'); | |
32 | + $this->setDisplayField('nom'); | |
32 | 33 | $this->setPrimaryKey('id'); |
33 | 34 | |
34 | 35 | $this->hasMany('Materiels', [ | ... | ... |
src/Model/Table/MaterielsTable.php
... | ... | @@ -10,6 +10,7 @@ use Cake\I18n\Time; |
10 | 10 | use Cake\I18n\Date; |
11 | 11 | use Cake\ORM\Association\BelongsTo; |
12 | 12 | use Cake\ORM\Entity; |
13 | +use Cake\I18n\FrozenDate; | |
13 | 14 | |
14 | 15 | /** |
15 | 16 | * Materiels Model |
... | ... | @@ -47,6 +48,12 @@ use Cake\ORM\Entity; |
47 | 48 | class MaterielsTable extends AppTable |
48 | 49 | { |
49 | 50 | |
51 | + private $PREV_SEUIL_INVENTORIABLE = 800; | |
52 | + | |
53 | + private $LAST_SEUIL_INVENTORIABLE_YEAR = 2020; | |
54 | + private $LAST_SEUIL_INVENTORIABLE_DATE = '03/06/2020'; | |
55 | + private $LAST_SEUIL_INVENTORIABLE; // 1000€ pour IRAP (depuis 3/6/2020) | |
56 | + | |
50 | 57 | public $ALL_STATUS = array( |
51 | 58 | 'CREATED', |
52 | 59 | 'VALIDATED', |
... | ... | @@ -409,11 +416,12 @@ class MaterielsTable extends AppTable |
409 | 416 | |
410 | 417 | |
411 | 418 | $validator->numeric('prix_ht') |
412 | - ->allowEmpty('prix_ht') | |
419 | + // (EP202010 prix obligatoire) | |
420 | + //->allowEmpty('prix_ht') | |
413 | 421 | ->add('prix_ht', 'valid', [ |
414 | - 'rule' => 'check_string', | |
415 | - 'message' => 'Ce champ contient des caractères interdits', | |
416 | - 'provider' => 'table' | |
422 | + 'rule' => 'check_string', | |
423 | + 'message' => 'Ce champ contient des caractères interdits', | |
424 | + 'provider' => 'table' | |
417 | 425 | ]); |
418 | 426 | $validator->allowEmpty('eotp')->add('eotp', 'valid', [ |
419 | 427 | 'rule' => 'check_string', |
... | ... | @@ -537,6 +545,7 @@ class MaterielsTable extends AppTable |
537 | 545 | */ |
538 | 546 | //$this->config = TableRegistry::getTableLocator()->get('Configurations')->get(1); |
539 | 547 | $this->config = TableRegistry::getTableLocator()->get('Configurations')->find()->first(); |
548 | + $this->LAST_SEUIL_INVENTORIABLE = $this->config->prix_inventaire_administratif; | |
540 | 549 | |
541 | 550 | // 1) Définition de nos propres règles de gestion |
542 | 551 | |
... | ... | @@ -568,9 +577,14 @@ class MaterielsTable extends AppTable |
568 | 577 | // return if checked as "administratif" price MUST be set |
569 | 578 | $checkPriceIfIsAdministratif = function ($entity) { |
570 | 579 | //if ($entity->materiel_administratif) |
571 | - if (! $entity->materiel_technique) | |
572 | - return ($entity->prix_ht >= $this->config->prix_inventaire_administratif); // 1000€ pour l'IRAP | |
580 | + if (! $entity->materiel_technique) { | |
581 | + //debug($entity->date_acquisition); | |
582 | + //debug($entity->date_acquisition->format('Y')); | |
583 | + $year = $entity->date_acquisition->format('Y'); | |
584 | + $this->SEUIL_INVENTORIABLE = ($year >= $this->LAST_SEUIL_INVENTORIABLE_YEAR) ? $this->LAST_SEUIL_INVENTORIABLE : $this->PREV_SEUIL_INVENTORIABLE; | |
585 | + return ($entity->prix_ht >= $this->SEUIL_INVENTORIABLE); // 1000€ pour l'IRAP (depuis 2017 ?) | |
573 | 586 | //return ($entity->prix_ht !== null); |
587 | + } | |
574 | 588 | return true; |
575 | 589 | }; |
576 | 590 | |
... | ... | @@ -655,16 +669,20 @@ class MaterielsTable extends AppTable |
655 | 669 | 'message' => 'Le matériel vaut moins de ' . $configuration->prix_inventaire_administratif . '€ HT, il n\'est donc pas inventoriable.' |
656 | 670 | ]); |
657 | 671 | */ |
672 | + | |
673 | + /* (EP 202010 n'est plus nécessaire) | |
658 | 674 | $rules->add($checkPriceIfIsAdministratif, [ |
659 | 675 | 'errorField' => 'prix_ht', |
660 | 676 | //'message' => 'Le matériel ne peut pas être inventoriable et ne pas avoir de prix' |
661 | - 'message' => "Si le matériel n'est pas technique, son prix doit obligatoirement être supérieur à 1000€ (inventoriable)" | |
677 | + 'message' => "Si le matériel n'est pas technique, son prix HT doit obligatoirement être supérieur à ". | |
678 | + $this->LAST_SEUIL_INVENTORIABLE."€ (inventoriable)" | |
662 | 679 | ]); |
663 | 680 | $rules->add($checkPriceIfIsAdministratif, [ |
664 | 681 | 'errorField' => 'materiel_technique', |
665 | 682 | //'message' => 'Le matériel ne peut pas être inventoriable et ne pas avoir de prix' |
666 | - 'message' => "Si le matériel n'est pas technique, son prix doit obligatoirement être supérieur à 1000€ (inventoriable)" | |
683 | + 'message' => "Si le matériel n'est pas technique, son prix HT doit obligatoirement être supérieur à ".$this->LAST_SEUIL_INVENTORIABLE."€ (inventoriable)" | |
667 | 684 | ]); |
685 | + */ | |
668 | 686 | |
669 | 687 | $rules->add($rules->isUnique([ |
670 | 688 | 'numero_laboratoire' | ... | ... |
... | ... | @@ -0,0 +1,33 @@ |
1 | + | |
2 | +<div class="fournisseurs index"> | |
3 | + | |
4 | + <?php echo '<h2><i class="icon-list"></i> Nettoyage de la liste des Fournisseurs</h2>'; ?> | |
5 | + | |
6 | + <?= $this->Html->link( | |
7 | + "Nettoyage de toute la liste (suppression des doublons et des espaces en trop)", | |
8 | + ['controller'=>'Materiels', 'action' => 'exec_sql_request_for_bugfix'], | |
9 | + ['title' => 'Nettoyage', 'style' => 'margin: 0 2px', 'escape' => false ]) | |
10 | + ?> | |
11 | + | |
12 | + <br><br> | |
13 | + (TODO) Remplacer un fournisseur par un autre : | |
14 | + <br> | |
15 | + Remplacer le fournisseur FOURNISSEUR1 par FOURNISSEUR2 | |
16 | + <br><br> | |
17 | + | |
18 | + [SUBMIT] | |
19 | + | |
20 | + | |
21 | +</div> | |
22 | + | |
23 | +<!-- | |
24 | +<div class="actions"> | |
25 | + <php echo $this->element('menu') ?> | |
26 | + <php | |
27 | + | |
28 | +echo $this->element('menu_index', [ | |
29 | + 'pluralHumanName' => 'Fournisseurs', | |
30 | + 'singularHumanName' => 'Fournisseur' | |
31 | +])?> | |
32 | + </div> | |
33 | +--> | |
0 | 34 | \ No newline at end of file | ... | ... |
src/Template/Materiels/view.ctp
... | ... | @@ -311,7 +311,7 @@ $CAN_PRINT_LABEL = $IS_VALIDATED && $configuration->hasPrinter && $USER_IS_ADMIN |
311 | 311 | |
312 | 312 | // Bouton Modifier |
313 | 313 | if ($CAN_EDIT) |
314 | - $echoActionButton($this->Html, 'icon-pencil', $bStyle, ' Editer', 'materiels', 'edit', $entity->id); | |
314 | + $echoActionButton($this->Html, 'icon-pencil', $bStyle, ' Éditer', 'materiels', 'edit', $entity->id); | |
315 | 315 | |
316 | 316 | // Bouton Supprimer |
317 | 317 | if ($CAN_DELETE) |
... | ... | @@ -666,10 +666,29 @@ $CAN_PRINT_LABEL = $IS_VALIDATED && $configuration->hasPrinter && $USER_IS_ADMIN |
666 | 666 | } |
667 | 667 | |
668 | 668 | $displayElement(__('Prix (HT)'), h($entity->prix_ht) . ' €'); |
669 | - $displayElement(__('Fournisseur'), $entity->has('fournisseur') ? $entity->fournisseur->nom : ''); | |
669 | + | |
670 | + // Fournisseur (lien) | |
671 | + //$displayElement(__('Fournisseur'), $entity->has('fournisseur') ? $entity->fournisseur->nom : ''); | |
672 | + $displayElement(__('Fournisseur'), | |
673 | + $this->Html->link( | |
674 | + h($entity->fournisseur->nom), | |
675 | + ['controller'=>'Fournisseurs', 'action'=>'view', $entity->fournisseur->id] | |
676 | + ) | |
677 | + ); | |
678 | + | |
670 | 679 | $displayElement(__('Lieu de stockage'), $entity->has('site') ? h($entity->site->nom) : ''); |
671 | 680 | $displayElement(__('Détail lieu de stockage'), h($entity->lieu_detail)); |
672 | - $displayElement(__('Nom de l\'utilisateur'), $this->Html->link(h($entity->nom_responsable), 'mailto:' . h($entity->email_responsable))); | |
681 | + | |
682 | + // Acheteur (lien mailto) | |
683 | + $displayElement(__("Nom de l'acheteur"), | |
684 | + $this->Html->link( | |
685 | + h($entity->nom_responsable), | |
686 | + // Mailto | |
687 | + 'mailto:' . h($entity->email_responsable) | |
688 | + //['controller'=>'Users', 'action'=>'view', 'id'=>$entity->id] | |
689 | + ) | |
690 | + ); | |
691 | + | |
673 | 692 | $displayElement(__('N. interne (labo)'), h($entity->numero_laboratoire)); |
674 | 693 | if ($entity->gestionnaire_id) { |
675 | 694 | $gestionnaire = TableRegistry::getTableLocator()->get('Users')->get($entity->gestionnaire_id); | ... | ... |
src/Template/Pages/tools.ctp
... | ... | @@ -107,6 +107,22 @@ echo '<tr><td></td></tr>'; |
107 | 107 | |
108 | 108 | if ($role == 'Super Administrateur') : |
109 | 109 | |
110 | + // Exécution d'un script correctif (bugfix) temporaire (superadmin only) | |
111 | + echo '<tr><td>'; | |
112 | + echo $this->Html->link('Exécuter le dernier script correctif', [ | |
113 | + 'controller' => 'Materiels', | |
114 | + 'action' => 'exec_sql_request_for_bugfix' | |
115 | + ]); | |
116 | + echo '</td></tr>'; | |
117 | + | |
118 | + // Nettoyage de la liste des fournisseurs (superadmin only) | |
119 | + echo '<tr><td>'; | |
120 | + echo $this->Html->link('Nettoyer la liste des Fournisseurs', [ | |
121 | + 'controller' => 'Fournisseurs', | |
122 | + 'action' => 'cleanup' | |
123 | + ]); | |
124 | + echo '</td></tr>'; | |
125 | + | |
110 | 126 | // Page des messages de log (level info, debug, et notice) |
111 | 127 | echo '<tr><td>'; |
112 | 128 | echo $this->Html->link('Voir les messages de LOG', [ | ... | ... |