diff --git a/VERSIONS b/VERSIONS
index 534b3a3861ff9421241dcecba1af7fd6f3b6d4c5..9f67b838c0f025f7b19fe2f3e8e6e9ffca690d3b 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,3 +1,16 @@
+24/01/2017 - v7.7.29
+
+ - ticket #52287 : Agendas externes : adaptation du parser iCal aux flux Archimed Ermes.
+
+ - ticket #51508 : Cosmogramme : correction de l'erreur SQL en création de section
+
+ - ticket #50082 : Compte abonné : correction des liens vers les notices dans la liste des prêts
+
+ - ticket #54111 : Boite bibliothèque : sélectionner le champ à afficher "horaire" affiche toutes les horaires, comme sur la fiche bibliothèque.
+ 
+- ticket #54626 : compatibilité PHP 7.1
+
+
 19/01/2017 - v7.7.28
 
  - ticket #47505 : Ressources CDScript : le lien de consultation dans la table des exemplaires ouvre une popup d'authentification lorsque l'utilisateur n'est pas connecté
diff --git a/application/modules/opac/controllers/RechercheController.php b/application/modules/opac/controllers/RechercheController.php
index 3299fce676b02b26b3ef1fb47bcbc8af4ffc4399..6a7b0611b63fc898cac2350932cc48828f5a2303 100644
--- a/application/modules/opac/controllers/RechercheController.php
+++ b/application/modules/opac/controllers/RechercheController.php
@@ -597,7 +597,7 @@ class RechercheController extends ZendAfi_Controller_Action {
 
     $current_hold = null;
     foreach($user->getReservations() as $hold) {
-      if (!$opac_item = $hold->getExemplaire()->getExemplaireOPAC())
+      if (!$opac_item = $hold->getExemplaireOPAC())
         continue;
 
       if ($item_id == $opac_item->getId()) {
@@ -606,12 +606,11 @@ class RechercheController extends ZendAfi_Controller_Action {
       }
     }
 
-    return ($current_hold
-            && ($location_label = $current_hold->getPickupLocationLabel())) ?
-      $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible pour être retiré à : %s',
-                     $this->_getMessageNoticeLabel($item_id), $location_label) :
-      $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible',
-                     $this->_getMessageNoticeLabel($item_id));
+    return ($current_hold && ($location_label = $current_hold->getPickupLocationLabel()))
+      ? $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible pour être retiré à : %s',
+                       $this->_getMessageNoticeLabel($item_id), $location_label)
+      : $this->view->_('Votre réservation est enregistrée.<br>Nous vous informerons quand le document%s sera disponible',
+                       $this->_getMessageNoticeLabel($item_id));
   }
 
 
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/SectionController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/SectionController.php
new file mode 100644
index 0000000000000000000000000000000000000000..12e8d870e21e0d39c14eaada2d032c2044bbf422
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/SectionController.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Cosmo_SectionController extends ZendAfi_Controller_Action {
+  public function getPlugins() {
+    return ['ZendAfi_Controller_Plugin_ResourceDefinition_Section',
+            'ZendAfi_Controller_Plugin_Manager_Section'];
+  }
+}
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/add.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/add.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..4cbf41858aff0ec2e6a75bb2528a42c4a2fe5b07
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/add.phtml
@@ -0,0 +1,3 @@
+<?php
+echo $this->renderForm($this->form);
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/edit.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/edit.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..4cbf41858aff0ec2e6a75bb2528a42c4a2fe5b07
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/edit.phtml
@@ -0,0 +1,3 @@
+<?php
+echo $this->renderForm($this->form);
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/index.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..171db88906e56271ab3a15e405c848fb9b3ea9db
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/section/index.phtml
@@ -0,0 +1,17 @@
+<?php
+echo $this->tagAnchor(['action' => 'add',
+                       'id' => null],
+                      $this->_('Ajouter une section'));
+echo $this->tagModelTable($this->sections,
+                          [$this->_('libellé'),
+                           $this->_('Règles de reconnaissance'),
+                           $this->_('Rejeter les exemplaires')],
+                          ['libelle',
+                           'regles',
+                           'invisible'],
+                          [function($model)
+                           {
+                             return $this->renderPluginsActions($model);
+                           }],
+                          'sections');
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..fef7aaf33b9fca6fe452cc7593beeb13690724a3
--- /dev/null
+++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/SectionControllerTest.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class Cosmo_SectionControllerTestCase extends CosmoControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+    $this->fixture('Class_CodifSection',
+                   ['id' => 5,
+                    'libelle' => '01 Energie Enjeux',
+                    'regles' => '995$q=98']);
+
+    $this->fixture('Class_CodifSection',
+                   ['id' => 7,
+                    'libelle' => '01 Energie Politique',
+                    'regles' => '995$q=99']);
+  }
+}
+
+
+
+
+class Cosmo_SectionControllerIndexTest extends Cosmo_SectionControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/cosmo/section', true);
+  }
+
+
+  /** @test */
+  public function addNewSectionShouldBePresent() {
+    $this->assertXPath('//a', 'Ajouter une section');
+  }
+
+
+  /** @test */
+  public function energieEnjeuxShouldBeInTable() {
+    $this->assertXPathContentContains('//table//tr//td', '01 Energie Enjeux');
+  }
+
+
+  /** @test */
+  public function energiePolitiqueShouldBeInTable() {
+    $this->assertXPathContentContains('//table//tr//td', '01 Energie Politique');
+  }
+
+
+  /** @test */
+  public function editEnergiePolitiqueShouldBePresent() {
+    $this->assertXPath('//table//tr//td//a[contains(@href, "/cosmo/section/edit/id/7")]');
+  }
+}
+
+
+
+
+class Cosmo_SectionControllerActionsTest extends Cosmo_SectionControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+  }
+
+
+  /** @test */
+  public function inputLibelleShouldBePresent() {
+    $this->dispatch('/cosmo/section/edit/id/7', true);
+    $this->assertXPath('//form//input[@value="01 Energie Politique"]');
+  }
+
+
+  /** @test */
+  public function postLibelle02ShouldSaveSection() {
+    $this->postDispatch('/cosmo/section/edit/id/7',
+                        ['libelle' => '02 Energie Politique']);
+    $this->assertEquals('02 Energie Politique', Class_CodifSection::find(7)->getLibelle());
+  }
+
+
+  /** @test */
+  public function deleteEnergiePolitiqueShouldRemoveItFromDB() {
+    $this->dispatch('/cosmo/section/delete/id/7', true);
+    $this->assertNull(Class_CodifSection::find(7));
+  }
+
+
+  /** @test */
+  public function deleteEnergiePolitiqueShouldRedirectToSectionIndex() {
+    $this->dispatch('/cosmo/section/delete/id/7', true);
+    $this->assertRedirectTo('/cosmo/section/index');
+  }
+}
\ No newline at end of file
diff --git a/cosmogramme/php/_init.php b/cosmogramme/php/_init.php
index 090fe6e06466679e5775493eed46370fea1fcc61..248610c3978799f9677ec08186c6a47c1493e61b 100644
--- a/cosmogramme/php/_init.php
+++ b/cosmogramme/php/_init.php
@@ -1,7 +1,7 @@
 <?php
 error_reporting(E_ERROR | E_PARSE);
 
-define("PATCH_LEVEL","315");
+define("PATCH_LEVEL","316");
 
 define("APPLI","cosmogramme");
 define("COSMOPATH", "/var/www/html/vhosts/opac2/www/htdocs");
diff --git a/cosmogramme/php/_menu.php b/cosmogramme/php/_menu.php
index 4e8ed257ab39f852f25dff736242f2fedc2229b5..13aea8c795bef4577400207bbdc93fd7882d4007 100644
--- a/cosmogramme/php/_menu.php
+++ b/cosmogramme/php/_menu.php
@@ -100,7 +100,7 @@ else
 	?>
 	<div class="menu_section">Autorités et codifications</div>
 	<?php
-	ligneMenu("Sections","codif_section.php");
+	ligneMenu("Sections","../cosmozend/cosmo/section");
 	ligneMenu("Genres","codif_genre.php");
 	ligneMenu("Emplacements", '../cosmozend/cosmo/emplacement');
 	ligneMenu("Auteurs","codif_auteur.php");
