diff --git a/application/modules/admin/controllers/StatController.php b/application/modules/admin/controllers/StatController.php
index e23e2c59e0d43e73aeae13c9e79bcb0e596efd81..91459510d0643be9e4a85f6f325ffb9c9490ace5 100644
--- a/application/modules/admin/controllers/StatController.php
+++ b/application/modules/admin/controllers/StatController.php
@@ -18,82 +18,58 @@
  * along with AFI-OPAC 2.0; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
  */
-//-----------------------------------------------------------------------
-// OPAC3 - Statistiques notices
-//-----------------------------------------------------------------------
-class Admin_StatController extends Zend_Controller_Action
-{
-	private $cls_stat;											// Instance classe stat
 
-	function indexAction()
-	{
-		$this->_redirect('admin/index');
-	}
+class Admin_StatController extends Zend_Controller_Action {
+	private $cls_stat;											// Instance classe stat
 
-//-----------------------------------------------------------------------
-// Initialisation
-//-----------------------------------------------------------------------
-	function init()
-	{
-		$this->cls_stat=new Class_StatsNotices();
+	public function init() {
+		$this->cls_stat = new Class_StatsNotices();
 		$css = '<link rel="stylesheet" type="text/css" media="screen" href="'.URL_ADMIN_CSS.'statistique.css" />';
 		$this->getResponse()->setBody($css);
 	}
 
-//-----------------------------------------------------------------------
-// Visualisations de notices
-//-----------------------------------------------------------------------
-	function visunoticeAction()
-	{
+	
+	public function preDispatch() {
+		$this->view->periode = $this->cls_stat->getPeriode();
+	}
+
+
+	public function indexAction() {
+		$this->_redirect('admin/index');
+	}
+
+
+	public function visunoticeAction() {
 		$this->view->titre = 'Statistiques de visualisation des notices';
-		$this->view->periode=$this->cls_stat->getPeriode(0,0);
-		$this->view->table_stat=$this->cls_stat->getRecapVisu();
+		$this->view->table_stat = $this->cls_stat->getRecapVisu();
 	}
 	
-//-----------------------------------------------------------------------
-// Palmares Visualisations de notices
-//-----------------------------------------------------------------------
-	function palmaresvisunoticeAction()
-	{
+
+	public function palmaresvisunoticeAction() {
 		$this->view->titre = 'Palmarès des visualisations de notices';
-		$this->view->periode = $this->cls_stat->getPeriode(0,0);
-		$this->view->table_stat = $this->cls_stat->getPalmaresVisu($_REQUEST["type_doc"]);
+		$this->view->table_stat = $this->cls_stat->getPalmaresVisu($this->_getParam('type_doc'));
 	}
 	
-//-----------------------------------------------------------------------
-// Recherches infructueuses
-//-----------------------------------------------------------------------
-	function rechercheinfructueuseAction()
-	{
+
+	public function rechercheinfructueuseAction() {
 		$this->view->titre = 'Recherches infructueuses';
+		$page = $this->_getParam('page', 1);
 		$this->view->nb_par_page = 20;
-		$page = $this->_getParam('page');
-		if(!$page) $page=1;
-		$this->view->page=$page;
-		$limit=($page-1) * $this->view->nb_par_page;
-		$limit=" limit ".$limit.",".$this->view->nb_par_page;
-		$this->view->nombre_total=fetchOne("select count(*) from stats_recherche_echec");
-		$req="select * from stats_recherche_echec order by id desc ".$limit;
-		$this->view->liste = fetchAll($req);
+		$start = ($page-1) * $this->view->nb_par_page;
+		$this->view->liste = $this->cls_stat->getNotFoundByPage($page, $this->view->nb_par_page);
+		$this->view->nombre_total = $this->cls_stat->getTotalNotFound();
+		$this->view->page = $page;
 	}
 
-//-----------------------------------------------------------------------
-// Réservations de notices
-//-----------------------------------------------------------------------
-	function reservationnoticeAction()
-	{
+
+	public function reservationnoticeAction() {
 		$this->view->titre = 'Statistiques des réservations de notices';
-		$this->view->periode=$this->cls_stat->getPeriode(0,0);
-		$this->view->table_stat=$this->cls_stat->getRecapReservation();
+		$this->view->table_stat = $this->cls_stat->getRecapReservation();
 	}
 
-//-----------------------------------------------------------------------
-// Palmares Réservations de notices
-//-----------------------------------------------------------------------
-	function palmaresreservationnoticeAction()
-	{
+
+	public function palmaresreservationnoticeAction() {
 		$this->view->titre = 'Palmarès des réservations de notices';
-		$this->view->periode=$this->cls_stat->getPeriode(0,0);
-		$this->view->table_stat=$this->cls_stat->getPalmaresReservation($_REQUEST["type_doc"]);
+		$this->view->table_stat = $this->cls_stat->getPalmaresReservation($this->_getParam('type_doc'));
 	}
 }
\ No newline at end of file
diff --git a/application/modules/admin/views/scripts/stat/reservationnotice.phtml b/application/modules/admin/views/scripts/stat/reservationnotice.phtml
index ecc0ea3d1e6750551fbfd97fef4fb91bb7466374..b635c301e7ed041d722ab1fbed2adfd19ffc1487 100644
--- a/application/modules/admin/views/scripts/stat/reservationnotice.phtml
+++ b/application/modules/admin/views/scripts/stat/reservationnotice.phtml
@@ -1,33 +1,15 @@
+<h2 class="stat"><?php echo $this->periode;?>, 
+<?php echo number_format($this->table_stat["total"], 0, ',', ' ');?> 
+demandes de réservation ont été effectuées</h2>
+
+<h3 class="stat">Détail par années</h3>
 <?php 
-print('<h2 class="stat">'.$this->periode.", ".number_format($this->table_stat["total"], 0, ',', ' ').' demandes de réservation ont été effectuées</h2>');
-print('<h3 class="stat">Détail par années</h3>');
-printBlocStat("Année",$this->table_stat["annees"],$this->table_stat["graphes"]["annees"]);
-print('<h3 class="stat">Détail par mois</h3>');
-printBlocStat("Mois",$this->table_stat["mois"],$this->table_stat["graphes"]["mois"]);
+	 if (isset($this->table_stat['annees']))
+		 echo $this->blocStats('Année', $this->table_stat['annees']);?>
 
-// Bloc stat : tableau et graphe
-function printBlocStat($titre,$table,$graphe)
-{
-	// container principal
-	print('<table><tr><td valign="top">');
-	// Tableau
-	print('<table class="stat" style="width:180px;margin-left:10px"><tr>');
-	print('<th class="stat" width="70%">'.$titre.'</th>');
-	print('<th class="stat" width="30%">Nombre</th>');
-	print('</tr>');
-	foreach($table as $libelle => $nombre)
-	{
-		print('<tr>');
-		print('<td class="stat_libelle">'.$libelle.'</td>');
-		print('<td class="stat_nombre">'.$nombre.'</td>');
-		print('</tr>');
-	}
-	print('</table></td>');
-	// Graphe
-	print('<td>'.$graphe.'</td>');
-	// Fini
-	print('</tr></table>');
-}
-?>
+<h3 class="stat">Détail par mois</h3>
+<?php 
+	 if (isset($this->table_stat['mois']))
+		 echo $this->blocStats('Mois',	$this->table_stat['mois']);?>
 
 <br>
diff --git a/application/modules/admin/views/scripts/stat/visunotice.phtml b/application/modules/admin/views/scripts/stat/visunotice.phtml
index 78ef09b53cef062b044889cb2cd70195d96d0be1..e9fdf4e3361e6d54a55a6bbd88ba8ffe2172d817 100644
--- a/application/modules/admin/views/scripts/stat/visunotice.phtml
+++ b/application/modules/admin/views/scripts/stat/visunotice.phtml
@@ -1,35 +1,28 @@
-<?php 
-print('<h2 class="stat">'.$this->periode.", ".number_format($this->table_stat["total"], 0, ',', ' ').' notices ont été visualisées</h2>');
-print('<h3 class="stat">Détail par années</h3>');
-printBlocStat("Année",$this->table_stat["annees"],$this->table_stat["graphes"]["annees"]);
-print('<h3 class="stat">Détail par mois</h3>');
-printBlocStat("Mois",$this->table_stat["mois"],$this->table_stat["graphes"]["mois"]);
+<h2 class="stat">
+<?php echo $this->periode;?>, 
+<?php echo number_format($this->table_stat["total"], 0, ',', ' ');?> notices ont été visualisées
+</h2>
+
+<script>
+	 $(function(){$('#accordion').accordion({autoHeight:false, collapsible:true});});
+</script>
 
-// Bloc stat : tableau et graphe
-function printBlocStat($titre,$table,$graphe)
-{
-	if (!$table)
-		return;
-	// container principal
-	print('<table><tr><td valign="top">');
-	// Tableau
-	print('<table class="stat" style="width:180px;margin-left:10px"><tr>');
-	print('<th class="stat" width="70%">'.$titre.'</th>');
-	print('<th class="stat" width="30%">Nombre</th>');
-	print('</tr>');
-	foreach($table as $libelle => $nombre)
-	{
-		print('<tr>');
-		print('<td class="stat_libelle">'.$libelle.'</td>');
-		print('<td class="stat_nombre">'.$nombre.'</td>');
-		print('</tr>');
-	}
-	print('</table></td>');
-	// Graphe
-	print('<td>'.$graphe.'</td>');
-	// Fini
-	print('</tr></table>');
-}
-?>
+<?php if (isset($this->table_stat)) { ?>
+<h3 class="stat">Détail par années</h3>
+<?php 
+$years = [];
+foreach ($this->table_stat as $label => $datas)
+	if (isset($datas['total']))
+		$years[$label] = $datas['total'];
+echo $this->blocStats('Année', $years);?>
 
+<h3 class="stat">Détail par mois</h3>
+<div id="accordion">
+<?php foreach ($this->table_stat as $label => $datas) { 
+if (!isset($datas['mois'])) continue;?>
+<h4><?php echo $label;?></h4>
+<?php echo $this->blocStats('Mois',	$datas['mois']);?>
+<?php } ?>
+</div>
+<?php } ?>
 <br>
diff --git a/library/Class/StatsNotices.php b/library/Class/StatsNotices.php
index 88f9d747b7da3f3aa75f11137e6a3fb6d7ac0152..629b241eff9f50e4e069a8cefa24da1b5f0ed16e 100644
--- a/library/Class/StatsNotices.php
+++ b/library/Class/StatsNotices.php
@@ -64,7 +64,7 @@ class Class_StatsNotices {
 			$msg = 'en ' . $msg;
 		} else {
 			if ($annee = fetchOne('select min(annee) from stats_notices'))
-				$mois = fetchOne("select min(mois) from stats_notices where annee=$annee");
+				$mois = fetchOne('select min(mois) from stats_notices where annee=' . $annee);
 			$msg = 'depuis ' . $this->lib_mois[$mois] . ' ' . $annee;
 		}
 		return $msg;
@@ -72,27 +72,24 @@ class Class_StatsNotices {
 
 
 	public function getRecapVisu() {
-		// Par années
-		$liste = fetchAll("Select annee, sum(nb_visu) from stats_notices group by 1");
+		$ret = ['total' => 0, 'annees' => [], 'mois' => [], 'graphes' => []];
+		$liste = fetchAll('Select annee, sum(nb_visu) from stats_notices group by 1 order by annee desc');
 		$total = 0;
 		foreach($liste as $stat) {
 			$annee = $stat["annee"];
 			$nombre = $stat["sum(nb_visu)"];
 			$total += $nombre;
-			$ret["annees"][$annee]=$nombre;
+			$ret[$annee] = ['total' => $nombre, 'mois' => []];
 		}
 		$ret["total"] = $total;
-		$ret["graphes"]["annees"] = $this->getGraphe($ret["annees"], $total);
 		
-		// Par mois
-		$liste = fetchAll("Select mois, sum(nb_visu) as cnt from stats_notices group by 1");
+		$liste = fetchAll("Select annee, mois, nb_visu as cnt from stats_notices order by annee desc, mois desc");
 		foreach ($liste as $stat) {
-			$mois = $this->lib_mois[$stat["mois"]];
-			$nombre = $stat["cnt"];
-			$ret["mois"][$mois] = $nombre;
+			$mois = $this->lib_mois[$stat['mois']];
+			$nombre = $stat['cnt'];
+			$ret[$stat['annee']]['mois'][$mois] = $nombre;
 		}
 
-		$ret["graphes"]["mois"] = $this->getGraphe($ret["mois"], $total);
 		return $ret;
 	}
 
@@ -168,27 +165,14 @@ class Class_StatsNotices {
 	}
 
 
-	public function getGraphe($data_graphe, $total) {
-		$nb_rubriques = count($data_graphe);
-		if (!$nb_rubriques)
-			return false;
-		
-		// Constituer les arguments pour google
-		$datas = $labels = [];
-		foreach($data_graphe as $label => $data) {
-			$datas[] = ($data and $total) ? (int)($data / $total * 100) : 0;
-			$labels[] = $label;
-		}
-
-		$chd = implode(',', $datas);
-		$chl = implode('|', $labels);
+	public function getTotalNotFound() {
+		return fetchOne('select count(*) from stats_recherche_echec');
+	}
 
-		$taille = ($nb_rubriques < 5) ? 
-			'chs=200x120&amp;cht=bvg': 
-			'chs=450x200&amp;cht=p3';
 
-		$url_google = $this->url_google . $taille . "&amp;chd=t:" . $chd . "&amp;chl=" . $chl;
-		return '<img src="' . $url_google . '" border="0">';
+	public function getNotFoundByPage($start, $count) {
+		return fetchAll(sprintf('select * from stats_recherche_echec order by id desc limit %s, %s',
+														$start, $count));
 	}
 
 
diff --git a/library/ZendAfi/View/Helper/Admin/BlocStats.php b/library/ZendAfi/View/Helper/Admin/BlocStats.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed6d064fde76aa1d2f421cd5ae7207d481898c18
--- /dev/null
+++ b/library/ZendAfi/View/Helper/Admin/BlocStats.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * AFI-OPAC 2.0 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with AFI-OPAC 2.0; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ */
+class ZendAfi_View_Helper_Admin_BlocStats extends ZendAfi_View_Helper_BaseHelper {
+	const GOOGLE_URL = 'http://chart.apis.google.com/chart?';
+
+	public function blocStats($title, $datas) {
+		if (!$datas)
+			return;
+
+		$html = '<table><tr><td valign="top">' 
+			. '<table class="stat" style="width:180px;margin-left:10px"><tr>'
+			. '<th class="stat" width="70%">' . $title . '</th>'
+			. '<th class="stat" width="30%">Nombre</th>'
+			. '</tr>';
+
+		foreach ($datas as $label => $count)
+			$html .= $this->_dataFor($label, $count);
+		
+		$html .= '</table></td>'
+			. '<td>'. $this->_graph($datas) . '</td>'
+			. '</tr></table>';
+
+		return $html;
+	}
+
+
+	protected function _dataFor($label, $count) {
+		return '<tr>'
+			. '<td class="stat_libelle">' . $label . '</td>'
+			. '<td class="stat_nombre">' . $count . '</td>'
+			. '</tr>';
+	}
+
+
+	protected function _graph($graph_datas) {
+		if (empty($graph_datas))
+			return false;
+		
+		$total = 0;
+		array_walk($graph_datas, function($item) use (&$total) {$total += $item;});
+
+		$datas = $labels = [];
+		array_walk($graph_datas, function($data, $label) use ($total, &$datas, &$labels) {
+		  $datas[] = ($data and $total) ? (int)($data / $total * 100) : 0;
+			$labels[] = $label;						 
+	  });
+
+		$chd = implode(',', $datas);
+		$chl = implode('|', $labels);
+
+		$taille = (count($datas) < 5) ? 
+			'chs=200x120&amp;cht=bvg': 
+			'chs=450x200&amp;cht=p3';
+
+		return '<img src="' . self::GOOGLE_URL . $taille . "&amp;chd=t:" . $chd . "&amp;chl=" . $chl . '" border="0">';
+	}
+}
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/StatControllerTest.php b/tests/application/modules/admin/controllers/StatControllerTest.php
index a75b8bffa97441035b3fa4ee7fe5c659d4ff07a7..5cc95f27717aeee20d963dd98ff947fbc6507cee 100644
--- a/tests/application/modules/admin/controllers/StatControllerTest.php
+++ b/tests/application/modules/admin/controllers/StatControllerTest.php
@@ -36,6 +36,30 @@ class Admin_StatControllerRecherchesInfructueusesTest extends Admin_AbstractCont
 class Admin_StatControllerVisunoticeTest extends Admin_AbstractControllerTestCase{
 	public function setUp() {
 		parent::setUp();
+		$this->sql = $this->mock()
+			->whenCalled('fetchAll')
+			->with('Select annee, sum(nb_visu) from stats_notices group by 1 order by annee desc', false)
+			->answers([['annee' => '2000', 'sum(nb_visu)' => 6000],])
+
+			->whenCalled('fetchAll')
+			->with('Select annee, mois, nb_visu as cnt from stats_notices order by annee desc, mois desc',
+						 false)
+			->answers([['annee' => '2000', 'mois' => 1, 'cnt' => 42],])
+			
+			->whenCalled('fetchOne')
+			->with('select min(annee) from stats_notices')
+			->answers('2000')
+			
+			->whenCalled('fetchOne')
+			->with("select min(mois) from stats_notices where annee=2000")
+			->answers('1')
+
+			->whenCalled('fetchOne')
+			->answers('1');
+
+
+		Zend_Registry::set('sql', $this->sql);
+
 		$this->dispatch('/admin/stat/visunotice', true);
 	}
 
@@ -44,6 +68,54 @@ class Admin_StatControllerVisunoticeTest extends Admin_AbstractControllerTestCas
 	public function titreShouldBeVisualisationNotice() {
 		$this->assertXPathContentContains('//h1', 'visualisation des notices');
 	}
+
+
+	/** @test */
+	public function shouldHaveYearDetails() {
+		$this->assertXPathContentContains('//h3', 'Détail par années');
+	}
+
+
+	/** @test */
+	public function shouldHaveYear2000Label() {
+		$this->assertXPathContentContains('//td', '2000');
+	}
+
+
+	/** @test */
+	public function shouldHaveYear2000Detail() {
+		$this->assertXPathContentContains('//td', '6000');
+	}
+
+
+	/** @test */
+	public function shouldHaveYearsGraph() {
+		$this->assertXPath('//img[contains(@src, "chl=2000")]');
+	}
+
+
+	/** @test */
+	public function shouldHaveMonthDetails() {
+		$this->assertXPathContentContains('//h3', 'Détail par mois');
+	}
+
+
+	/** @test */
+	public function shouldHaveMonth1DetailLabel() {
+		$this->assertXPathContentContains('//td', 'janvier');
+	}
+
+
+	/** @test */
+	public function shouldHaveMonth1DetailCount() {
+		$this->assertXPathContentContains('//td', '42');
+	}
+
+	/** @test */
+	public function shouldHaveMonthsGraph() {
+		$this->assertXPath('//img[contains(@src, "janvier")]',
+											 $this->_response->getBody());
+	}
 }
 
 ?>
\ No newline at end of file