diff --git a/cosmogramme/php/classes/classe_parseur.php b/cosmogramme/php/classes/classe_parseur.php
index 8535816c8eba44642af81074b67d564cecc142ba..2170150c6630c6eb6dccceb47a545bfd783f5219 100644
--- a/cosmogramme/php/classes/classe_parseur.php
+++ b/cosmogramme/php/classes/classe_parseur.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 class parseur {
@@ -38,7 +38,7 @@ class parseur {
 
 	protected $_fileSystem;
 
-	public function open($fic, $format, $pointeur_reprise, $id_profil=0) {
+	public function open($fic, $format, $pointeur_reprise = 0, $id_profil=0) {
 		$this->formatFichier = $format;
 		$fileSystem = $this->getFileSystem();
 		$this->hFic = @$fileSystem->fopen($fic, 'rb');
@@ -64,10 +64,10 @@ class parseur {
 		}
 		return true;
 	}
-	
+
 
 	public function close()	{
-		if($this->hFic) 
+		if($this->hFic)
 			$this->getFileSystem()->fclose($this->hFic);
 		unset($this->hFic);
 	}
@@ -78,7 +78,7 @@ class parseur {
 		$fileSystem = $this->getFileSystem();
 		switch($this->formatFichier) {
 		case self::FORMAT_UNIMARC:
-			$ret = $this->nextUnimarc($this->hFic); 
+			$ret = $this->nextUnimarc($this->hFic);
 			$this->pointeur_reprise += strlen($ret['data']);
 			break;
 		case self::FORMAT_ASCII_TAB:
@@ -88,7 +88,7 @@ class parseur {
 			}
 			break;
 		case self::FORMAT_ASCII_COMMA:
-			$ret = $this->nextAscii($this->hFic, ';');	
+			$ret = $this->nextAscii($this->hFic, ';');
 			$this->pointeur_reprise = $fileSystem->ftell($this->hFic);
 			break;
 		case self::FORMAT_ASCII_PIPE:
@@ -104,7 +104,7 @@ class parseur {
 			$this->pointeur_reprise = $fileSystem->ftell($this->hFic);
 			break;
 		case self::FORMAT_MARC21:
-			$ret = $this->nextUnimarc($this->hFic); 
+			$ret = $this->nextUnimarc($this->hFic);
 			$this->pointeur_reprise += strlen($ret['data']);
 			break;
 		}
@@ -119,7 +119,7 @@ class parseur {
 
 
 	public function getEnreg($adresse) {
-		if(!$this->hFic) 
+		if(!$this->hFic)
 			afficherErreur('Il faut d\'abord ouvrir le fichier');
 		$this->pointeur_reprise = $adresse;
 		$this->buffer = '';
@@ -169,7 +169,7 @@ class parseur {
 	private function nextAscii($hFic, $separateur) {
 		$fileSystem = $this->getFileSystem();
 		$data = trim($fileSystem->fgets($hFic));
-		if ($separateur != chr(9)) 
+		if ($separateur != chr(9))
 			$data = str_replace($separateur, chr(9), $data);
 
 		return ['data' => $data,
@@ -187,7 +187,7 @@ class parseur {
 			// trouvé un enreg
 			if(!$pos_debut) {
 				$pos_debut=stripos($data,$debut_enreg);
-				if($pos_debut !== false ) 
+				if($pos_debut !== false )
 					$data=substr($data,$pos_debut);
 			}
 			if($pos_debut !== false) {
@@ -202,14 +202,14 @@ class parseur {
 			// lecture buffer
 			$enreg = $fileSystem->fread($hFic, $long);
 			if ($fileSystem->feof($hFic)) {
-				if($enreg == false) { 
-					$ret["statut"] = "eof"; 
-					return $ret; 
+				if($enreg == false) {
+					$ret["statut"] = "eof";
+					return $ret;
 				}
 			}
 			$data .= $enreg;
 		}
-		
+
 		// Retour ok
 		$ret["statut"] = "ok";
 		$ret["data"] = $data;
diff --git a/cosmogramme/php/classes/classe_unimarc.php b/cosmogramme/php/classes/classe_unimarc.php
index 5dcc647418c1d5248f9ac207bb5cf2578776d6cf..69ce9a40d46685950136c81b735a3290257eeca9 100644
--- a/cosmogramme/php/classes/classe_unimarc.php
+++ b/cosmogramme/php/classes/classe_unimarc.php
@@ -765,7 +765,7 @@ class notice_unimarc extends iso2709_record {
       $ex = $this->withExemplaireDo(
         $exemplaire,
         function($champ, &$ex) use ($ret, $codes_barres, $cotes) {
-          return $this->getPMBExemplaire($champ,$ex,$code_barres,$cotes);
+          return $this->getPMBExemplaire($champ,$ex, $ret, $code_barres,$cotes);
         });
 
       if ($ex["code_barres"]>"") {
diff --git a/cosmogramme/php/codif_section.php b/cosmogramme/php/codif_section.php
deleted file mode 100644
index 932cb70f691cf87aaddc19df7c2ec70e079ce52b..0000000000000000000000000000000000000000
--- a/cosmogramme/php/codif_section.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?PHP
-/**
- * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH 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).
- *
- * BOKEH 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 BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
- */
-///////////////////////////////////////////////////////////////////
-//
-//        CODIFS : SECTIONS
-//
-////////////////////////////////////////////////////////////////////
-include("_init_frame.php");
-
-require_once( "fonctions/objets_saisie.php");
-
-?>
-
-<h1>Codification des sections</h1>
- 
-<?PHP
-
-//---------------------------------------------------------------------------------
-// CREER
-//---------------------------------------------------------------------------------
-if($_REQUEST["action"]=="CREER")
-{
-	$action=array("libelle" => "** nouvelle section **","regles" => "995\$j=a");
-	print(BR.BR.BR);
-	afficherSection($action,"block");
-	print('</form></body></html>');
-	exit;
-}
-//---------------------------------------------------------------------------------
-// VALIDER
-//---------------------------------------------------------------------------------
-if($_REQUEST["action"]=="VALIDER")
-{
-	// Vérif de la syntaxe des règles
-	$regles=trim($_POST["regles"]);
-	if(! $regles) erreurFormat("Vous devez définir au moins une règle");
-	$regles=str_replace(" ","",$regles);
-	$test = explode("\n",$regles);
-	foreach($test as $regle)
-		{
-			$nb++;
-			$zone=substr($regle,0,3); if(intval($zone) != $zone) erreurFormat("La zone est mal définie pour la règle n° ".$nb);
-			if(substr($regle,3,1) != "\$") erreurFormat("Le \$ est absent ou mal positionné pour la règle n° ".$nb);
-			$champ=substr($regle,4,1); if(($champ < "0" or $champ >"9") and ($champ < "a" or $champ > "z")) erreurFormat("Le champ est mal défini pour la règle n° ".$nb);
-			$valeurs=substr($regle,6); if(!trim($valeurs)) erreurFormat("Indiquez des valeurs pour la règle n° ".$nb);
-			$signe=substr($regle,5,1); if( strpos("=/*",$signe) === false) erreurFormat("Signe de comparaison incorrect pour la règle n° ".$nb);
-			$elem=explode(" ",$regle);
-		}
-	
-	// ecriture
-	if(!isset($_POST["invisible"])) $_POST["invisible"]="0";
-	$id_section=$_POST["id_section"];
-	$_POST["regles"]=$regles;
-	if(!$id_section) $sql->insert("codif_section",$_POST);
-	else 
-	{
-		unset($_POST["id_section"]);
-		$sql->update("update codif_section set @SET@ where id_section=$id_section",$_POST);
-	}
-
-}
-//---------------------------------------------------------------------------------
-// SUPPRIMER
-//---------------------------------------------------------------------------------
-
-if($_REQUEST["action"]=="SUPPRIMER")
-{
-	$id_section=$_REQUEST["id_section"];
-	if($id_section)	$sql->execute("delete from codif_section where id_section =$id_section");
-}
-
-//---------------------------------------------------------------------------------
-// LISTE 
-//---------------------------------------------------------------------------------
-print('<div class="liste">');
-
-$liste=$sql->fetchAll("Select * from codif_section order by libelle");
-for($p=0; $p< count($liste); $p++)
-{
-	$section=$liste[$p];
-	$img="plus.gif";
-	$display="none";
-	if($section["id_section"] == $_REQUEST["id_section"])
-		{
-			$img="moins.gif";
-			$display="block";
-		}
-		print('<div class="liste_img"><img id="Isection'.$section["id_section"].'" src="'.URL_IMG.$img.'" onclick="contracter_bloc(\'section'.$section["id_section"].'\')" style="cursor:pointer"></div>');
-		print('<div class="liste_titre">'. $section["libelle"].'</div>');
-		affichersection($section,$display);
-}
-print('</div>');
-// Bouton ajouter
-$bouton_ajout=rendBouton("Ajouter une section","codif_section","action=CREER");
-print(BR.BR.$bouton_ajout);
-
-print('</body></html>');
-exit;
-
-function affichersection($section,$display)
-{
-	print('<div class="form" id="section'.$section["id_section"].'" style="width:600px;margin-left:20px;display:'.$display.'">');
-	print('<form method="post" action="'.URL_BASE.'php/codif_section.php?action=VALIDER">');
-	print('<input type="hidden" name="id_section" value="'.$section["id_section"].'">');
-	print('<table class="form" cellspacing="0" cellpadding="5">');
-	print('<tr><th class="form" colspan="2" align="left">Création de section</th></tr>');
-	print('<tr><td class="form_first" align="right" width="35%">Libellé</td><td class="form_first">'.getChamp("libelle",$section["libelle"],43).'</td></tr>');
-	print('<tr><td class="form_first" align="center" colspan="2"><div class="commentaire">Syntaxe : [zone$champ][signe][valeur1;valeur2;etc...] - Ex : 995$a = a<br>Signes : "=" égal - "/" commence par - "*" contient</div></td></tr>');
-	print('<tr><td class="form" align="right" valign="top">Règles de reconnaissance</td><td class="form">'.getTextarea("regles",$section["regles"],40,5).'</td></tr>');
-	if($section["invisible"]==1) $checked="checked"; else $checked="";
-	print('<tr><td class="form_first" align="right" width="35%">Rejeter les exemplaires</td><td class="form_first"><input type="checkbox" value="1" '.$checked.' name="invisible"></td></tr>');
-	
-	// Boutons maj
-	print('<tr><th class="form" colspan="2" align="center">');
-	$bouton_valider='<input type="submit" class="bouton" value="Valider">';
-	$bouton_supprimer=rendBouton("Supprimer","codif_section","action=SUPPRIMER&id_section=".$section["id_section"]);
-	print($bouton_valider.str_repeat("&nbsp;",5).$bouton_supprimer);
-	print('</th></tr></table></form></div>');
-}
-
-function erreurFormat($erreur)
-{
-	print('<span class = "rouge">'.$erreur.'</span>');
-	$action=$_POST;
-	print(BR.BR.BR);
-	afficherSection($action,"block");
-	print('</form></body></html>');
-	exit;
-}
-?>
\ No newline at end of file
diff --git a/cosmogramme/sql/patch/patch_316.php b/cosmogramme/sql/patch/patch_316.php
new file mode 100644
index 0000000000000000000000000000000000000000..e1578072ceab6f73d7934e8d1db6ec51a1721f40
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_316.php
@@ -0,0 +1,6 @@
+<?php
+try {
+  Zend_Db_Table_Abstract::getDefaultAdapter()
+    ->query('ALTER TABLE codif_section MODIFY id_section int(11) NOT NULL AUTO_INCREMENT');
+} catch(Exception $e) {}
+?>
diff --git a/library/Class/CommSigb.php b/library/Class/CommSigb.php
index 0f643046b11d67837ac48c00db53c4e1e11421e0..d9a0568d7b1ed37a5bba805d9ff236e268a33e0d 100644
--- a/library/Class/CommSigb.php
+++ b/library/Class/CommSigb.php
@@ -20,7 +20,9 @@
  */
 class Class_CommSigb {
   use Trait_Translator;
-  protected static $_instance;
+
+  protected static $_instance = null;
+
 
   public static function getInstance() {
     if (null != self::$_instance)
@@ -28,10 +30,12 @@ class Class_CommSigb {
     return new self();
   }
 
+
   public static function setInstance($instance) {
-    self::$_instance = $instance;
+    return self::$_instance = $instance;
   }
 
+
   /**
    * @param array $exemplaires_to_check
    * @return array
@@ -95,7 +99,7 @@ class Class_CommSigb {
       try {
         return ['fiche' =>  $cache->loadFromCacheOrSIGB($user, $sigb)];
       } catch (Exception $e) {
-        return ['erreur' =>  $e->getMessage()];
+        return $this->_error($e->getMessage());
       }
     };
 
@@ -111,14 +115,13 @@ class Class_CommSigb {
    */
   public function reserverExemplaire($id_bib, $exemplaire_id, $code_annexe) {
     if (!$user = Class_Users::getIdentity())
-      return ['statut' => 2,
-              'erreur' => $this->_('Vous devez vous connecter pour réserver un document.')];
+      return $this->_error($this->_('Vous devez vous connecter pour réserver un document.'));
 
     if (!$user->getIdabon())
-      return ['statut' => 2,
-              "erreur" => $this->_('Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation.')];
+      return $this->_error($this->_('Vous devez vous connecter sous votre numéro de carte pour effectuer une réservation.'));
 
-    $exemplaire = Class_Exemplaire::find($exemplaire_id);
+    if(!$exemplaire = Class_Exemplaire::find($exemplaire_id))
+      return $this->_error($this->_('Document introuvable'));
 
     $reserver = function ($user, $sigb) use ($exemplaire, $code_annexe) {
       return $sigb->reserverExemplaire($user, $exemplaire, $code_annexe);
@@ -217,10 +220,10 @@ class Class_CommSigb {
 
   public function SIGBConnect($user) {
     if (null == $sigb = $user->getSIGBComm())
-      return ['erreur' => $this->_('Communication SIGB indisponible')];
+      return $this->_error($this->_('Communication SIGB indisponible'));
 
     if (!$sigb->isConnected())
-      return ['erreur' => $this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.")];
+      return $this->_error($this->_("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque."));
 
     return $sigb;
   }
@@ -233,4 +236,9 @@ class Class_CommSigb {
     $sigb = $this->SIGBConnect($user);
     return (is_array($sigb)) ? $sigb : $closure($user, $sigb);
   }
+
+
+  protected function _error($message) {
+    return ['erreur' => $message];
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php
index b30f5d4b161a78e654adcd7aeac6192046e1368f..1d38354efad366961fa2aaa0176d888838cb60d7 100644
--- a/library/Class/Exemplaire.php
+++ b/library/Class/Exemplaire.php
@@ -19,12 +19,41 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
+class Class_ExemplaireLoader extends Storm_Model_Loader {
+  public function findFirstBySIGBOperation($user, $operation) {
+    if(!$user || !$operation)
+      return null;
+
+    $params = $operation->getCodeBarre()
+      ? ['code_barres' => $operation->getCodeBarre()]
+      : ['id_origine' => $operation->getNoNotice()];
+
+    if (!array_filter($params))
+      return null;
+
+    if(!($int_bibs = Class_IntBib::findAllAvailableForUser($user)) || $int_bibs->isEmpty())
+      return null;
+
+    $params['id_int_bib'] = $int_bibs->collect('id')->getArrayCopy();
+
+    if (!array_filter($params))
+      return null;
+
+    return Class_Exemplaire::findFirstBy($params);
+  }
+}
+
+
+
+
 class Class_Exemplaire extends Storm_Model_Abstract {
   use Trait_Translator, Trait_TimeSource;
 
-  protected $_table_name = 'exemplaires';
-  protected $_table_primary = 'id';
-  protected $_group_count = 0;
+  protected
+    $_table_name = 'exemplaires',
+    $_table_primary = 'id',
+    $_loader_class = 'Class_ExemplaireLoader',
+    $_group_count = 0;
 
   protected $_belongs_to = [
     'notice' => ['model' => 'Class_Notice',
@@ -52,7 +81,8 @@ class Class_Exemplaire extends Storm_Model_Abstract {
                                           'id_bib' => 0,
                                           'activite' => null,
                                           'date_nouveaute' => '',
-                                          'to_delete' => false];
+                                          'to_delete' => false,
+                                          'id_int_bib' => 0];
 
   protected $_sigb_exemplaire;
 
@@ -345,5 +375,13 @@ class Class_Exemplaire extends Storm_Model_Abstract {
     $raw['zone995'] = unserialize($raw['zone995']);
     return $raw;
   }
+
+
+  public function getSIGBComm() {
+    if(!$this->hasIdIntBib())
+      return null;
+
+    return $this->getIntBib()->getSIGBComm();
+  }
 }
 ?>
\ No newline at end of file
diff --git a/library/Class/IntBib.php b/library/Class/IntBib.php
index 0550501dd941ac950d36fe325d62682f49979f83..c8891cfb7eb9806749420ba9fae0055c6b26633d 100644
--- a/library/Class/IntBib.php
+++ b/library/Class/IntBib.php
@@ -30,6 +30,13 @@ class IntBibLoader extends Storm_Model_Loader {
       ? $bib
       : new Class_IntBib();
   }
+
+
+  public function findAllAvailableForUser($user) {
+    if($user_int_bib = $user->getIntBib())
+      return $user_int_bib->findAllWithSameCommunication();
+    return new Storm_Collection();
+  }
 }
 
 
@@ -57,6 +64,9 @@ class Class_IntBib extends Storm_Model_Abstract {
   const SIGB_PERGAME = 1;
   const SIGB_NANOOK = 13;
 
+  const TYPE = 'type';
+  const URL_SERVER = 'url_server';
+
   protected static $COM_CLASSES = [self::COM_PERGAME => 'Class_WebService_SIGB_Pergame',
                                    self::COM_OPSYS => 'Class_WebService_SIGB_Opsys',
                                    self::COM_VSMART => 'Class_WebService_SIGB_VSmart',
@@ -107,6 +117,18 @@ class Class_IntBib extends Storm_Model_Abstract {
   }
 
 
+  public function findAllWithSameCommunication() {
+    return (new Storm_Model_Collection($this->getLoader()->findAll()))
+      ->select([$this, 'hasSameCommunicationAs']);
+  }
+
+
+  public function hasSameCommunicationAs($other_int_bib) {
+    return ($this->getUrlServer() == $other_int_bib->getUrlServer())
+      && ($this->getCommSigb() == $other_int_bib->getCommSigb());
+  }
+
+
   public function getLabel() {
     if ($bib = $this->getBib())
       return $bib->getLibelle();
@@ -138,7 +160,13 @@ class Class_IntBib extends Storm_Model_Abstract {
   public function getModeComm() {
     return array_merge($this->getCommParamsAsArray(),
                        ['id_bib' => $this->getId(),
-                        'type' => $this->getCommSigb()]);
+                        static::TYPE => $this->getCommSigb()]);
+  }
+
+
+  public function getCommSettings() {
+    return array_filter(array_merge($this->getModeComm(),
+                                    [static::URL_SERVER => $this->getUrlServer()]));
   }
 
 
@@ -150,6 +178,13 @@ class Class_IntBib extends Storm_Model_Abstract {
   }
 
 
+  public function getUrlServer() {
+    if(!$sigb_comm = $this->getSIGBComm())
+      return '';
+    return $sigb_comm->getServerRoot();
+  }
+
+
   public function isPreRegistrationKohaEnabled() {
     if(!$this->getSIGBComm() == Class_IntBib::COM_KOHA)
       return false;
diff --git a/library/Class/NoticeUnimarc.php b/library/Class/NoticeUnimarc.php
index 1dca7c4aea4b9cd1fc31140be390ef11f8381884..bec73dccbd3151994263037bab6a7c034462daf7 100644
--- a/library/Class/NoticeUnimarc.php
+++ b/library/Class/NoticeUnimarc.php
@@ -208,7 +208,7 @@ class Class_NoticeUnimarc {
     $this->full_record = '';
     $this->guide = '';
     $this->directory = '';
-    $this->errors = '';
+    $this->errors = [];
     $this->inner_guide = '';
     $this->inner_directory = [];
     $this->inner_data = [];
diff --git a/library/Class/SuggestionAchat.php b/library/Class/SuggestionAchat.php
index 40f0033bacab9d2cb7643aa479bd6abb75cfdf3f..620d358d73d8cd22a1ef7e079ab77903a9e2b5b8 100644
--- a/library/Class/SuggestionAchat.php
+++ b/library/Class/SuggestionAchat.php
@@ -31,7 +31,9 @@ class Class_SuggestionAchat extends Storm_Model_Abstract {
   protected $_default_attribute_values = ['date_creation' => '',
                                           'titre' => '',
                                           'auteur' => '',
-                                          'bib_id' => ''];
+                                          'bib_id' => '',
+                                          'commentaire' => '',
+                                          'description_url' => ''];
 
   public function setIsbn($isbn) {
     return parent::_set('isbn', preg_replace('/[\s\.\-\_]/', '', (string)$isbn));
diff --git a/library/Class/WebService/ICalendar.php b/library/Class/WebService/ICalendar.php
index f70b0e6417482ddfe6d08552f62e0b16a502561e..e9a3df47864653479b0513d4f37e88f5f7a4bbba 100644
--- a/library/Class/WebService/ICalendar.php
+++ b/library/Class/WebService/ICalendar.php
@@ -26,6 +26,7 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
   protected
     $_events,
     $_current_event,
+    $_current_url,
     $_external_agenda;
 
   public function import($external_agenda) {
@@ -33,8 +34,12 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
     $this->_events = new Storm_Model_Collection();
     $this->_current_event = null;
 
-    array_map([$this, '_importLine'],
-              explode("\r\n", $this->httpGet($external_agenda->getUrl())));
+
+    $ics_content = $this->httpGet($external_agenda->getUrl());
+    $ics_content = preg_replace('|\n\s|', '', $ics_content); //see RFC2445
+    $lines = preg_split('|\r?\n|', $ics_content);
+
+    array_map([$this, '_importLine'], $lines);
 
     return $this->_events;
   }
@@ -44,8 +49,13 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
 
 
   protected function _importLine($line) {
+    if (!$line)
+      return $this;
+
     list($key, $value) = explode(':', $line, 2);
     $this->_importData($key, $value);
+
+    return $this;
   }
 
 
diff --git a/library/Class/WebService/MappedSoapClient.php b/library/Class/WebService/MappedSoapClient.php
index 51a22c57d9cd3b7a4afb581c94ad5286f1da435d..cd222356556610c6bb81d77d195080e45115a652 100644
--- a/library/Class/WebService/MappedSoapClient.php
+++ b/library/Class/WebService/MappedSoapClient.php
@@ -110,6 +110,11 @@ class Class_WebService_MappedSoapClient extends SoapClient {
   }
 
 
+  public function getServer() {
+    return $this->_soap_server;
+  }
+
+
   public function __doRequest($request, $location, $action, $version, $one_way = null) {
     try {
       if (!$this->_soap_server) {
diff --git a/library/Class/WebService/SIGB/AbstractService.php b/library/Class/WebService/SIGB/AbstractService.php
index efc2e6942755851feadaefacecfe66f392da6117..2a13bfb54135923f70bcee5701316260ac694f8a 100644
--- a/library/Class/WebService/SIGB/AbstractService.php
+++ b/library/Class/WebService/SIGB/AbstractService.php
@@ -68,24 +68,6 @@ abstract class Class_WebService_SIGB_AbstractService {
     return [];
   }
 
-  abstract public function getServerRoot();
-
-  abstract public function getEmprunteur($user);
-
-  abstract public function getUserAnnexe($user);
-
-
-  abstract public function reserverExemplaire($user, $exemplaire, $code_annexe);
-
-
-  abstract public function supprimerReservation($user, $reservation_id);
-
-
-  abstract public function prolongerPret($user, $pret_id);
-
-
-  abstract public function getNotice($id);
-
 
   public function getPopupUrlForUserInformations($user) {
     return null;
@@ -210,4 +192,19 @@ abstract class Class_WebService_SIGB_AbstractService {
   public function getConsultationRequests() {
     return [];
   }
+
+
+  abstract public function getServerRoot();
+
+  abstract public function getEmprunteur($user);
+
+  abstract public function getUserAnnexe($user);
+
+  abstract public function reserverExemplaire($user, $exemplaire, $code_annexe);
+
+  abstract public function supprimerReservation($user, $reservation_id);
+
+  abstract public function prolongerPret($user, $pret_id);
+
+  abstract public function getNotice($id);
 }
\ No newline at end of file
diff --git a/library/Class/WebService/SIGB/CdScript/Service.php b/library/Class/WebService/SIGB/CdScript/Service.php
index 93c67bad028ccde977ca7b5bfedbc450b2c803b8..3ca3264771c19505ccc4eb1b211816c8e029d24c 100644
--- a/library/Class/WebService/SIGB/CdScript/Service.php
+++ b/library/Class/WebService/SIGB/CdScript/Service.php
@@ -35,17 +35,17 @@ class Class_Webservice_SIGB_CdScript_Service extends Class_WebService_SIGB_Abstr
   }
 
 
-  public function getServerRoot() {
-    return $this->_server_url;
-  }
-
-
   protected function setServerUrl($url) {
     $this->_server_url = $url;
     return $this;
   }
 
 
+  public function getServerRoot() {
+    return $this->_server_url;
+  }
+
+
   protected function setRemoteLibraryId($remote_library_id) {
     $this->_remote_library_id = $remote_library_id;
     return $this;
diff --git a/library/Class/WebService/SIGB/Emprunteur.php b/library/Class/WebService/SIGB/Emprunteur.php
index c03f18511b3c522ebe2f2f6e6a407bc1ff9e4777..f47b55e7e1470f04013879c8bbcdc4c7601c5391 100644
--- a/library/Class/WebService/SIGB/Emprunteur.php
+++ b/library/Class/WebService/SIGB/Emprunteur.php
@@ -23,9 +23,9 @@ class Class_WebService_SIGB_Emprunteur {
   protected
     $_id,
     $_name,
-    $_emprunts,
-    $_reservations,
-    $_waiting_holds,
+    $_emprunts = [],
+    $_reservations = [],
+    $_waiting_holds = [],
     $_email = '',
     $_nom = null,
     $_prenom = null,
@@ -98,10 +98,8 @@ class Class_WebService_SIGB_Emprunteur {
    * @param string $name
    */
   function __construct($id, $name){
-    $this->_id=$id;
-    $this->_name=$name;
-    $this->_emprunts=null;
-    $this->_reservations=null;
+    $this->_id = $id;
+    $this->_name = $name;
   }
 
   /**
@@ -292,12 +290,10 @@ class Class_WebService_SIGB_Emprunteur {
    * @return Class_WebService_SIGB_Emprunteur
    */
   public function empruntsAddAll($emprunts){
-    if (null === $this->_emprunts)
-      $this->_emprunts = [];
-
     $this->_emprunts = array_merge($this->_emprunts, $emprunts);
     $this->_nb_emprunts = null;
     $this->_nb_retards = null;
+
     $this->sortByDateRetour($this->_emprunts);
     return $this;
   }
@@ -315,16 +311,13 @@ class Class_WebService_SIGB_Emprunteur {
    * @return Class_WebService_SIGB_Emprunteur
    */
   public function reservationsAddAll($reservations){
-    if (null === $this->_reservations)
-      $this->_reservations = array();
-
     $this->_reservations = array_merge($this->_reservations, $reservations);
     $this->_nb_reservations = count($this->_reservations);
     return $this;
   }
 
   /**
-   * @param Class_WebService_SIGB_Reservation $reservation
+   * @param Class_WebService_SIGB_eservation $reservation
    */
   public function reservationsAdd($reservation) {
     $this->reservationsAddAll(array($reservation));
@@ -334,24 +327,25 @@ class Class_WebService_SIGB_Emprunteur {
    * @return array
    */
   public function getReservations() {
-    if (null !== $this->_reservations)
+    if (!empty($this->_reservations))
       return $this->_reservations;
 
     if (!isset($this->_service))
       return [];
+
     $this->reservationsAddAll($this->_service->getReservationsOf($this));
     return $this->_reservations;
   }
 
 
   public function getHoldsWaitingToBePulled() {
-    if (null === $this->_waiting_holds) {
-      $this->_waiting_holds = [];
-      foreach ($this->getReservations() as $hold) {
-        if ($hold->isWaitingToBePulled())
-          $this->_waiting_holds[] = $hold;
-      }
-    }
+    if(!empty($this->_waiting_holds))
+      return $this->_waiting_holds;
+
+    foreach ($this->getReservations() as $hold)
+      if ($hold->isWaitingToBePulled())
+        $this->_waiting_holds[] = $hold;
+
     return $this->_waiting_holds;
   }
 
@@ -433,8 +427,8 @@ class Class_WebService_SIGB_Emprunteur {
   }
 
 
-  public function getEmprunts(){
-    if (null !== $this->_emprunts)
+  public function getEmprunts() {
+    if (!empty($this->_emprunts))
       return $this->_emprunts;
 
     if (!isset($this->_service))
@@ -458,15 +452,19 @@ class Class_WebService_SIGB_Emprunteur {
       : [];
   }
 
+
   /**
    * @param int $index
    * @return Class_WebService_SIGB_Emprunt
    */
   public function getEmpruntAt($index){
     $emprunts = $this->getEmprunts();
-    return $emprunts[$index];
+    return isset($emprunts[$index])
+      ? $emprunts[$index]
+      : new Class_Entity();
   }
 
+
   /**
    * @return int
    */
@@ -476,6 +474,7 @@ class Class_WebService_SIGB_Emprunteur {
     return $this->_nb_emprunts;
   }
 
+
   /**
    * @param int $nb_emprunts
    * @return Class_WebService_SIGB_Emprunteur
diff --git a/library/Class/WebService/SIGB/Exemplaire.php b/library/Class/WebService/SIGB/Exemplaire.php
index 9aa49a711de3581d22f2e6be77a80337ae9174cb..f93a7ed0271bdd7f608af1578cb6f69c45077f0c 100644
--- a/library/Class/WebService/SIGB/Exemplaire.php
+++ b/library/Class/WebService/SIGB/Exemplaire.php
@@ -98,22 +98,12 @@ class Class_WebService_SIGB_Exemplaire {
    * @return Class_Exemplaire
    */
   public function getExemplaireOPAC() {
-    if (isset($this->_exemplaire_opac))
+    if($this->_exemplaire_opac)
       return $this->_exemplaire_opac;
 
-    if ($no_notice = $this->getNoNotice())
-      $params = ['id_origine' => $no_notice];
-
-    if ($this->code_barre)
-      $params = ['code_barres' => $this->code_barre];
-
-    if (!isset($params))
-      return null;
-
-    if(1 < count(Class_Exemplaire::findAllBy($params)))
-      $params = array_merge(['id_int_bib not' => [$no_notice, 0]] , $params);
-
-    return $this->_exemplaire_opac = Class_Exemplaire::findFirstBy($params);
+    $operation = (new Class_Entity())->updateAttributes(['CodeBarre' => $this->code_barre,
+                                                         'NoNotice' => $this->no_notice]);
+    return $this->_exemplaire_opac = Class_Exemplaire::findFirstBySIGBOperation(Class_Users::getIdentity(), $operation);
   }
 
 
@@ -141,17 +131,18 @@ class Class_WebService_SIGB_Exemplaire {
    * @return Class_Notice
    */
   public function getNoticeOPAC() {
-    if (!isset($this->_notice_opac) and ($exemplaire_opac = $this->getExemplaireOPAC())) {
+    if (!isset($this->_notice_opac) &&
+        ($exemplaire_opac = $this->getExemplaireOPAC()))
       $this->_notice_opac = $exemplaire_opac->getNotice();
-    }
+
     return $this->_notice_opac;
   }
 
 
   public function getTitre() {
-    return ($record = $this->getNoticeOPAC())
-      && ($record_title = $record->getTitrePrincipal())
-      ? $record_title : $this->titre;
+    return $this->getNoticeOPAC()
+      ? $this->_notice_opac->getTitrePrincipal()
+      : $this->titre;
   }
 
 
@@ -187,10 +178,9 @@ class Class_WebService_SIGB_Exemplaire {
 
 
   public function getAuteur(){
-    if (!$this->auteur  and ($notice = $this->getNoticeOPAC()))
-      $this->auteur = $notice->getAuteurPrincipal();
-
-    return $this->auteur;
+    return $this->getNoticeOPAC()
+      ? $this->_notice_opac->getAuteurPrincipal()
+      : $this->auteur;
   }
 
 
diff --git a/library/Class/WebService/SIGB/ExemplaireOperation.php b/library/Class/WebService/SIGB/ExemplaireOperation.php
index 82bedea21782184008096baf432badbef3ad8519..71bcdd4aefbc6a832115b01a86f9601b7dc2878a 100644
--- a/library/Class/WebService/SIGB/ExemplaireOperation.php
+++ b/library/Class/WebService/SIGB/ExemplaireOperation.php
@@ -158,7 +158,7 @@ abstract class Class_WebService_SIGB_ExemplaireOperation {
    * @return string
    */
   public function getNoticeOPACId() {
-    if ($notice = $this->getNoticeOpac())
+    if ($notice = $this->getNoticeOPAC())
       return $notice->getId();
     return 0;
   }
diff --git a/library/Class/WebService/SIGB/Koha/PatronInfoReader.php b/library/Class/WebService/SIGB/Koha/PatronInfoReader.php
index 9df2c6d40cf3e9edd96a564915309b3f3bf1dffb..a85b69b5fab211f6be9a5385e59ac4afbb12dab5 100644
--- a/library/Class/WebService/SIGB/Koha/PatronInfoReader.php
+++ b/library/Class/WebService/SIGB/Koha/PatronInfoReader.php
@@ -68,7 +68,8 @@ class Class_WebService_SIGB_Koha_PatronInfoReader extends Class_WebService_SIGB_
 
 
   public function endHoldingbranch($data) {
-    if ($this->_currentLoan)  $this->updateBibliothequeWith($data);
+    if ($this->_currentLoan)
+      $this->updateBibliothequeWith($data);
   }
 
 
diff --git a/library/Class/WebService/SIGB/Opsys/Service.php b/library/Class/WebService/SIGB/Opsys/Service.php
index 1f93daaf5380c3d54032c45453351b9be9992052..b75459b1ed7e2ae71ffdf046c908bae6069c9b49 100644
--- a/library/Class/WebService/SIGB/Opsys/Service.php
+++ b/library/Class/WebService/SIGB/Opsys/Service.php
@@ -139,11 +139,6 @@ class Class_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_Abstract
   }
 
 
-  public function getServerRoot() {
-    return $this->search_client->getWsdlUrl();
-  }
-
-
   public function getCatalogClient() {
     return $this->catalog_client;
   }
@@ -342,6 +337,11 @@ class Class_WebService_SIGB_Opsys_Service extends Class_WebService_SIGB_Abstract
   }
 
 
+  public function getServerRoot() {
+    return $this->search_client->getWsdlUrl();
+  }
+
+
   public function getGUID(){
     return $this->guid;
   }
diff --git a/library/ZendAfi/Controller/Action/Helper/View.php b/library/ZendAfi/Controller/Action/Helper/View.php
index ac9eba74434a8e05f7696863cc85e0876a04c731..bdeb124e8cbad00001b201a04d42337a7effcef0 100644
--- a/library/ZendAfi/Controller/Action/Helper/View.php
+++ b/library/ZendAfi/Controller/Action/Helper/View.php
@@ -76,7 +76,7 @@ class ZendAfi_Controller_Action_Helper_View extends Zend_View {
 
     if (file_exists($template)) {
       $html = file_get_contents($template);
-      $blocs = '';
+      $blocs = [];
       // Interpretation des IF-xxx
       $pos_fin = 0;
       while (true) {
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Section.php b/library/ZendAfi/Controller/Plugin/Manager/Section.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c9a966e14385bfe776e08ffdd3bfb08877b83dd
--- /dev/null
+++ b/library/ZendAfi/Controller/Plugin/Manager/Section.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_Controller_Plugin_Manager_Section extends ZendAfi_Controller_Plugin_Manager_Manager {
+  public function getActions($model) {
+    return [['url' => ['action' => 'edit',
+                       'id' => $model->getId()],
+             'icon' => 'edit',
+             'label' => $this->_('Modifier')],
+
+            ['url' => ['action' => 'delete',
+                       'id' => $model->getId()],
+             'icon' => 'delete',
+             'label' => $this->_('Supprimer')]];
+  }
+
+
+  protected function _redirectToIndex() {
+    $this->_redirect('/cosmo/' . $this->_request->getControllerName().'/index');
+  }
+
+
+  protected function _redirectToEdit($model) {
+    $this->_redirect('/cosmo/' . $this->_request->getControllerName().'/edit/id/' . $model->getId());
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9000b9070dd46d67a4c1a7b4b0fa277eed0c72c
--- /dev/null
+++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Section.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_Controller_Plugin_ResourceDefinition_Section extends ZendAfi_Controller_Plugin_ResourceDefinition_Abstract {
+
+  public function getDefinitions() {
+    return ['model' => ['class' => 'Class_CodifSection',
+                        'name' => 'section',
+                        'order' => 'libelle',
+                        'model_id' => 'id_section'],
+
+            'messages' => ['successful_save' => $this->_('La section "%s" a été modifée'),
+                           'successful_add' => $this->_('La section "%s" a été ajoutée'),
+                           'successful_delete' => $this->_('La section "%s" a été suppriméee')],
+
+            'form_class_name' => 'ZendAfi_Form_Admin_Section'];
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/Form/Admin/Section.php b/library/ZendAfi/Form/Admin/Section.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ba993e32b6f16acef79cf48b40f0f8f56dbb935
--- /dev/null
+++ b/library/ZendAfi/Form/Admin/Section.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_Form_Admin_Section extends ZendAfi_Form {
+  public function init() {
+    parent::init();
+
+    $this
+      ->addElement('text',
+                   'libelle',
+                   ['label' => $this->_('Libellé'),
+                    'required' => true,
+                    'allowEmpty' => false])
+      ->addElement('textarea',
+                   'regles',
+                   ['label' => $this->_('Règles de reconnaissance : Syntaxe : [zone$champ][signe][valeur1;valeur2;etc...] - Ex : 995$a = a . Signes : "=" égal - "/" commence par - "*" contient'),
+                    'required' => true,
+                    'allowEmpty' => false])
+      ->addElement('checkbox',
+                   'invisible',
+                   ['label' => $this->_('Rejeter les exemplaires')])
+      ->addUniqDisplayGroup('section',
+                            ['legend' => $this->_('Formulaire de section')]);
+  }
+
+
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/Validate/Isbn.php b/library/ZendAfi/Validate/Isbn.php
index 2a4a504878ac0b456ac798a4eba64af41a0d4faf..69a811c044d3fda762209ac5e5e3364be88fc554 100644
--- a/library/ZendAfi/Validate/Isbn.php
+++ b/library/ZendAfi/Validate/Isbn.php
@@ -28,7 +28,6 @@ class ZendAfi_Validate_Isbn extends Zend_Validate_Abstract {
       return true;
 
     $this->_setValue($valueString);
-
     if ($this->isISBN10Valid($valueString) || $this->isISBN13Valid($valueString))
       return true;
 
@@ -39,6 +38,9 @@ class ZendAfi_Validate_Isbn extends Zend_Validate_Abstract {
 
   /** cf http://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-13_check_digit_calculation */
   public function isISBN13Valid($n) {
+    if (strlen($n) != 13 || !is_numeric($n))
+      return false;
+
     $check = 0;
     for ($i = 0; $i < 13; $i+=2) $check += substr($n, $i, 1);
     for ($i = 1; $i < 12; $i+=2) $check += 3 * substr($n, $i, 1);
diff --git a/library/ZendAfi/View/Helper/Abonne/Loans.php b/library/ZendAfi/View/Helper/Abonne/Loans.php
index 0707f65b069f60a20ea59b85f1a3ccabb5bea93a..2e5b0d6ae5d96fe79bc76413f2d46f0fdf32802c 100644
--- a/library/ZendAfi/View/Helper/Abonne/Loans.php
+++ b/library/ZendAfi/View/Helper/Abonne/Loans.php
@@ -76,26 +76,27 @@ class ZendAfi_View_Helper_Abonne_Loans extends ZendAfi_View_Helper_BaseHelper {
 
 
   protected function renderLoan($loan) {
-    $record_title = $loan->getTitre();
-
-    if ($record = $loan->getNoticeOPAC())
-      $record_title = $this->view->tagAnchor($this->view->url(
-                                                              ['controller' => 'recherche',
-                                                               'action' => 'viewnotice',
-                                                               'id' => $record->getId(),
-                                                               'retour_abonne' => 'prets'],
-                                                              null, true),
-                                             $loan->getTitre());
+    $record = new Class_Entity();
+    if($item = $loan->getExemplaireOPAC())
+      $record = $item->getNotice();
+
+    $record_title = ($record->getId())
+      ? $this->view->recordAnchor($record, ['retour_abonne' => 'prets'])
+      : $loan->getTitre();
+
     return
       $this->_tag('tr',
                   $this->_tag('td',
                               $loan->getUserFullName())
                   . $this->_tag('td',
-                                $record ? $record->getTypeDocLabel() : '')
+                                $record->getTypeDocLabel())
                   . $this->_tag('td',
                                 $record_title)
                   . $this->_tag('td',
-                                $loan->getAuteur())
+                                $this->view->authorAnchor($loan->getAuteur()
+                                                          ? $loan->getAuteur()
+                                                          : $record->getAuteurPrincipal(),
+                                                          ['retour_abonne' => 'prets']))
                   . $this->_tag('td',
                                 $this->_in_progress ? $loan->getBibliotheque() : $loan->getIssueDate())
                   . $this->_tag('td',
diff --git a/library/ZendAfi/View/Helper/Abonne/LoansExtension.php b/library/ZendAfi/View/Helper/Abonne/LoansExtension.php
index c02f2f0d44ccaabe951d125515c5290a0042bf36..c3e304093e30ee43decf60760a88b9d919b886e5 100644
--- a/library/ZendAfi/View/Helper/Abonne/LoansExtension.php
+++ b/library/ZendAfi/View/Helper/Abonne/LoansExtension.php
@@ -71,8 +71,10 @@ class ZendAfi_View_Helper_Abonne_LoansExtension extends ZendAfi_View_Helper_Base
       return '';
 
     foreach ($this->_cards->getLoansWithOutPNB() as $loan) {
-      if ($loan->getId() == $result['id'])
-        return '<br>'. $this->_tag('strong', $loan->getTitre() . ':') . ' ' . $result['erreur'];
+      if ($loan->getId() != $result['id'])
+        continue;
+
+      return '<br>'. $this->_tag('strong', $loan->getTitre() . ':') . ' ' . $result['erreur'];
     }
 
     return '';
diff --git a/library/ZendAfi/View/Helper/Abonne/ReservationsTable.php b/library/ZendAfi/View/Helper/Abonne/ReservationsTable.php
index c80e1756fe30545fc958aedac1a2849fd65bc052..35a2771210b5805bd27098d2aa6f657fbf32198a 100644
--- a/library/ZendAfi/View/Helper/Abonne/ReservationsTable.php
+++ b/library/ZendAfi/View/Helper/Abonne/ReservationsTable.php
@@ -26,7 +26,8 @@ class ZendAfi_View_Helper_Abonne_ReservationsTable extends ZendAfi_View_Helper_B
   public function abonne_ReservationsTable($reservations, $fiche) {
     Class_ScriptLoader::getInstance()->loadTableSorter();
     return $this->_tag('table',
-                       $this->_renderHeader() . $this->_renderReservations($reservations, $fiche),
+                       $this->_renderHeader()
+                       . $this->_renderReservations($reservations, $fiche),
                        ['class' => 'tablesorter reservations']);
   }
 
@@ -57,7 +58,6 @@ class ZendAfi_View_Helper_Abonne_ReservationsTable extends ZendAfi_View_Helper_B
     $html = '';
     $html .= (isset($fiche['message']) && $fiche['message'] ? $this->_renderError($fiche['message']) : '');
     $html .= (isset($fiche['erreur']) && $fiche['erreur'] ? $this->_renderError($fiche['erreur']) : '');
-
     $this->_line_no = 1;
     foreach($reservations as $reservation)
       $html .= $this->_renderReservation($reservation);
@@ -67,16 +67,23 @@ class ZendAfi_View_Helper_Abonne_ReservationsTable extends ZendAfi_View_Helper_B
 
 
   protected function _renderReservation($reservation) {
-    $record = $reservation->getNoticeOPAC();
+    $record = new Class_Entity();
+    if($item = $reservation->getExemplaireOPAC())
+      $record = $item->getNotice();
+
+    $record_title = ($record->getId())
+      ? $this->view->recordAnchor($record, ['retour_abonne' => 'reservations'])
+      : $reservation->getTitre();
 
     return
       $this->_tag('tr',
                   $this->_tag('td', $reservation->getUserFullName())
-                  . $this->_tag('td', $record ? $record->getTypeDocLabel() : '')
+                  . $this->_tag('td', $record->getTypeDocLabel())
                   . $this->_tag('td',
-                                $this->_getRecordLink($reservation->getTitre(), $reservation->getNoticeOPACId()))
+                                $record_title)
                   . $this->_tag('td',
-                                strip_tags($reservation->getAuteur()))
+                                $this->view->authorAnchor($record->getAuteurPrincipal(),
+                                                          ['retour_abonne' => 'reservations']))
                   . $this->_tag('td',
                                 $reservation->getBibliotheque())
                   . $this->_tag('td',
@@ -88,19 +95,6 @@ class ZendAfi_View_Helper_Abonne_ReservationsTable extends ZendAfi_View_Helper_B
   }
 
 
-  protected function _getRecordLink($title, $record_id) {
-    if (!$record_id)
-      return $title;
-
-    return $this->view->tagAnchor($this->view->url(['controller' => 'recherche',
-                                                    'action' => 'viewnotice',
-                                                    'id' => $record_id,
-                                                    'retour_abonne' => 'reservations'],
-                                                   null, true),
-                                  $title);
-  }
-
-
   protected function _getCancelLink($reservation) {
     return $this->view->tagAnchor($this->view->url(['id_delete' => $reservation->getId()]),
                                   $this->view->tagImg(URL_IMG . 'bouton/cancel.gif',
@@ -158,15 +152,19 @@ class ZendAfi_View_Helper_Abonne_OnPlaceConsultationReservationsTable extends Ze
 
   protected function _renderReservation($reservation) {
     $record = $reservation->getRecord();
+    $record_title = ($record->getId())
+      ? $this->view->recordAnchor($record, ['retour_abonne' => 'reservations'])
+      : $reservation->getTitre();
+
     return
       $this->_tag('tr',
                   $this->_tag('td',
                               $this->_line_no++)
                   . $this->_tag('td',
-                                $this->_getRecordLink($reservation->getTitle(),
-                                                      $reservation->getRecordId()))
+                                $record_title)
                   . $this->_tag('td',
-                                strip_tags($record ? $record->getAuteurPrincipal() : ''))
+                                $this->view->authorAnchor($record->getAuteurPrincipal(),
+                                                          ['retour_abonne' => 'reservations']))
                   . $this->_tag('td',
                                 $reservation->getLocationLabel())
                   . $this->_tag('td',
diff --git a/library/ZendAfi/View/Helper/Accueil/Reservations.php b/library/ZendAfi/View/Helper/Accueil/Reservations.php
index d305a0dec486e64af12832aaaf103a581b93b8d1..1d6e02e0e986b68e9da94147f973ad33ac0e2fbb 100644
--- a/library/ZendAfi/View/Helper/Accueil/Reservations.php
+++ b/library/ZendAfi/View/Helper/Accueil/Reservations.php
@@ -31,9 +31,10 @@ class ZendAfi_View_Helper_Accueil_Reservations extends ZendAfi_View_Helper_Accue
   public function renderModelReservations($reservations) {
     $html = '';
     foreach ($reservations as $reservation) {
+      $record = Class_Notice::find($reservation->getNoticeOPACId());
       $html .= $this->renderElement($reservation->getTitre(),
                                     $reservation->getEtat(),
-                                    $reservation->getNoticeOPAC());
+                                    $record);
     }
     return $html;
   }
diff --git a/library/ZendAfi/View/Helper/AuthorAnchor.php b/library/ZendAfi/View/Helper/AuthorAnchor.php
new file mode 100644
index 0000000000000000000000000000000000000000..e2872b1eb8e7b7048f90eba0a9481d7ac02f9032
--- /dev/null
+++ b/library/ZendAfi/View/Helper/AuthorAnchor.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_View_Helper_AuthorAnchor extends ZendAfi_View_Helper_BaseHelper {
+
+  public function authorAnchor($author, $params = []) {
+    if(!$author)
+      return '';
+
+    if(!$facet = Class_CodifAuteur::findFirstBy(['libelle' => $author]))
+      return $author;
+
+    $params = array_merge(['controller' => 'recherche',
+                           'action' => 'simple',
+                           'facette' => Class_CodifAuteur::CODE_FACETTE . $facet->getId()],
+                          $params);
+      return
+      $this->view->tagAnchor($this->view->url($params, null, true), $author);
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/RecordAnchor.php b/library/ZendAfi/View/Helper/RecordAnchor.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a32218fbbf57aa82fe9d7935a91815e7583ea22
--- /dev/null
+++ b/library/ZendAfi/View/Helper/RecordAnchor.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH 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).
+ *
+ * BOKEH 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 BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_View_Helper_RecordAnchor extends ZendAfi_View_Helper_BaseHelper {
+
+  public function recordAnchor($record, $params = []) {
+    if(!$record)
+      return '';
+
+    return $this->view->tagAnchor($this->view->urlNotice($record, $params),
+                                  $record->getTitrePrincipal());
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/RenderLibrary.php b/library/ZendAfi/View/Helper/RenderLibrary.php
index dc071c2be61802f786b5a466f5bf913eb8c51549..570a6339caed9503f72bb04dbef126f772144d21 100644
--- a/library/ZendAfi/View/Helper/RenderLibrary.php
+++ b/library/ZendAfi/View/Helper/RenderLibrary.php
@@ -122,10 +122,11 @@ class ZendAfi_View_Helper_RenderLibrary extends ZendAfi_View_Helper_BaseHelper {
 
 
   protected function renderOpeningHours() {
-    if (!strlen($this->library->getHoraire()))
-      return '';
+    $openings = $this->library->getHoraire()
+      ? $this->library->getHoraire()
+      : $this->view->libraryOpenings($this->library);
 
-    return $this->_renderField($this->_escapeInfo($this->library->getHoraire()),
+    return $this->_renderField($this->_escapeInfo($openings),
                                'field-opening-hours');
   }
 
diff --git a/library/ZendAfi/View/Helper/Telephone/Abonne/Operations.php b/library/ZendAfi/View/Helper/Telephone/Abonne/Operations.php
index efd0bfccfb9f977b9b123c3c17d7574c07fd9ea6..90f6b78cc4a5f4575d5529c093eee7215f2b0cf6 100644
--- a/library/ZendAfi/View/Helper/Telephone/Abonne/Operations.php
+++ b/library/ZendAfi/View/Helper/Telephone/Abonne/Operations.php
@@ -24,12 +24,10 @@ class ZendAfi_View_Helper_Telephone_Abonne_Operations extends ZendAfi_View_Helpe
   protected
     $_operations = [],
     $_title = '',
-    $_no_operation_text = ''
-    ;
+    $_no_operation_text = '';
 
   public function abonne_Operations($operations) {
     $this->_operations = $operations;
-
     return $this->_tag('ul',
                        $this->_renderTitle() . $this->_renderOperations(),
                        ['data-role' => 'listview',
diff --git a/library/ZendAfi/View/Helper/UrlNotice.php b/library/ZendAfi/View/Helper/UrlNotice.php
index 0e54f03d498f70e9ca79ac6a8d8d3bad1eec72c3..f2c55e24e776ec7ca53f5165cf42050d098bb373 100644
--- a/library/ZendAfi/View/Helper/UrlNotice.php
+++ b/library/ZendAfi/View/Helper/UrlNotice.php
@@ -36,6 +36,7 @@ class ZendAfi_View_Helper_UrlNotice extends Zend_View_Helper_HtmlElement {
     $options = array_merge($options,
                            array_intersect_key(array_filter($preferences),
                                                ['retour_panier' => '',
+                                                'retour_abonne' => '',
                                                 'id_panier' => 0,
                                                 'id_catalogue' => 0,
                                                 'module' => 'opac',
diff --git a/library/startup.php b/library/startup.php
index 95dff0d8d07708730cdc8980e6c3e16aed995570..fb1979a74d402cd340cb800a5e16feceb7ac3de9 100644
--- a/library/startup.php
+++ b/library/startup.php
@@ -83,7 +83,7 @@ class Bokeh_Engine {
 
   function setupConstants() {
     defineConstant('BOKEH_MAJOR_VERSION','7.7');
-    defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.28');
+    defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.29');
 
     defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/');
 
diff --git a/public/opac/js/recherche.js b/public/opac/js/recherche.js
index 72ba8f08e6fd41508a99d59be036a083c056dd74..664301d2e82a47b64302796f84f27fbc240ff7c5 100644
--- a/public/opac/js/recherche.js
+++ b/public/opac/js/recherche.js
@@ -365,57 +365,10 @@ function chercher_videos(sId,sAuteur,sTitre) {
 ////////////////////////////////////////////////////////////////////////////////////
 // Réservation de notice en ajax (pour comm sigb)
 ///////////////////////////////////////////////////////////////////////////////////
-function reservationAjax(oImg,nIdBib,sIdOrigine, sCodeAnnexe)
-{
-  var sUrl=baseUrl+'/recherche/reservationajax?id_bib='+nIdBib+"&id_origine="+sIdOrigine+"&code_annexe="+sCodeAnnexe;
-  var saveImg=$(oImg).attr('src');
-  $(oImg).attr('src',imagesUrl+'patience.gif');
-  $.getJSON(sUrl, function(data)	{
-    $(oImg).attr('src',saveImg);
-
-    if (data.indexOf('http') == 0)
-      showPopWin(data, 500, 345, 
-		 function(event, ui) {
-		   if (undefined == event.currentTarget)
-		     reservationAjax(oImg,nIdBib,sIdOrigine, sCodeAnnexe);
-		 });
-    else 
-      alert(data);
-  });
-}
 
 
 var pickupImgCallback;
 var pickupConfirmCallBack;
-function reservationPickupAjax(oImg,nIdBib,sIdOrigine,sCodeAnnexe)
-{
-  var sUrl = baseUrl+'/recherche/reservation-pickup-ajax?id_bib='+nIdBib+"&id_origine="+sIdOrigine+"&code_annexe="+sCodeAnnexe;
-  var saveImg = $(oImg).attr('src');
-  pickupImgLoadingCallback = function() {
-    $(oImg).attr('src', saveImg);
-  };
-  pickupConfirmCallBack = function(form) {
-    reservationPickupAjaxCancel();
-    var sCodeAnnexe = $(form).find('input:radio[name="code_annexe"]:checked').val();
-    reservationAjax(oImg, nIdBib, sIdOrigine, sCodeAnnexe);
-  };
-  
-  var img = $(oImg).attr('src');
-  $(oImg).attr('src',imagesUrl+'patience.gif');
-  showPopWin(sUrl, 500, 345, function(){$(oImg).attr('src',img);});
-}
-
-
-function reservationPickupAjaxCancel() {
-  pickupImgLoadingCallback();
-  hidePopWin(false);
-}
-
-
-function reservationPickupAjaxConfirm(form) {
-  pickupConfirmCallBack(form);
-}
-
 
 
 var scrollToSelectedNoticeInResult = function() {
diff --git a/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryTest.php b/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryTest.php
index d72146b1dcd502171d4e755db4ccb17ed5486355..f5481ce890b5e7f79df39ce3368f03e67fbe3997 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerLoansHistoryTest.php
@@ -32,11 +32,18 @@ abstract class AbonneControllerLoansHistoryTestCase extends AbstractControllerTe
 
   public function setUp() {
     parent::setUp();
+
+    $library = $this->fixture('Class_IntBib',
+                              ['id' => 1,
+                               'comm_sigb' => Class_IntBib::COM_KOHA,
+                               'comm_params' => ['url_serveur' => static::BASE_URL]]);
+
     $faustine = $this->fixture('Class_Users', ['id' => 12,
                                                'login' => 'faustine',
-                                               'password' => 'toto']);
-    $this->_emprunteur = new Class_WebService_SIGB_Emprunteur('34', 'faustine');
+                                               'password' => 'toto',
+                                               'int_bib' => $library]);
 
+    $this->_emprunteur = new Class_WebService_SIGB_Emprunteur('34', 'faustine');
 
     $faustine->setFicheSigb(['type_comm' => Class_IntBib::COM_KOHA,
                              'fiche' => $this->_emprunteur]);
@@ -48,11 +55,11 @@ abstract class AbonneControllerLoansHistoryTestCase extends AbstractControllerTe
 
     $params = ['url_serveur' => static::BASE_URL . 'ilsdi.pl',
                'restful' => '1'];
+
     $service = Class_WebService_SIGB_Koha::getService($params);
     $service->setWebClient($this->mock_web_client);
 
     $this->_emprunteur->setService($service);
-
   }
 }
 
@@ -79,14 +86,12 @@ class AbonneControllerLoansHistorySuccessfulTest extends  AbonneControllerLoansH
   public function setUp() {
     parent::setUp();
 
-    $pomme = $this->fixture('Class_Notice',
-                   ['id' => 1456,
-                    'clef_alpha' => 'POMME',
-                    'titre' => 'Tarte au pommes']);
-
-    $this->fixture('Class_Exemplaire', ['id' => 123,
-                                        'notice' => $pomme,
-                                        'code_barres' => '31301009564282']);
+    $this->fixture('Class_Exemplaire', ['id' => 123789,
+                                        'notice' => $this->fixture('Class_Notice',
+                                                                   ['id' => 1456])
+                                        ->setTitrePrincipal('Cedric :Chaud et froid Vol 6'),
+                                        'code_barres' => '31301009564282',
+                                        'id_int_bib' => 1]);
 
     $this->mock_web_client
       ->whenCalled('open_url')
@@ -103,6 +108,7 @@ class AbonneControllerLoansHistorySuccessfulTest extends  AbonneControllerLoansH
     $this->assertAction('loans-history');
   }
 
+
   /** @test */
   public function titleShouldBeDisplay() {
     $this->assertXPathContentContains('//table', 'Cedric :Chaud et froid Vol 6');
diff --git a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
index f882c3652651bf9a2709d5da36af3d1c14ead3b0..d960128be24d841ccd0ab7e51c89d612c280e9c8 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerPretsTest.php
@@ -20,6 +20,7 @@
  */
 
 require_once 'tests/fixtures/DilicomFixtures.php';
+require_once 'tests/fixtures/NanookFixtures.php';
 
 abstract class AbstractAbonneControllerPretsTestCase extends AbstractControllerTestCase {
   protected
@@ -39,13 +40,20 @@ abstract class AbstractAbonneControllerPretsTestCase extends AbstractControllerT
   public function setUp() {
     parent::setUp();
 
+    $webservice = 'http://mon_sigb_koha.org';
+
+    $library = $this->fixture('Class_IntBib',
+                              ['id' => 1,
+                               'comm_sigb' => Class_IntBib::COM_KOHA,
+                               'comm_params' => ['url_serveur' => $webservice]]);
+
     $this->florence = $this->fixture('Class_Users',
                                      ['id' => '123456',
                                       'login' => 'flo',
                                       'idabon' => 'x234',
                                       'password' => 'flo',
                                       'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
-                                      'id_site' => 1]);
+                                      'int_bib' => $library]);
 
     Storm_Cache::beVolatile();
     Storm_Cache::setSeed('local');
@@ -109,7 +117,22 @@ abstract class AbonneControllerPretsListThreePretsTestCase extends AbstractAbonn
   public function setUp() {
     parent::setUp();
     $potter = new Class_WebService_SIGB_Emprunt('12', new Class_WebService_SIGB_Exemplaire(123));
-    $potter->getExemplaire()->setTitre('Potter');
+    $potter
+      ->setCodeBarre(123)
+      ->getExemplaire()
+      ->setTitre('Potter')
+      ->setExemplaireOPAC($this->fixture('Class_Exemplaire',
+                                              ['id' => 967,
+                                               'code_barres' => 123,
+                                               'id_int_bib' => 1,
+                                               'id_origine' => 1234,
+                                               'zone995' => serialize([['clef' => 'a', 'valeur' => 'PotterItem']]),
+                                               'notice' => $this->fixture('Class_Notice',
+                                                                          ['id' => 889,
+                                                                           'titre_principal' => 'Potter',
+                                                                           'type_doc' => Class_TypeDoc::LIVRE,
+                                                                           'unimarc' => '00577nam0 2200181   450 001001500000010001800015100004100033101000800074200010700082210003000189215001100219461002000230606002900250676000800279700004500287801005600332940000700388frOr1314913787  a9781408812792  a20140320                  0103        aEng1 aHarry Potter and the deathly hallowsdHarry Potter et les reliques de la mortfJoanne Kathleen Rowling  aLondrescBloomsburyd2010  a831 p. 1tHarry Potterv7  aAnglais (langue)2Rameau  a420 1aRowlingbJoanne Kathleenf1965-....4070  aFRbBibliothèque de l\'agglomération de Saint-Omer  apm'])]));
+
     $potter->parseExtraAttributes(['Dateretourprevue' => '29/10/2022',
                                    'Section' => 'Espace jeunesse',
                                    'Auteur' => 'JK Rowling',
@@ -120,6 +143,8 @@ abstract class AbonneControllerPretsListThreePretsTestCase extends AbstractAbonn
     $this->fixture('Class_Exemplaire',
                    ['id' => 967,
                     'id_origine' => 1234,
+                    'code_barres' => 123,
+                    'id_int_bib' => 1,
                     'zone995' => serialize([['clef' => 'a', 'valeur' => 'PotterItem']]),
                     'notice' => $this->fixture('Class_Notice',
                                                ['id' => 889,
@@ -128,7 +153,21 @@ abstract class AbonneControllerPretsListThreePretsTestCase extends AbstractAbonn
                                                 'unimarc' => '00577nam0 2200181   450 001001500000010001800015100004100033101000800074200010700082210003000189215001100219461002000230606002900250676000800279700004500287801005600332940000700388frOr1314913787  a9781408812792  a20140320                  0103        aEng1 aHarry Potter and the deathly hallowsdHarry Potter et les reliques de la mortfJoanne Kathleen Rowling  aLondrescBloomsburyd2010  a831 p. 1tHarry Potterv7  aAnglais (langue)2Rameau  a420 1aRowlingbJoanne Kathleenf1965-....4070  aFRbBibliothèque de l\'agglomération de Saint-Omer  apm'])]);
 
     $alice = new Class_WebService_SIGB_Emprunt('13', new Class_WebService_SIGB_Exemplaire(456));
-    $alice->getExemplaire()->setTitre('Alice');
+    $alice
+      ->setCodeBarre(124)
+      ->getExemplaire()
+      ->setTitre('Alice')
+      ->setExemplaireOPAC($this->fixture('Class_Exemplaire',
+                                         ['id' => 918,
+                                          'id_origine' => 5678,
+                                          'code_barres' => 124,
+                                          'id_int_bib' => 1,
+                                          'zone995' => serialize([['clef' => 'a', 'valeur' => 'AliceItem']]),
+                                          'notice' => $this->fixture('Class_Notice',
+                                                                     ['id' => 827,
+                                                                      'titre_principal' => 'Alice',
+                                                                      'unimarc' => '01175cam0 22002771  450 001001500000010003700015100004100052101000800093102000700101105001800108106000600126200009300132210002400225211001300249215006400262300002400326307002900350330027300379345001800652461005600670700001800726701003000744801003300774856008300807940000700890frOr0354235228  a978-2-35592-635-8bbr.d7,65 EUR  a20140225d2014    |  |0fre|0103||||ba  afre  aFR  a        0||y|  ar1 aAlice au royaume de TrèfleeCheshire cat Waltzh5fQuinRosegdessin Mamenosuke Fujimaru  aPariscKi-oond2014 1a20140227  a1 vol. (164 p.)cillustrations en noir et blancd18 x 13 cm  aTraduit du japonais  aSens de lecture japonais  aPerdue dans la forêt aux portes, Alice tombe nez à nez avec Ace. Devenue malgré elle la confidente du chevalier, elle ne sait comment repousser ses avances. Lorsque le chat du Cheshire, qui a assisté à la scène, intervient, la rencontre tourne à l\'affrontement.  b9782355926358 1tAlice au royaume de Trèfle : Cheshire cat Waltzv5 1aQuinRose4070 1aFujimarubMamenosuke4440  aFRbElectrec20140225gAFNOR  uhttp://www.electre.com//GetBlob.ashx?Ean=9782355926358,0-1913692&Size=Original  aLR'])]));
+
     $alice->parseExtraAttributes(['Dateretourprevue' => '21/10/2010',
                                   'Section' => 'Espace jeunesse',
                                   'Auteur' => 'Lewis Caroll',
@@ -138,6 +177,8 @@ abstract class AbonneControllerPretsListThreePretsTestCase extends AbstractAbonn
     $this->fixture('Class_Exemplaire',
                    ['id' => 918,
                     'id_origine' => 5678,
+                    'code_barres' => 124,
+                    'id_int_bib' => 1,
                     'zone995' => serialize([['clef' => 'a', 'valeur' => 'AliceItem']]),
                     'notice' => $this->fixture('Class_Notice',
                                                ['id' => 827,
@@ -195,6 +236,7 @@ class AbonneControllerPretsExportThreePretsTest extends AbonneControllerPretsLis
 
   public function setUp() {
     parent::setUp();
+
     $this->dispatch('/opac/abonne/loan-export', true);
     $this->_dl_file = tempnam('/tmp', 'UNIMARC');
     file_put_contents($this->_dl_file, $this->_response->getBody());
@@ -235,6 +277,7 @@ class AbonneControllerPretsExportThreePretsTest extends AbonneControllerPretsLis
 
 
 
+
 class AbonneControllerPretsListThreePretsTest extends AbonneControllerPretsListThreePretsTestCase {
   public function setUp() {
     parent::setUp();
@@ -253,7 +296,7 @@ class AbonneControllerPretsListThreePretsTest extends AbonneControllerPretsListT
   /** @test */
   public function returnToMyHomeShouldBePresent() {
     $this->assertXPathContentContains('//a[contains(@href, "/abonne/fiche")]',
-    utf8_encode('Retour à mon compte'));
+                                      utf8_encode('Retour à mon compte'));
   }
 
 
@@ -312,8 +355,8 @@ class AbonneControllerPretsListThreePretsTest extends AbonneControllerPretsListT
 
 
   /** @test */
-  public function aliceAuthorShouldBeLewisCaroll() {
-    $this->assertXPathContentContains("//tbody/tr[1]//td", 'Lewis Caroll');
+  public function aliceAuthorShouldBeQuinRoseAndFetchFromDB() {
+    $this->assertXPathContentContains("//tbody/tr[1]//td", 'QuinRose');
   }
 
 
@@ -351,8 +394,8 @@ class AbonneControllerPretsListThreePretsTest extends AbonneControllerPretsListT
 
 
   /** @test */
-  public function potterAuthorShouldBeJKRolling() {
-    $this->assertXPathContentContains("//tbody/tr[2]//td", 'JK Rowling');
+  public function potterAuthorShouldBeJKRollingAndFetchFromDB() {
+    $this->assertXPathContentContains("//tbody/tr[2]//td", 'Joanne Kathleen Rowling');
   }
 
 
@@ -452,20 +495,29 @@ class AbonneControllerPretsListThreePretsPnbEarlyReturnTest extends AbonneContro
 
 
 class AbonneControllerPretsListReservationTest extends AbstractAbonneControllerPretsTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
-
-    Class_Exemplaire::beVolatile();
-
+    $exemplaire_potter = $this->fixture('Class_Exemplaire',
+                                        ['id' => 12089,
+                                         'code_barres' => 123,
+                                         'id_int_bib' => 1,
+                                         'id_notice' => 820]);
+    $this->fixture('Class_Notice',
+                   ['id' => 820,
+                    'titre_principal' => 'Potter']);
     $potter =
       (new Class_WebService_SIGB_Reservation('12',
-                                             (new Class_WebService_SIGB_Exemplaire(123))->setTitre('Potter')))
+                                             (new Class_WebService_SIGB_Exemplaire(123))
+                                             ->setTitre('Potter')
+                                             ->setExemplaireOPAC($exemplaire_potter)))
       ->parseExtraAttributes(['Etat' => 'Réservation émise',
                               'Rang' => '2',
                               'Bibliotheque' => 'Tombouctou',
                               'N° de notice' => 564]);
 
-    // This item has no library: non-regression test.
+    // This item has no library: non-regression test. @see http://forge.afi-sa.fr/issues/12864
     $dobby =
       (new Class_WebService_SIGB_Reservation('13',
                                              (new Class_WebService_SIGB_Exemplaire(124))->setTitre('Dobby')))
@@ -509,7 +561,7 @@ class AbonneControllerPretsListReservationTest extends AbstractAbonneControllerP
       ->setPseudo('FloFlo')
       ->setFicheSigb(['type_comm' => Class_IntBib::COM_OPSYS,
                       'fiche' => (new Class_WebService_SIGB_Emprunteur('1234', 'Florence'))
-                                  ->reservationsAddAll([$potter, $dobby]),
+                      ->reservationsAddAll([$potter, $dobby]),
                       'message' => '',
                       'erreur' => '']);
 
@@ -556,8 +608,7 @@ class AbonneControllerPretsListReservationTest extends AbstractAbonneControllerP
   /** @test */
   public function titreShouldBePotterAndLinkToNotice() {
     $this->assertXPathContentContains('//tbody/tr[1]//td//a[contains(@href, "recherche/viewnotice/id/820/retour_abonne/reservations")]',
-                                      'Potter',
-                                      $this->_response->getBody());
+                                      'Potter');
   }
 
 
@@ -586,17 +637,16 @@ class AbonneControllerPretsListReservationTest extends AbstractAbonneControllerP
 
   /** @test */
   public function bibliothequeShouldBeTombouctou() {
-    $this->assertXPathContentContains('//tbody/tr[1]//td', 'Tombouctou', $this->_response->getBody());
+    $this->assertXPathContentContains('//tbody/tr[1]//td', 'Tombouctou');
   }
 
 
-
   /** @test */
   public function secondReservationTitleShouldBeDobby() {
-    $this->assertXPathContentContains('//tbody/tr[2]//td//a', 'Dobby',
-                                      $this->_response->getBody());
+    $this->assertXPathContentContains('//tbody/tr[2]//td', 'Dobby');
   }
 
+
   /** @test */
   public function OnSiteConsultationTableSouldNotBeDisplay() {
     $this->assertNotXPathContentContains('//div[@class="boiteMilieu"]//h1', 'Réservations pour la consultation sur place');
@@ -772,7 +822,9 @@ class AbonneControllerPretsExtendAllLoansErrorThreePretsTest extends AbonneContr
     return $this->mock()
                 ->whenCalled('prolongerPret')
                 ->answers(['statut' => 0,
-                           'erreur' => utf8_encode('Prolongation impossible, votre abonnement est échu.')]);
+                           'erreur' => utf8_encode('Prolongation impossible, votre abonnement est échu.')])
+                ->whenCalled('getIntBib')
+                ->answers(null);
   }
 
 
@@ -802,7 +854,10 @@ class AbonneControllerPretsExtendAllLoansSuccessAndErrorThreePretsTest extends A
                 ->whenCalled('prolongerPret')
                 ->with($this->florence, '13')
                 ->answers(['statut' => 0,
-                           'erreur' => 'Prolongation interdite pour ce type de document.']);
+                           'erreur' => 'Prolongation interdite pour ce type de document.'])
+
+                ->whenCalled('getIntBib')
+                ->answers(null);
   }
 
 
@@ -852,29 +907,28 @@ class AbonneControllerPretsPeriodicalTitleTest extends AbstractAbonneControllerP
       ->setTitre('Avril-mai-juin 2013')
       ->setDateRetour('30-12-2015')
       ->setNoNotice(13340)
-      ->setBibliotheque('Espace Culturel François-Mitterrand');
+      ->setBibliotheque('Espace Culturel François-Mitterrand')
+      ->setExemplaireOPAC(
+                          $this->fixture('Class_Exemplaire',
+                                         ['id' => 967,
+                                          'id_origine' => 13340,
+                                          'id_int_bib' => 1,
+                                          'zone995' => serialize([['clef' => 'a', 'valeur' => 'Espace Culturel'],
+                                                                  ['clef' => 'f', 'valeur' => '0720028863'],
+                                                                  ['clef' => 'k', 'valeur' => 'J-REV 10-N°90']]),
+                                          'notice' => $this->fixture('Class_Notice',
+                                                                     ['id' => 889,
+                                                                      'unimarc' => file_get_contents(__DIR__.'/petites_mains.mrc')])]));
 
     $loan = new Class_WebService_SIGB_Emprunt(12387, $item);
-
     $patron->empruntsAdd($loan);
 
     Class_CommSigb::setInstance($this->mock()
                                 ->whenCalled('ficheAbonne')
-                                ->answers(['fiche' => $patron]));
+                                ->answers(['fiche' => $patron])
+                                ->whenCalled('getIntBib')
+                                ->answers(null));
 
-    $record = $this->fixture('Class_Notice',
-                             ['id' => 889,
-                              'unimarc' => file_get_contents(__DIR__.'/petites_mains.mrc')]);
-
-    $z995 = [['clef' => 'a', 'valeur' => 'Espace Culturel'],
-             ['clef' => 'f', 'valeur' => '0720028863'],
-             ['clef' => 'k', 'valeur' => 'J-REV 10-N°90']];
-
-    $this->fixture('Class_Exemplaire',
-                   ['id' => 967,
-                    'id_origine' => 13340,
-                    'zone995' => serialize($z995),
-                    'notice' => $record]);
 
     $identity->setIdabon('007');
 
@@ -892,4 +946,4 @@ class AbonneControllerPretsPeriodicalTitleTest extends AbstractAbonneControllerP
   public function titleShouldBePetitesMains90() {
     $this->assertXPathContentContains('//a', utf8_encode('Petites mains n° 90'));
   }
-}
\ No newline at end of file
+}
diff --git a/tests/application/modules/opac/controllers/BibControllerTest.php b/tests/application/modules/opac/controllers/BibControllerTest.php
index cbc776635e989e728a02086b4d1c3737b325a792..0fcea8751be3473b9212ae7be4f2b3d85d7c0180 100644
--- a/tests/application/modules/opac/controllers/BibControllerTest.php
+++ b/tests/application/modules/opac/controllers/BibControllerTest.php
@@ -686,7 +686,7 @@ class BibControllerBibViewAnnecyByRewriteUrlWithLinkToProfilTest extends BibCont
 
 
 
-class BibControllerBibViewAnnecyRangeOpeningsTest extends BibControllerBibViewTestCase {
+abstract class BibControllerLibraryWithOpeningsTestCase extends BibControllerBibViewTestCase {
   public function setUp() {
     parent::setUp();
 
@@ -745,7 +745,15 @@ class BibControllerBibViewAnnecyRangeOpeningsTest extends BibControllerBibViewTe
                     'debut_apres_midi' => '00:00',
                     'fin_apres_midi' => '00:00',
                     'label' => 'Repos']);
+  }
+}
+
 
+
+
+class BibControllerBibViewAnnecyRangeOpeningsTest extends BibControllerLibraryWithOpeningsTestCase {
+  public function setUp() {
+    parent::setUp();
     $this->dispatch('bib/bibview/id/4', true);
   }
 
@@ -1411,6 +1419,7 @@ abstract class BibControllerWidgetPageTestCase extends BibControllerWithThreeBib
     $this->_preferences = ['titre' => 'Bibliotheques',
                            'libraries' => '4;1;2',
                            'nb_aff' => 3,
+                           'fields' => 'opening_hours',
                            'order' => Class_Systeme_ModulesAccueil_Library::ORDER_SELECTION,
                            'filters' => 'custom_field_7;custom_field_5;custom_field_3;opening;town;territory;search'];
 
@@ -1535,6 +1544,12 @@ class BibControllerWidgetPageSelectOpenLibrariesTest extends BibControllerWidget
   }
 
 
+  /** @test */
+  public function openingHoursShouldBePresent() {
+    $this->assertXPathContentContains('//div[@class="field-opening-hours"]//li', '10h - 12h');
+  }
+
+
   /** @test */
   public function widgetShouldRenderLibraryCran() {
     $this->assertXPathContentContains('//div[@class="boite library"]//section/h2', 'Cran');
diff --git a/tests/application/modules/opac/controllers/OnSiteConsultationTest.php b/tests/application/modules/opac/controllers/OnSiteConsultationTest.php
index b82eaa81b2c633e289f2b486f275d699a659585d..43bb524a79dadcb9185265c3f90174d3307ff45e 100644
--- a/tests/application/modules/opac/controllers/OnSiteConsultationTest.php
+++ b/tests/application/modules/opac/controllers/OnSiteConsultationTest.php
@@ -444,7 +444,7 @@ class OnSiteConsultationReservationsTableTest extends OnSiteConsultationOneReser
 
   /** @test */
   public function titleShouldBeLinkToNoticeHarryPotter() {
-    $this->assertXPathContentContains('//td[2]/a[contains(@href, "/recherche/viewnotice/id/135/retour_abonne/reservations")]', 'Harry Potter', $this->_response->getBody());
+    $this->assertXPathContentContains('//td[2]/a[contains(@href, "/recherche/viewnotice/id/135/retour_abonne/reservations")]', 'Harry Potter');
   }
 
 
diff --git a/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php b/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php
index fc9ced76ea4306da95fc0bc5acf65e4de001ef02..efc7be7903fffedaaca3c1e2b44d65de1aacf244 100644
--- a/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php
+++ b/tests/application/modules/opac/controllers/RechercheControllerReservationTest.php
@@ -125,20 +125,19 @@ class RechercheControllerReservationPickupAjaxActionTestWithChosenPickupDispatch
       ->whenCalled('isConnected')->answers(true)
       ->whenCalled('reserverExemplaire')->answers(true);
 
-
-
-
     Class_WebService_SIGB_Nanook::setService($this->nanook);
 
     ZendAfi_Auth::getInstance()->logUser($this->jajm);
 
     Class_CosmoVar::newInstanceWithId('site_retrait_resa', ['valeur' => 1]);
 
-    $this->dispatch('recherche/reservationajax/id/11760/id_int_bib/23/id_bib/23/id_origine/594105/code_annexe/23/render/popup',true);
-    $this->_json = json_decode($this->_response->getBody());
-    $this->_xpath = new Storm_Test_XPath();
+    $this->fixture('Class_Exemplaire',
+                   ['id' => 12]);
+
+    $this->dispatch('recherche/reservationajax/id/11760/id_int_bib/23/id_bib/23/id_origine/594105/code_annexe/23/render/popup/copy_id/12',true);
   }
 
+
   /** @test */
   public function parameterCodeAnnexeShouldBeUsedForReservation() {
     $this->assertEquals('23',
@@ -170,6 +169,7 @@ class RechercheControllerReservationPickupAjaxActionTestWithPatronLibraryPickup
     $this->nanook = Storm_Test_ObjectWrapper::mock()
       ->whenCalled('isConnected')->answers(true)
       ->whenCalled('reserverExemplaire')->answers(true)
+      ->whenCalled('providesPickupLocations')->answers(false)
       ->whenCalled('getUserAnnexe')->answers('12');
 
     Class_WebService_SIGB_Nanook::setService($this->nanook);
@@ -190,9 +190,10 @@ class RechercheControllerReservationPickupAjaxActionTestWithPatronLibraryPickup
 
     Class_CosmoVar::newInstanceWithId('site_retrait_resa', ['valeur' => 2]);
 
-    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=ANN',true);
-    $this->_json = json_decode($this->_response->getBody());
-    $this->_xpath = new Storm_Test_XPath();
+    $this->fixture('Class_Exemplaire',
+                   ['id' => 12]);
+
+    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=ANN&copy_id=12',true);
   }
 
 
@@ -225,6 +226,7 @@ class RechercheControllerReservationPickupAjaxActionTestWithItemLibraryPickup ex
 
     $this->nanook = Storm_Test_ObjectWrapper::mock()
       ->whenCalled('isConnected')->answers(true)
+      ->whenCalled('providesPickupLocations')->answers(false)
       ->whenCalled('reserverExemplaire')->answers(true);
 
 
@@ -245,9 +247,10 @@ class RechercheControllerReservationPickupAjaxActionTestWithItemLibraryPickup ex
                       ->setCode('CRN')));
     Class_CosmoVar::newInstanceWithId('site_retrait_resa', ['valeur' => 0]);
 
-    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=ANN',true);
-    $this->_json = json_decode($this->_response->getBody());
-    $this->_xpath = new Storm_Test_XPath();
+    $this->fixture('Class_Exemplaire',
+                   ['id' => 12]);
+
+    $this->dispatch('recherche/reservation-pickup-ajax?id_bib=2&id_origine=12&code_annexe=ANN&copy_id=12',true);
   }
 
   /** @test */
@@ -261,6 +264,8 @@ class RechercheControllerReservationPickupAjaxActionTestWithItemLibraryPickup ex
 }
 
 
+
+
 class RechercheControllerReservationWithMailPostAction extends AbstractControllerTestCase {
   protected $_sent_mails;
 
@@ -354,6 +359,8 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
   public function setUp() {
     parent::setUp();
 
+    $webservice = 'http://bib.valensol.net';
+
     $this->jajm = $this->fixture('Class_Users',
                                  ['id' => 1,
                                   'login' => 'jajm',
@@ -361,15 +368,19 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
                                   'int_bib' => $this->fixture('Class_IntBib',
                                                               ['id' => 1,
                                                                'comm_sigb' => Class_IntBib::COM_KOHA,
-                                                               'comm_params' => ['url_serveur' => 'http://bib.valensol.net']])
+                                                               'comm_params' => ['url_serveur' => $webservice]])
                                    ]);
 
     ZendAfi_Auth::getInstance()->logUser($this->jajm);
+    $this->koha = Storm_Test_ObjectWrapper::mock();
+    $this->koha
+      ->whenCalled('getServerRoot')
+      ->answers($webservice);
 
-    Class_WebService_SIGB_Koha::setService(['url_serveur' => 'http://bib.valensol.net',
-                                            'id_bib' => 1,
-                                            'type' => Class_IntBib::COM_KOHA],
-                                           $this->koha = Storm_Test_ObjectWrapper::mock());
+      Class_WebService_SIGB_Koha::setService(['url_serveur' => $webservice,
+                                              'id_bib' => 1,
+                                              'type' => Class_IntBib::COM_KOHA],
+                                           $this->koha);
   }
 
 
@@ -377,16 +388,21 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
     $this->dispatch('/recherche/reservationajax/id_bib/1/copy_id/456/code_annexe/VS',
                     true);
     $this->json = json_decode($this->_response->getBody());
-    $this->assertEquals($this->json->content, $expected);
+    $this->assertEquals($expected, $this->json->content);
   }
 
 
   /** @test */
   public function withMatchingHoldMessageShouldContainsPickupLocation() {
-    $this->_dispatchWithEmprunteurAndAssertContentEquals(
-      $this->_prepareEmprunteurHolding($this->fixture('Class_Exemplaire', ['id' => 456]),
-                                       'Valensole'),
-      'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible pour être retiré à : Valensole');
+    $item = $this->fixture('Class_Exemplaire',
+                           ['id' => 456,
+                            'code_barres' => 123,
+                            'id_int_bib' => 1]);
+
+    $response = $this->_prepareEmprunteurHolding($item, 'Valensole');
+    $expected_message = 'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible pour être retiré à : Valensole';
+    $this->_dispatchWithEmprunteurAndAssertContentEquals($response,
+                                                         $expected_message);
   }
 
 
@@ -394,6 +410,8 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
   public function withMatchingHoldAndRecordMessageShouldContainsPickupLocationAndRecordTitleAuthor() {
     $exemplaire = $this->fixture('Class_Exemplaire',
                                  ['id' => 456,
+                                  'code_barres' => 123,
+                                  'id_int_bib' => 1,
                                   'notice' => $this->fixture('Class_Notice',
                                                              ['id' => 8890,
                                                               'titre_principal' => 'Arcadia',
@@ -405,10 +423,10 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
 
 
   /** @test */
-  public function withoutMatchingHoldMessageShouldNotContainsPickupLocation() {
+  public function withoutMatchingHoldMessageShouldContainsDocumentNotFound() {
     $this->_dispatchWithEmprunteurAndAssertContentEquals(
       $this->_prepareEmprunteurHolding(null, 'Valensole'),
-      'Votre réservation est enregistrée.<br>Nous vous informerons quand le document sera disponible');
+      'Document introuvable');
   }
 
 
@@ -427,7 +445,8 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
     $exemplaire = (new Class_WebService_SIGB_Exemplaire(2))
       ->setExemplaireOPAC($item);
     $hold = new Class_WebService_SIGB_Reservation(2, $exemplaire);
-    $hold->setPickupLocationLabel($pickup_label);
+    $hold->setPickupLocationLabel($pickup_label)
+         ->setCodeBarre(123);
 
     $emprunteur_jajm = Class_WebService_SIGB_Emprunteur::newInstance(2, 'jajm');
     $emprunteur_jajm->reservationsAdd($hold);
@@ -451,6 +470,9 @@ class RechercheControllerReservationWithWebServiceKohaTest extends AbstractContr
   public function popupResultContentWithWebServiceErrorShouldContainsErreurDeCommunication() {
     $this->jajm->setIdabon(395749);
 
+    $this->_prepareEmprunteurHolding($this->fixture('Class_Exemplaire', ['id' => 456]),
+                                     'Valensole');
+
     $this->koha->whenCalled('isConnected')->answers(false);
 
     $this->dispatchAndCheckContentEquals("Une erreur de communication avec le serveur a fait échouer la requête. Merci de signaler ce problème à la bibliothèque.");
diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php
index 9c3f2a094c0caa9a2c82a0c5edbf96a4600702f8..1adf3a474075a45ea631151e03e2a7994a739a0e 100644
--- a/tests/db/UpgradeDBTest.php
+++ b/tests/db/UpgradeDBTest.php
@@ -1200,4 +1200,25 @@ class UpgradeDB_315_Test extends UpgradeDBTestCase {
     $this->assertFieldType('linked_cards', $field, $type);
     $this->assertFieldNotNullable('linked_cards', $field);
   }
+}
+
+
+
+class UpgradeDB_316_Test extends UpgradeDBTestCase {
+
+  public function prepare() {
+    try {
+      $this->query("ALTER TABLE codif_section MODIFY id_section tinyint(4)");
+    } catch (Exception $e) {
+      var_dump($e);
+    }
+  }
+
+
+  /** @test */
+  public function idSectionShouldBeIntElevenPrimaryKey() {
+    $this->assertFieldType('codif_section','id_section', 'int(11)');
+    $this->assertField('codif_section','id_section', 'PRI', 'Key');
+    $this->assertField('codif_section','id_section', 'NO', 'Null');
+  }
 }
\ No newline at end of file
diff --git a/tests/library/Class/CommSigbTest.php b/tests/library/Class/CommSigbTest.php
index 9b2cc13b188fe395a2d33d7f5debe1c3537760ad..6584d2eab7cf79b2fecded0fbfdbf47b19524cc9 100644
--- a/tests/library/Class/CommSigbTest.php
+++ b/tests/library/Class/CommSigbTest.php
@@ -25,6 +25,7 @@ abstract class CommSigbTestCase extends ModelTestCase {
   public function setUp() {
     parent::setUp();
 
+    Class_CommSigb::setInstance(null);
     $this->comm_sigb = new Class_CommSigb();
     $florence = new stdClass();
     $florence->username     = 'FloFlo';
@@ -49,6 +50,7 @@ abstract class CommSigbTestCase extends ModelTestCase {
 
     $this->zend_cache = $this->mock();
     $this->zend_cache
+      ->whenCalled('load')->answers(false)
       ->whenCalled('test')->answers(false)
       ->whenCalled('remove')->answers(true)
       ->whenCalled('save')->answers(true);
@@ -282,9 +284,9 @@ class CommSigbAstrolabeOpsysTest extends CommSigbTestCase {
 
 
   /**
-      @test
-      @dataProvider exemplaires
-   */
+     @test
+     @dataProvider exemplaires
+  */
   public function getModeCommShouldReturnAnArrayWithCommParams($exemplaires) {
     $this->assertEquals(array("url_serveur" => 'http://astrolabe.com/opsys.wsdl',
                               "type" => Class_IntBib::COM_OPSYS,
@@ -308,8 +310,8 @@ class CommSigbMoulinsVSmartTest extends CommSigbTestCase {
     Class_WebService_SIGB_VSmart::setService($this->createMockForService('VSmart'));
   }
   /**
-      @test
-      @dataProvider exemplaires
+     @test
+     @dataProvider exemplaires
   */
   public function getDispoExemplairesShouldReturnAnArrayWithPotterInfos($exemplaires) {
     $potter = new Class_WebService_SIGB_Exemplaire('123');
@@ -424,7 +426,7 @@ class CommSigbMoulinsVSmartTest extends CommSigbTestCase {
                             Class_Exemplaire::find($exemplaires['id'])->callGetterByAttributeName($key),$ex->getId());
       }
     }
-}
+  }
 
 
 
@@ -672,6 +674,12 @@ class CommSigbWithNotAbonneTest extends ModelTestCase {
   }
 
 
+  public function tearDown() {
+    $this->comm_sigb = null;
+    parent::tearDown();
+  }
+
+
   /** @test */
   public function prolongerPretShouldReturnError() {
     $this->assertEquals(['erreur' => 'Communication SIGB indisponible'],
@@ -694,8 +702,9 @@ class CommSigbWithNotAbonneTest extends ModelTestCase {
 
   /** @test */
   public function reserverExemplaireShouldReturnError() {
+    $this->fixture('Class_Exemplaire', ['id' => 12]);
     $this->assertEquals(['erreur' => 'Communication SIGB indisponible'],
-                        $this->comm_sigb->reserverExemplaire(0, 0, 0));
+                        $this->comm_sigb->reserverExemplaire(0, 12, 0));
   }
 
 
diff --git a/tests/library/Class/WebService/SIGB/BiblixNetTest.php b/tests/library/Class/WebService/SIGB/BiblixNetTest.php
index 1168af7645d63ef583956cfb06f984608a1829f5..cfa2e491153dbbb84769f1645f14e8ecb03861ce 100644
--- a/tests/library/Class/WebService/SIGB/BiblixNetTest.php
+++ b/tests/library/Class/WebService/SIGB/BiblixNetTest.php
@@ -55,7 +55,6 @@ abstract class BiblixNetTestCase extends Storm_Test_ModelTestCase {
 
   public function setUp() {
     parent::setUp();
-
     $this->_mock_web_client = Storm_Test_ObjectWrapper::mock();
     Class_WebService_SIGB_BiblixNet::setService(null);
     $this->_service = Class_WebService_SIGB_BiblixNet
@@ -161,28 +160,17 @@ class BiblixNetGetPatronInfoJustinTicou extends BiblixNetTestCase {
       ->answers(BiblixNetFixtures::xmlGetPatronJustinTicou())
       ->beStrict();
 
-    $this->_emprunteur = $this->_service->getEmprunteur(Class_Users::getLoader()
-                                                        ->newInstance()
-                                                        ->setIdSigb(34));
+    $this->_emprunteur = $this->_service
+      ->getEmprunteur(Class_Users::getLoader()
+                      ->newInstance()
+                      ->setIdSigb(34));
+
+  }
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Exemplaire')
-      ->whenCalled('findFirstBy')
-      ->with(array('code_barres' => '1069005966314'))
-      ->answers(
-        Class_Exemplaire::getLoader()
-        ->newInstanceWithId(34)
-        ->setNotice(
-          Class_Notice::getLoader()
-          ->newInstanceWithId('117661')))
 
-      ->whenCalled('findFirstBy')
-      ->with(array('id_origine' => '00000007307'))
-      ->answers(
-        Class_Exemplaire::getLoader()
-        ->newInstanceWithId(36)
-        ->setNotice(
-          Class_Notice::getLoader()
-          ->newInstanceWithId('7307')));
+  /** @test */
+  public function numberOfLoansShouldBeTwo() {
+    $this->assertCount(2, $this->_emprunteur->getEmprunts());
   }
 
 
@@ -221,12 +209,6 @@ class BiblixNetGetPatronInfoJustinTicou extends BiblixNetTestCase {
   }
 
 
-  /** @test */
-  public function firstLoanNoticeShouldBe117661() {
-    $this->assertEquals(117661, $this->_emprunteur->getEmprunts()[0]->getNoticeOPAC()->getId());
-  }
-
-
   /** @test */
   public function firstLoanDateRetourShouldBe04_05_2011() {
     $this->assertEquals('04/05/2011', $this->_emprunteur->getEmprunts()[0]->getDateRetour());
@@ -239,12 +221,6 @@ class BiblixNetGetPatronInfoJustinTicou extends BiblixNetTestCase {
   }
 
 
-  /** @test */
-  public function firstHoldExemplaireOPACShouldBeTheOneWithId36() {
-    $this->assertEquals(36, $this->_emprunteur->getReservations()[0]->getExemplaireOPAC()->getId());
-  }
-
-
   /** @test */
   public function firstHoldRangShouldBeTwo() {
     $this->assertEquals(2, $this->_emprunteur->getReservations()[0]->getRang());
@@ -290,16 +266,16 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => true, 'erreur' => ''),
                         $this->_service->reserverExemplaire(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('34'),
-                          Class_Exemplaire::getLoader()->newInstance()->setIdOrigine('1432'),
-                          'Mediatheque'
+                                                            Class_Users::getLoader()->newInstance()->setIdSigb('34'),
+                                                            Class_Exemplaire::getLoader()->newInstance()->setIdOrigine('1432'),
+                                                            'Mediatheque'
                         ));
   }
 
 
   /** @test */
   public function reserverExemplairesWithErrorShouldReturnErrorWithMessage() {
-      $this->_mock_web_client
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://mediathequewormhout.biblixnet.com/exporte_afi/?service=HoldTitle&patronId=34&bibId=1432&pickupLocation=Mediatheque')
       ->answers(BiblixNetFixtures::xmlHoldTitleError())
@@ -308,9 +284,9 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => false, 'erreur' => 'Réservation impossible'),
                         $this->_service->reserverExemplaire(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('34'),
-                          Class_Exemplaire::getLoader()->newInstance()->setIdOrigine('1432'),
-                          'Mediatheque'
+                                                            Class_Users::getLoader()->newInstance()->setIdSigb('34'),
+                                                            Class_Exemplaire::getLoader()->newInstance()->setIdOrigine('1432'),
+                                                            'Mediatheque'
                         ));
   }
 
@@ -326,8 +302,8 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => true, 'erreur' => ''),
                         $this->_service->supprimerReservation(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('1'),
-                          '987'
+                                                              Class_Users::getLoader()->newInstance()->setIdSigb('1'),
+                                                              '987'
                         ));
   }
 
@@ -342,8 +318,8 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => false, 'erreur' => 'Annulation impossible'),
                         $this->_service->supprimerReservation(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('1'),
-                          '987'
+                                                              Class_Users::getLoader()->newInstance()->setIdSigb('1'),
+                                                              '987'
                         ));
   }
 
@@ -358,8 +334,8 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => true, 'erreur' => ''),
                         $this->_service->prolongerPret(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('4'),
-                          '987'
+                                                       Class_Users::getLoader()->newInstance()->setIdSigb('4'),
+                                                       '987'
                         ));
   }
 
@@ -374,8 +350,8 @@ class BiblixNetOperationsTest extends BiblixNetTestCase {
 
     $this->assertEquals(array('statut' => false, 'erreur' => 'Prolongation impossible'),
                         $this->_service->prolongerPret(
-                          Class_Users::getLoader()->newInstance()->setIdSigb('4'),
-                          '987'
+                                                       Class_Users::getLoader()->newInstance()->setIdSigb('4'),
+                                                       '987'
                         ));
   }
 
diff --git a/tests/library/Class/WebService/SIGB/CarthameTest.php b/tests/library/Class/WebService/SIGB/CarthameTest.php
index 80106799b59596bb06e71d3a75c9fde0a36696ea..3a24c6e8929f19c7e5bd45608207d1c1be87abdd 100644
--- a/tests/library/Class/WebService/SIGB/CarthameTest.php
+++ b/tests/library/Class/WebService/SIGB/CarthameTest.php
@@ -360,7 +360,8 @@ class CarthameEmprunteurPatrickBTest extends CarthameOperationTestCase {
     $exemplaire = $this->fixture('Class_Exemplaire', ['id' => 3,
                                                       'id_origine' => 'L8984',
                                                       'id_notice' => '123',
-                                                      'id_bib' => 47]);
+                                                      'id_bib' => 47,
+                                                      'id_int_bib' => 789]);
 
     $this->fixture('Class_Notice', ['id' => 123,
                                     'titre_principal' => 'Harry Potter',
@@ -375,13 +376,22 @@ class CarthameEmprunteurPatrickBTest extends CarthameOperationTestCase {
                           ->answers(CarthameTestFixtures::createEmprunteurPatrickBLoginXml())
                           ->whenCalled('open_url')
                           ->with('http://server.domain/webservices/index.php?sigb=karvi&version=standalone&idclient=bibkey&action=accountDetails&userid=3')
-                          ->answers(CarthameTestFixtures::createEmprunteurPatrickBXml())
-                          ;
+                          ->answers(CarthameTestFixtures::createEmprunteurPatrickBXml());
 
-    $this->emprunteur = $this->service->getEmprunteur(
-                          Class_Users::newInstance()
-                            ->setLogin('pbarroca')
-                            ->setPassword('1974'));
+    $library = $this->fixture('Class_IntBib',
+                              ['id' => 789,
+                               'comm_sigb' => Class_IntBib::COM_CARTHAME,
+                               'comm_params' => ['url_serveur' => 'https://mon-carthame.it']]);
+
+    $user = $this->fixture('Class_Users',
+                           ['id' => 56,
+                            'login' => 'pbarroca',
+                            'password' => '1974',
+                            'int_bib' => $library]);
+
+    ZendAfi_Auth::getInstance()->logUser($user);
+
+    $this->emprunteur = $this->service->getEmprunteur($user);
 
   }
 
diff --git a/tests/library/Class/WebService/SIGB/DynixTest.php b/tests/library/Class/WebService/SIGB/DynixTest.php
index 0c27ea5d748815dc9cf60b0abd4332401044b6ef..0dd0d7938f2b0a46b33aa612fda779e54956006e 100644
--- a/tests/library/Class/WebService/SIGB/DynixTest.php
+++ b/tests/library/Class/WebService/SIGB/DynixTest.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 require('DynixFixtures.php');
@@ -101,13 +101,13 @@ class DynixCurrentLocationAsStatus extends DynixTestCase {
   public function firstExemplaireDisponibiliteShouldBeInProgress() {
     $this->assertEquals('En traitement',
                         $this->_notice->exemplaireAt(0)->getDisponibilite());
-  } 
+  }
 
 
   /** @test */
   public function firstExemplaireShouldNotBeReservable() {
     $this->assertFalse($this->_notice->exemplaireAt(0)->isReservable());
-  } 
+  }
 }
 
 
@@ -188,7 +188,7 @@ class DynixGetNoticeLeCombatOrdinaire extends DynixTestCase {
   public function secondExemplairDisponibiliteShouldBeEnTransit() {
     $this->assertEquals(Class_WebService_SIGB_Exemplaire::DISPO_TRANSIT,
                         $this->_notice->exemplaireAt(1)->getDisponibilite());
-  } 
+  }
 
 
   /** @test */
@@ -201,25 +201,25 @@ class DynixGetNoticeLeCombatOrdinaire extends DynixTestCase {
   public function thirdExemplaireDisponibiliteShouldBeDisponible() {
     $this->assertEquals('Disponible',
                         $this->_notice->exemplaireAt(2)->getDisponibilite());
-  } 
+  }
 
   /** @test */
   public function thirdExemplaireShouldBeVisibleOPAC() {
     $this->assertTrue($this->_notice->exemplaireAt(2)->isVisibleOPAC());
-  } 
+  }
 
 
   /** @test */
   public function fourthExemplaireDisponibiliteShouldBeDiscard() {
     $this->assertEquals('Retiré',
                         $this->_notice->exemplaireAt(3)->getDisponibilite());
-  } 
+  }
 
 
   /** @test */
   public function fourthExemplaireDisponibiliteShouldNotBeVisibleOPAC() {
     $this->assertFalse($this->_notice->exemplaireAt(3)->isVisibleOPAC());
-  } 
+  }
 }
 
 
@@ -280,7 +280,7 @@ class DynixGetEmprunteurManuLarcinetTest extends DynixTestCase {
       ->answers('')
       ->beStrict();
 
-    $this->_manu = $this->_service->getEmprunteur(Class_Users::newInstanceWithId(3, ['login' => '0917036', 
+    $this->_manu = $this->_service->getEmprunteur(Class_Users::newInstanceWithId(3, ['login' => '0917036',
                                                                                      'password' => 'secret']));
   }
 
@@ -335,7 +335,7 @@ class DynixGetEmprunteurManuLarcinetTest extends DynixTestCase {
 
   /** @test */
   public function firstReservationCodeBarreShouldBe00577705() {
-    $this->assertEquals('00577705', $this->_manu->getReservationAt(0)->getCodeBarre());   
+    $this->assertEquals('00577705', $this->_manu->getReservationAt(0)->getCodeBarre());
   }
 
 
@@ -347,31 +347,31 @@ class DynixGetEmprunteurManuLarcinetTest extends DynixTestCase {
 
   /** @test */
   public function firstReservationIDShouldBe160540() {
-    $this->assertEquals('160540', $this->_manu->getReservationAt(0)->getId());    
+    $this->assertEquals('160540', $this->_manu->getReservationAt(0)->getId());
   }
 
 
   /** @test */
   public function firstReservationRangShouldBeOne() {
-    $this->assertEquals(1, $this->_manu->getReservationAt(0)->getRang());   
+    $this->assertEquals(1, $this->_manu->getReservationAt(0)->getRang());
   }
 
 
   /** @test */
   public function firstReservationEtatShouldBeReserve() {
-    $this->assertEquals('Réservé', $this->_manu->getReservationAt(0)->getEtat());   
+    $this->assertEquals('Réservé', $this->_manu->getReservationAt(0)->getEtat());
   }
 
 
   /** @test */
   public function secondReservationRangShouldBeTwo() {
-    $this->assertEquals(2, $this->_manu->getReservationAt(1)->getRang());   
+    $this->assertEquals(2, $this->_manu->getReservationAt(1)->getRang());
   }
 
 
   /** @test */
   public function secondReservationEtatShouldBeDisponible() {
-    $this->assertEquals('Disponible', $this->_manu->getReservationAt(1)->getEtat());    
+    $this->assertEquals('Disponible', $this->_manu->getReservationAt(1)->getEtat());
   }
 
 
@@ -412,7 +412,7 @@ abstract class DynixOperationsTestCase extends DynixTestCase {
       ->answers('')
       ->beStrict();
 
-    $this->_manu = Class_Users::newInstanceWithId(3, ['login' => '0917036', 
+    $this->_manu = Class_Users::newInstanceWithId(3, ['login' => '0917036',
                                                       'password' => 'secret',
                                                       'nom' => 'Skywalker',
                                                       'prenom' => 'Luc',
@@ -431,7 +431,7 @@ class DynixOperationsTest extends DynixOperationsTestCase {
       ->with('http://www.infocom94.fr:8080/capcvm/rest/standard/lookupTitleInfo?clientID=SymWS&titleID=233823&includeItemInfo=true&includeAvailabilityInfo=true')
       ->answers(DynixFixtures::xmlLookupTitleInfoLeCombatOrdinaire());
 
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/createMyHold?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&titleKey=233823&pickupLibraryID=ALFMEDA')
       ->answers('163144');
@@ -450,12 +450,12 @@ class DynixOperationsTest extends DynixOperationsTestCase {
       ->with('http://www.infocom94.fr:8080/capcvm/rest/standard/lookupTitleInfo?clientID=SymWS&titleID=233823&includeItemInfo=true&includeAvailabilityInfo=true')
       ->answers(DynixFixtures::xmlLookupTitleInfoLeCombatOrdinaire());
 
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/createMyHold?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&titleKey=233823&pickupLibraryID=CRETBUS')
       ->answers(DynixFixtures::createMyHoldFaultXML());
 
-    $this->assertEquals(['statut' => false, 
+    $this->assertEquals(['statut' => false,
                          'erreur' => 'Vous ne pouvez plus emprunter, adressez-vous au bibliothécaire'],
                         $this->_service->reserverExemplaire($this->_manu,
                                                             Class_Exemplaire::newInstance()
@@ -466,7 +466,7 @@ class DynixOperationsTest extends DynixOperationsTestCase {
 
   /** @test */
   public function successfulSupprimerReservationShouldReturnStatutTrue() {
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/cancelMyHold?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&holdKey=161340')
       ->answers('true');
@@ -478,7 +478,7 @@ class DynixOperationsTest extends DynixOperationsTestCase {
 
   /** @test */
   public function errorSupprimerReservationShouldReturnStatutFalseWithErrorMessage() {
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/cancelMyHold?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&holdKey=161340')
       ->answers(DynixFixtures::cancelMyHoldFaultXML());
@@ -491,7 +491,7 @@ class DynixOperationsTest extends DynixOperationsTestCase {
 
   /** @test */
   public function successfulProlongerPretShouldReturnStatutTrue() {
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/renewMyCheckout?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&itemID=39410001449012')
       ->answers(DynixFixtures::renewMyCheckoutSuccessXML());
@@ -504,7 +504,7 @@ class DynixOperationsTest extends DynixOperationsTestCase {
 
   /** @test */
   public function errorProlongerPretShouldReturnStatutFalseWithErrorMessage() {
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/renewMyCheckout?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&itemID=39410001449012')
       ->answers(DynixFixtures::renewMyCheckoutFaultXML());
@@ -526,7 +526,7 @@ class DynixReservationByMailForAvailableDocTest extends DynixOperationsTestCase
       ->with('http://www.infocom94.fr:8080/capcvm/rest/standard/lookupTitleInfo?clientID=SymWS&titleID=233823&includeItemInfo=true&includeAvailabilityInfo=true')
       ->answers(DynixFixtures::xmlLookupTitleInfoLeCombatOrdinaire());
 
-    $this->_mock_web_client   
+    $this->_mock_web_client
       ->whenCalled('open_url')
       ->with('http://www.infocom94.fr:8080/capcvm/rest/patron/createMyHold?clientID=SymWS&sessionToken=497e6380-69fb-4850-b552-40dede41f0b5&titleKey=233823&pickupLibraryID=ALFMEDA')
       ->never();
@@ -541,8 +541,8 @@ class DynixReservationByMailForAvailableDocTest extends DynixOperationsTestCase
                                                           'notice' => Class_Notice::newInstanceWithId(5)
                                                           ->setTitrePrincipal('Le combat ordinaire')]);
 
-    $bib_creteil = Class_Bib::newInstanceWithId(2, 
-                                                ['int_bib' => Class_IntBib::newInstanceWithId(2, 
+    $bib_creteil = Class_Bib::newInstanceWithId(2,
+                                                ['int_bib' => Class_IntBib::newInstanceWithId(2,
                                                                                           ['mail' => 'creteil@plaine.fr'])]);
 
     $exemplaire->setBib($bib_creteil)->setAnnexe('ALFMEDA');
@@ -550,7 +550,7 @@ class DynixReservationByMailForAvailableDocTest extends DynixOperationsTestCase
     Class_CosmoVar::newInstanceWithId('mail_admin', ['valeur' => 'creteil@plaine.fr']);
 
 
-    $bib_limeil = Class_Bib::newInstanceWithId(4, 
+    $bib_limeil = Class_Bib::newInstanceWithId(4,
                                                ['int_bib' => Class_IntBib::newInstanceWithId(4,
                                                                                          ['mail' => 'limeil@plaine.fr'])]);
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_CodifAnnexe')
@@ -589,8 +589,8 @@ class DynixReservationByMailForAvailableDocTest extends DynixOperationsTestCase
 
   /** @test */
   public function mailToShouldBeMalfortville() {
-    $this->assertContains('malfortville@agglo-plainecentrale94.fr', 
-                          $this->mail->getRecipients(), 
+    $this->assertContains('malfortville@agglo-plainecentrale94.fr',
+                          $this->mail->getRecipients(),
                           implode(',', $this->mail->getRecipients()));
   }
 
diff --git a/tests/library/Class/WebService/SIGB/EmpruntTest.php b/tests/library/Class/WebService/SIGB/EmpruntTest.php
index 7e2a06e05ac223e88698571073876ef28ff7384f..3365a58f08b7cc104ec50b80f9bbeaca16c60362 100644
--- a/tests/library/Class/WebService/SIGB/EmpruntTest.php
+++ b/tests/library/Class/WebService/SIGB/EmpruntTest.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 class WebServiceSIGBEmpruntTest  extends Storm_Test_ModelTestCase {
diff --git a/tests/library/Class/WebService/SIGB/KohaRestfulTest.php b/tests/library/Class/WebService/SIGB/KohaRestfulTest.php
index 5d4a03c2ae897f18b1f70a8d1388f205c837dc06..b63793f1e1a0c93b9244b4cbcc50125dc300c112 100644
--- a/tests/library/Class/WebService/SIGB/KohaRestfulTest.php
+++ b/tests/library/Class/WebService/SIGB/KohaRestfulTest.php
@@ -406,7 +406,7 @@ class KohaRestGetUserHistoryTest extends KohaRestfulTestCase {
     $this->mock_web_client
       ->whenCalled('open_url')
       ->with(static::BASE_URL . 'rest.pl/user/byid/34/issues_history')
-      ->answers(file_get_contents(realpath(dirname(__FILE__)) . '/../../../../fixtures/koha_issues_history.json'));
+      ->answers(file_get_contents(__DIR__ . '/../../../../fixtures/koha_issues_history.json'));
 
     $this->loans = $this->service->loansHistory($emprunteur);
   }
@@ -424,12 +424,6 @@ class KohaRestGetUserHistoryTest extends KohaRestfulTestCase {
   }
 
 
-  /** @test */
-  public function loanShouldHaveNoticeHopital() {
-    $this->assertEquals('2004',$this->loans[1]->getNoticeOPAC()->getAnnee());
-  }
-
-
   /** @test */
   public function returnDateShouldBe22_07_2015() {
     $this->assertEquals('22/07/2015', $this->loans[1]->getDateRetour());
diff --git a/tests/library/Class/WebService/SIGB/KohaTest.php b/tests/library/Class/WebService/SIGB/KohaTest.php
index ee7903bf7f57a26c9e877bf462d33e6d149570b0..5a6d0e7a9bfc9af3b89b2a8a45296f9c66ae3272 100644
--- a/tests/library/Class/WebService/SIGB/KohaTest.php
+++ b/tests/library/Class/WebService/SIGB/KohaTest.php
@@ -20,6 +20,7 @@
  */
 
 require_once 'tests/fixtures/KohaFixtures.php';
+
 class KohaGetServiceTest extends ModelTestCase {
   protected $_storm_default_to_volatile = true;
 
diff --git a/tests/library/Class/WebService/SIGB/MicrobibServiceTest.php b/tests/library/Class/WebService/SIGB/MicrobibServiceTest.php
index e4600508b089f04dbd9488b940a8a6f48d3f6b42..8c5ef82bf7cb896ba4eb4a60356e6a517034811c 100644
--- a/tests/library/Class/WebService/SIGB/MicrobibServiceTest.php
+++ b/tests/library/Class/WebService/SIGB/MicrobibServiceTest.php
@@ -20,21 +20,8 @@
  */
 
 include_once('MicrobibFixtures.php');
-
-abstract class MicrobibServiceIntegrationTest extends PHPUnit_Framework_TestCase {
-  /** @test */
-  public function infoExemplairesWithRealServer() {
-    Class_WebService_SIGB_Microbib::reset();
-    $microbib = Class_WebService_SIGB_Microbib::getService(array('url_serveur' => 'http://80.11.188.93/webservices/ws_maze.wsdl'));
-    $notice = $microbib->getNotice('5204');
-    $this->assertEquals(2, count($notice->getExemplaires()));
-  }
-}
-
-
-
-
-abstract class MicrobibServiceTestCase extends PHPUnit_Framework_TestCase {
+abstract class MicrobibServiceTestCase extends Storm_Test_ModelTestCase {
+  protected $_storm_default_to_volatile = true;
   protected $_search_client;
   protected $_microbib;
 
diff --git a/tests/library/Class/WebService/SIGB/NanookTest.php b/tests/library/Class/WebService/SIGB/NanookTest.php
index b6570a191e85dccf7ec5f3b1b5d97d5823a767cb..9bcee4388e67a84c8e72bac97dd251273a714db4 100644
--- a/tests/library/Class/WebService/SIGB/NanookTest.php
+++ b/tests/library/Class/WebService/SIGB/NanookTest.php
@@ -143,7 +143,7 @@ class NanookServiceTestCommunicationStatusTest extends NanookTestCase {
 
 
 
-abstract class NanookServiceErrorTestCase extends NanookTestCase {
+class NanookServiceErrorTestCase extends NanookTestCase {
   /** @test */
   public function reserverExemplaireShouldReturnFailure() {
     $this->assertEquals(
diff --git a/tests/library/Class/WebService/SIGB/OpsysServiceTest.php b/tests/library/Class/WebService/SIGB/OpsysServiceTest.php
index a7a85ac98f7e034802d126bbbc5d88aa37611b1f..8264382240cc4a9653628a0a4ea5329db1e21df4 100644
--- a/tests/library/Class/WebService/SIGB/OpsysServiceTest.php
+++ b/tests/library/Class/WebService/SIGB/OpsysServiceTest.php
@@ -1444,24 +1444,21 @@ class OpsysServiceEmpruntRetardAttributesTest extends Storm_Test_ModelTestCase {
 class OpsysServiceEmpruntTestSort extends Storm_Test_ModelTestCase {
   public function setUp() {
     $this->opsys_service = $this->createMock('Mock_OpsysService',
-                                          array('getEmpruntsOf', 'getReservationsOf'));
+                                             ['getEmpruntsOf',
+                                              'getReservationsOf']);
     $this->opsys_service
       ->expects($this->any())
       ->method('getEmpruntsOf')
-      ->will($this->returnValue(array(
-                                      EmpruntFixtures::cendrillon(),
-                                      EmpruntFixtures::alice(),
-                                      EmpruntFixtures::potter()
-                                      )));
+      ->will($this->returnValue([EmpruntFixtures::cendrillon(),
+                                 EmpruntFixtures::alice(),
+                                 EmpruntFixtures::potter()]));
 
     $this->opsys_service
       ->expects($this->any())
       ->method('getReservationsOf')
-      ->will($this->returnValue(array(
-                                      EmpruntFixtures::alice(),
-                                      EmpruntFixtures::potter(),
-                                      EmpruntFixtures::cendrillon(),
-                                      )));
+      ->will($this->returnValue([EmpruntFixtures::alice(),
+                                 EmpruntFixtures::potter(),
+                                 EmpruntFixtures::cendrillon()]));
 
     $this->emprunteur = new Class_WebService_SIGB_Emprunteur('1234', 'Yoda');
     $this->emprunteur->setService($this->opsys_service);
diff --git a/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php b/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php
index c44da9a1c330ed52b78f8f16331db7dcb604ead4..5ff507c6b3588437d49d501f96b6cda6c53a0a7c 100644
--- a/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php
+++ b/tests/library/Class/WebService/SIGB/OrpheeServiceTest.php
@@ -707,7 +707,8 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase
        'id_bib' => 3,
        'notice' => $this->fixture('Class_Notice',
                                   ['id' => '974898302',
-                                   'titre_principal' => 'Le Chemin'])]);
+                                   'titre_principal' => 'Le Chemin',
+                                   'auteur_principal' => 'Kyo'])]);
 
 
     $this->_search_client
@@ -928,7 +929,8 @@ class OrpheeServiceGetInfoUserCarteHenryDupontTest extends OrpheeServiceTestCase
    * @depends firstReservationShouldNotBeEmpty
    */
   public function firstReservationExemplaireOpacShouldBeLeChemin($reservation) {
-    $this->assertEquals('Le Chemin', $reservation->getExemplaire()->getExemplaireOPAC()->getTitrePrincipal());
+    $this->assertEquals('Le Chemin',
+                        $reservation->getExemplaire()->getExemplaireOPAC()->getTitrePrincipal());
   }
 
 
diff --git a/tests/library/Class/WebService/SIGB/PMBTest.php b/tests/library/Class/WebService/SIGB/PMBTest.php
index dea70a42a4a9d2507e4198199e12de7f82b18178..aff2ad9aa63e538341fa527f8d078498a960a333 100644
--- a/tests/library/Class/WebService/SIGB/PMBTest.php
+++ b/tests/library/Class/WebService/SIGB/PMBTest.php
@@ -198,7 +198,7 @@ class PMBServiceTest extends PMBTestCase {
   }
 
 
- /** @test */
+  /** @test */
   public function item20AvailabilityShouldBeExcluDuPret() {
     $item = $this->_service->getExemplaire('54', '000020');
     $this->assertEquals('Exclu du prêt', $item->getDisponibilite());
diff --git a/tests/library/Class/WebService/SIGB/VSmartTest.php b/tests/library/Class/WebService/SIGB/VSmartTest.php
index ab84ef9c317f1dee4a04647ce63680a116d0a1ec..bbe494de26d67a0edc68890caa903de1f82f2bfc 100644
--- a/tests/library/Class/WebService/SIGB/VSmartTest.php
+++ b/tests/library/Class/WebService/SIGB/VSmartTest.php
@@ -40,6 +40,7 @@ class VSmartServiceDummyFunctionsTest extends Storm_Test_ModelTestCase {
     $this->service = Class_WebService_SIGB_VSmart_Service::newInstance();
   }
 
+
   /** @test */
   public function isConnectedShouldReturnTrue() {
     $this->assertTrue($this->service->isConnected());
diff --git a/tests/library/ZendAfi/Validate/IsbnTest.php b/tests/library/ZendAfi/Validate/IsbnTest.php
index cce5ad323b82dad20f1beca4c7ea0da74f9271c0..548dfe323505d3b1255c1da40274394effe30471 100644
--- a/tests/library/ZendAfi/Validate/IsbnTest.php
+++ b/tests/library/ZendAfi/Validate/IsbnTest.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 class IsbnTest extends PHPUnit_Framework_TestCase {
@@ -49,9 +49,11 @@ class IsbnTest extends PHPUnit_Framework_TestCase {
 
 
   public function invalidIsbns() {
-    return [ ['234'], 
-             ['A-9?52298-0-X'],
-             ['978-1-?028-9462-6'] ];
+    return [
+            ['978-1-?028-9462-6'],
+            ['234'],
+            ['A-9?52298-0-X']
+    ];
   }
 
 
diff --git a/tests/library/ZendAfi/View/Helper/Abonne/ReservationsTableTest.php b/tests/library/ZendAfi/View/Helper/Abonne/ReservationsTableTest.php
index 048cf366837fbbd64725a355cd153e3b48135a6e..a36a6985531f5fd610237296dfafcec4a5efaccb 100644
--- a/tests/library/ZendAfi/View/Helper/Abonne/ReservationsTableTest.php
+++ b/tests/library/ZendAfi/View/Helper/Abonne/ReservationsTableTest.php
@@ -25,27 +25,58 @@ class ReservationsTableTest extends ViewHelperTestCase {
 
   public function setUp() {
     parent::setUp();
+    $potter_record = $this->fixture('Class_Notice',
+                                    ['id' => 100])
+                          ->setTitrePrincipal('Harry Potter');
+
+    $marche_record = $this->fixture('Class_Notice',
+                                    ['id' => 120]);
 
     $harry_potter = new Class_WebService_SIGB_Reservation('10', new Class_WebService_SIGB_Exemplaire(100));
     $harry_potter->getExemplaire()
                  ->setTitre('Harry Potter')
-                 ->setNoticeOPAC(Class_Notice::newInstanceWithId(100));
+                 ->setCodeBarre(123456)
+                 ->setNoticeOPAC($potter_record);
     $harry_potter->setEtat('Pas disponible');
 
 
     $le_marche = new Class_WebService_SIGB_Reservation('12', new Class_WebService_SIGB_Exemplaire(120));
     $le_marche->getExemplaire()
               ->setTitre('Le marché couvert')
-              ->setNoticeOPAC(Class_Notice::newInstanceWithId(120));
+              ->setCodeBarre(456789)
+              ->setNoticeOPAC($marche_record);
     $le_marche->setEtat('Disponible');
 
     $emprunteur = new Class_WebService_SIGB_Emprunteur('1234', 'Estelle');
     $emprunteur->reservationsAddAll([$harry_potter, $le_marche]);
 
-    $user = Class_Users::newInstanceWithId('123456',
-                                           ['nom' => 'Estelle',
-                                            'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB])
-      ->setFicheSigb(['fiche' => $emprunteur]);
+    $this->fixture('Class_Exemplaire',
+                   ['id' => 45,
+                    'code_barres' => 123456,
+                    'id_notice' => 100,
+                    'id_int_bib' => 654]);
+
+    $this->fixture('Class_Exemplaire',
+                   ['id' => 89,
+                    'code_barres' => 456789,
+                    'id_notice' => 120,
+                    'id_int_bib' => 654]);
+
+    $this->fixture('Class_IntBib',
+                   ['id' => 654,
+                    'comm_sigb' => 666,
+                    'comm_params' => ['url_serveur' => 'https://mon-sigb.even']]);
+
+    $user = $this->fixture('Class_Users',
+                           ['id' => 123456,
+                            'nom' => 'Estelle',
+                            'login' => 'stl',
+                            'password' => 'pwd',
+                            'idabon' => '888',
+                            'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB,
+                            'id_site' => 654,
+                            'id_int_bib' => 654])
+                 ->setFicheSigb(['fiche' => $emprunteur]);
     ZendAfi_Auth::getInstance()->logUser($user);
 
     $helper = new ZendAfi_View_Helper_Abonne_ReservationsTable();
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php b/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
index d2c4994a131e5663554928f53f8ebc7a6cf6cf5f..10fc40437aa38aa6beb87034e2cf6c0b7e446b32 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
@@ -37,10 +37,9 @@ class PretsTestWithConnectedUser extends ViewHelperTestCase {
     $alice = new Class_WebService_SIGB_Emprunt(456, new Class_WebService_SIGB_Exemplaire(456));
     $alice->getExemplaire()
           ->setTitre('Alice')
-          ->setNoticeOPAC(Class_Notice::newInstanceWithId(1234))
+          ->setNoticeOPAC(Class_Notice::newInstanceWithId(1234)->setTitrePrincipal('Alice'))
           ->setDateRetour('21/10/2021');
 
-
     $klein = new Class_WebService_SIGB_Emprunt(458, new Class_WebService_SIGB_Exemplaire(458));
     $klein->getExemplaire()->setTitre('La stratégie du choc');
     $klein->parseExtraAttributes(['Dateretourprevue' => '21/10/2000',
@@ -48,7 +47,6 @@ class PretsTestWithConnectedUser extends ViewHelperTestCase {
                                   'Auteur' => 'Naomie Klein',
                                   'Bibliotheque' => 'Almont']);
 
-
     $emprunteur = new Class_WebService_SIGB_Emprunteur('1234', 'Estelle');
     $emprunteur->empruntsAddAll([$klein, $alice]);
 
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/ReservationsTest.php b/tests/library/ZendAfi/View/Helper/Accueil/ReservationsTest.php
index df927e47113d378b2d9ce87f5b9e9c9fa78e17d7..d00c293673fb357a3934cc6de6f70d0c447aeacb 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/ReservationsTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/ReservationsTest.php
@@ -35,15 +35,15 @@ class ReservationsTestWithConnectedUser extends ViewHelperTestCase {
     $helper->setView(new ZendAfi_Controller_Action_Helper_View());
     $propaganda = new Class_WebService_SIGB_Reservation('13', new Class_WebService_SIGB_Exemplaire(456));
     $propaganda->getExemplaire()
-          ->setTitre('Propaganda')
-          ->setNoticeOPAC(Class_Notice::newInstanceWithId(1234));
+               ->setTitre('Propaganda')
+               ->setNoticeOPAC(Class_Notice::newInstanceWithId(1234)->setTitrePrincipal('Propaganda'));
 
     $propaganda->setEtat('Pas disponible');
 
     $en_suivant_emma = new Class_WebService_SIGB_Reservation('13', new Class_WebService_SIGB_Exemplaire(456));
     $en_suivant_emma->getExemplaire()
           ->setTitre('En suivant Emma')
-          ->setNoticeOPAC(Class_Notice::newInstanceWithId(333));
+                    ->setNoticeOPAC(Class_Notice::newInstanceWithId(333)->setTitrePrincipal('En suivant Emma'));
 
     $en_suivant_emma->setEtat('Disponible');
     $emprunteur = new Class_WebService_SIGB_Emprunteur('1234', 'Estelle');
diff --git a/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php b/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
index e6e271ed0e6945979c69c19ecfaa27492b52eff3..fc6a057b2b2eee8e212e8b69002b93598c6a24b2 100644
--- a/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
+++ b/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
@@ -58,6 +58,12 @@ abstract class ExternalAgendasAdminTestCase extends Admin_AbstractControllerTest
   }
 
   public function __call($method, $args) { /** in order to stub Class_ExternalAgenda::import($this) */}
+
+
+  public function tearDown() {
+    Class_WebService_ICalendar::setDefaultHttpClient(null);
+    parent::tearDown();
+  }
 }
 
 
@@ -475,12 +481,6 @@ class ExternalAgendasAdminImportTest extends ExternalAgendasAdminTestCase {
   }
 
 
-  public function tearDown() {
-    Class_WebService_ICalendar::setDefaultHttpClient(null);
-    parent::tearDown();
-  }
-
-
   /** @test */
   public function titleShouldBeMoissonageDesEvenements() {
     $this->assertXPathContentContains('//h1', 'Moissonnage des évènements de l\'agenda "Personal Agenda"');
@@ -490,8 +490,7 @@ class ExternalAgendasAdminImportTest extends ExternalAgendasAdminTestCase {
   /** @test */
   public function pageShouldContainsABackButton() {
     $this->assertXPathContentContains('//div[contains(@onclick, "replace(\'/admin/external-agendas\')")]//td',
-                                      'Retour à la liste des agendas',
-                                      $this->_response->getBody());
+                                      'Retour à la liste des agendas');
   }
 
 
@@ -660,3 +659,36 @@ class ExternalAgendasAdminSecondImportTest extends ExternalAgendasAdminTestCase
     $this->assertEquals(1, Class_ArticleCategorie::countBy(['libelle' => 'Atelier']));
   }
 }
+
+
+
+
+
+class ExternalAgendasAdminErmesImportTest extends ExternalAgendasAdminTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    Class_WebService_ICalendar::setDefaultHttpClient($this->mock()
+                                                     ->whenCalled('open_url')
+                                                     ->with('http://my.server.com/calendar.ics')
+                                                     ->answers(file_get_contents(__DIR__.'/ermes.ics'))
+                                                     ->beStrict());
+
+    $this->dispatch('/admin/external-agendas/import/id/124', true);
+    Class_Article::clearCache();
+  }
+
+
+
+  /** @test */
+  public function pageShouldContainsFiveEventsCreated() {
+    $this->assertXPathContentContains('//h2',
+                                      'Nombre d\'évènements créés : 5');
+  }
+
+
+  /** @test */
+  public function firstEventDescriptionShouldContainsEntreeLibre() {
+    $this->assertContains('entrée libre', Class_Article::find(1)->getContenu());
+  }
+}
diff --git a/tests/scenarios/ExternalAgendas/ermes.ics b/tests/scenarios/ExternalAgendas/ermes.ics
new file mode 100644
index 0000000000000000000000000000000000000000..a92980782c2d371ee99e16be4eff1b06224d9df0
--- /dev/null
+++ b/tests/scenarios/ExternalAgendas/ermes.ics
@@ -0,0 +1,128 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//ddaysoftware.com//NONSGML DDay.iCal 1.0//EN
+X-ARCHIMED-IdAgenda:1
+X-ARCHIMED-Rights:
+X-WR-CALDESC:Ermes Calandar
+X-WR-CALNAME:Evenements des médiathèques de Lille
+BEGIN:VTIMEZONE
+TZID:Romance Standard Time
+BEGIN:STANDARD
+DTSTART:20161002T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYHOUR=3;BYMINUTE=0;BYMONTH=10
+TZNAME:Romance Standard Time
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20160301T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYHOUR=2;BYMINUTE=0;BYMONTH=3
+TZNAME:Romance Daylight Time
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:Heure du conte pour les 0-3 ans<br />Parents-Enfants<br />entré
+ e libre
+DTEND:20160921T110000
+DTSTAMP:20170118T135101Z
+DTSTART:20160921T103000
+LAST-MODIFIED:20160927T114437
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Tentative
+SUMMARY:Kilikili minus
+UID:a1bc19ad-9371-4627-80e1-16ed6d303b89
+X-ALT-DESC;FMTTYPE=text/html:Heure du conte pour les 0-3 ans<br />Parents-E
+ nfants<br />entrée libre
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Alexis SETFAOUI (admin)
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:Heure du conte pour les 0-3 ans<br />Parents-Enfants<br />entré
+ e libre
+DTEND:20161015T110000
+DTSTAMP:20170118T135101Z
+DTSTART:20161015T103000
+LAST-MODIFIED:20160927T114437
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Tentative
+SUMMARY:Kilikili minus
+UID:c0de757c-ff46-4dac-b648-05e972da2784
+X-ALT-DESC;FMTTYPE=text/html:Heure du conte pour les 0-3 ans<br />Parents-E
+ nfants<br />entrée libre
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Alexis SETFAOUI (admin)
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND;VALUE=DATE:20160921
+DTSTAMP:20170118T135101Z
+DTSTART:20160921T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:3905e44d-9fa9-48f8-b1ad-6a7beda0ee76
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND:20161012T160000
+DTSTAMP:20170118T135101Z
+DTSTART:20161012T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:35b302c6-e362-4f8a-9861-b7b9b91eb568
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND:20161116T160000
+DTSTAMP:20170118T135101Z
+DTSTART:20161116T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:bb7f02cf-3515-4dbc-ae57-3bdd35a341ad
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+END:VCALENDAR