diff --git a/library/Class/Album.php b/library/Class/Album.php
index ef39a702a913c098482b4914dee9ae4d64bb1f54..24871b321decb638b2c5bf0006d83ca45c5a4db0 100644
--- a/library/Class/Album.php
+++ b/library/Class/Album.php
@@ -111,7 +111,11 @@ class Class_Album extends Storm_Model_Abstract {
 													'usage_constraints' => ['model' => 'Class_Album_UsageConstraint',
 																									'role' => 'album',
 																									'instance_of' => 'Class_Album_UsageConstraints',
-																									'dependents' => 'delete']];
+																									'dependents' => 'delete'],
+
+													'items' => ['model' => 'Class_Album_Item',
+																			'role' => 'album',
+																			'dependents' => 'delete']];
 
 	protected $_default_attribute_values = ['titre' => '',
 																					'sous_titre' => '',
diff --git a/library/Class/Album/Item.php b/library/Class/Album/Item.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a521b6efb0a858ae6d3a1f740c055d4ca56cd61
--- /dev/null
+++ b/library/Class/Album/Item.php
@@ -0,0 +1,40 @@
+<?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
+ */
+
+class Class_Album_Item extends Storm_Model_Abstract {
+	protected
+		$_table_name = 'album_item',
+		$_belongs_to = ['album' => ['model' => 'Class_Album']],
+		$_default_attribute_values = ['loan_count' => 0];
+
+
+	public function incrementLoanCount() {
+		$this->setLoanCount((int) $this->getLoanCount() + 1);
+		return $this;
+	}
+
+
+	public function incrementQuantity() {
+		$this->setQuantity((int) $this->getQuantity() + 1);
+		return $this;
+	}
+}
+?>
\ No newline at end of file
diff --git a/library/Class/Album/UsageConstraint.php b/library/Class/Album/UsageConstraint.php
index 2fc8065ad2d9aef3e64c1ff4767753fd9020a88a..5ac1477aa8aad2f59f1f8f5ab08d722ac8b4c303 100644
--- a/library/Class/Album/UsageConstraint.php
+++ b/library/Class/Album/UsageConstraint.php
@@ -25,9 +25,9 @@ class Class_Album_UsageConstraint extends Storm_Model_Abstract {
 		DEVICE_SHARE_CONSTRAINT = '04',
 		LOAN_CONSTRAINT = '06',
 		AVAILABILITY_CONSTRAINT = '07',
+		ORDER_LINE_ID = 'order_line_id',
 		DURATION = 'duration',
 		QUANTITY = 'quantity',
-		ORDER_LINE_ID = 'order_line_id',
 		MAX_NB_OF_USERS = 'max_number_of_users';
 
 	protected
@@ -121,17 +121,23 @@ class Class_Album_UsageConstraint extends Storm_Model_Abstract {
 	}
 
 
-	protected function hasAvailableLoanUsers() {
-		return true;
+	public function hasAvailableLoanUsers() {
+		if(!$item = Class_Album_Item::findFirstBy(['album_id' => $this->getAlbum()->getId()]))
+			return false;
+
+		return $item->getLoanCount() < $this->getMaxNumberOfUsers();
 	}
 
 
-	protected function hasAvailableLoans() {
-		return true;
+	public function hasAvailableQuantity() {
+		if(!$item = Class_Album_Item::findFirstBy(['album_id' => $this->getAlbum()->getId()]))
+			return false;
+
+		return $item->getQuantity() < $this->getQuantity();
 	}
 
 
-	protected function hasAvailableTime() {
+	public function hasAvailableTime() {
 		return true;
 	}
 
diff --git a/library/Class/Album/UsageConstraints.php b/library/Class/Album/UsageConstraints.php
index 902127fc49d15907a0eddba99c223ee6cdd63fa9..83149cd8fb0b761be5540fdff74a30d25a8801d1 100644
--- a/library/Class/Album/UsageConstraints.php
+++ b/library/Class/Album/UsageConstraints.php
@@ -66,6 +66,16 @@ class Class_Album_UsageConstraints extends Storm_Model_Collection_Abstract {
 	}
 
 
+ 	public function hasAvailableLoanUsers() {
+		return $this->getLoanConstraint()->hasAvailableLoanUsers();
+	}
+
+
+	public function hasAvailableQuantity() {
+		return $this->getLoanConstraint()->hasAvailableQuantity();
+	}
+
+
 	public function acceptVisitor($visitor) {
 		return $this->eachDo(function($c) use ($visitor){ $visitor->visitUsageConstraint($c);});
 	}
diff --git a/library/Class/Pret.php b/library/Class/Pret.php
index 55547cf96b4dc8564702e61fa491c82160ad4c24..e81e2dd44adbde4b03c1b5cafb419ff82ee8ca77 100644
--- a/library/Class/Pret.php
+++ b/library/Class/Pret.php
@@ -36,5 +36,4 @@ class Class_Pret extends Storm_Model_Abstract {
 																					'code_barres' => $this->getCodeBarres()]);$item;
 	}
 }
-
 ?>
\ No newline at end of file
diff --git a/library/Class/WebService/BibNumerique/Dilicom/Book.php b/library/Class/WebService/BibNumerique/Dilicom/Book.php
index 2fea88928b13e14abc45fae8eabb364498024292..fb221012fa0af552b9861609b1d6d902aced5684 100644
--- a/library/Class/WebService/BibNumerique/Dilicom/Book.php
+++ b/library/Class/WebService/BibNumerique/Dilicom/Book.php
@@ -35,7 +35,8 @@ class Class_WebService_BibNumerique_Dilicom_Book extends Class_WebService_BibNum
 			->setISBN($this->_isbn)
 			->setSousTitre($this->_subtitle)
 			->addEditor($this->getEditeur())
-			->setUsageConstraints($this->_usage_constraints);
+			->setUsageConstraints($this->_usage_constraints)
+			->addItem(new Class_Album_Item());
 
 		if ($this->_order_line_id)
 			$album
diff --git a/library/Class/WebService/BibNumerique/Dilicom/Hub.php b/library/Class/WebService/BibNumerique/Dilicom/Hub.php
index 527029bbc01e36e9c0806e005d0e0a03d838bc07..d5cefeb7400323e434c090c3693c9395ec71ff3b 100644
--- a/library/Class/WebService/BibNumerique/Dilicom/Hub.php
+++ b/library/Class/WebService/BibNumerique/Dilicom/Hub.php
@@ -21,15 +21,16 @@
 
 
 class Class_WebService_BibNumerique_Dilicom_Hub extends Class_WebService_Abstract {
-	use Trait_TimeSource;
+	use Trait_TimeSource,
+		Trait_Translator;
 
 	protected $_now;
 
 
 	public function endLoanBook($album, $pret) {
 		$content = json_decode($this->dilicomCall('endLoan',
-																						 ['orderLineId' => $this->getOrderLineId($album),
-																							'loanId' => $pret->getId()]));
+																							['orderLineId' => $this->getOrderLineId($album),
+																							 'loanId' => $pret->getId()]));
 
 		if(!$content->returnMessage)
 			$pret->setEnCours(0)->save();
@@ -39,30 +40,53 @@ class Class_WebService_BibNumerique_Dilicom_Hub extends Class_WebService_Abstrac
 
 
 	public function loanBook($album) {
+		$user = Class_Users::getIdentity();
 		$this->_now = $this->getCurrentTime();
 
-		$pret = Class_Pret::newInstance(['code_barres' => $album->getIsbn(),
-																		 'idabon' => Class_Users::getIdentity()->getIdabon(),
+		if(($pret = Class_Pret::findFirstBy(['idabon' => $user->getIdabon(),
+																				 'en_cours' => 1,
+																				 'id_notice_origine' => $album->getIdOrigine()]))
+			 && ($pret->getDateRetour() > $this->startDate()))
+			return (object) ['link' => (object) ['url' => $pret->getLoanLink()],
+											 'returnMessage' => []];
+
+ 		if(!$album->getUsageConstraints()->hasAvailableLoanUsers())
+			return (object) ['returnMessage' => [$this->_('Emprunt impossible. Le nombre d\'emprunts simultanés est atteint.')]];
+
+		if(!$album->getUsageConstraints()->hasAvailableQuantity())
+			return (object) ['returnMessage' => [$this->_('Emprunt impossible. Le nombre d\'emprunts disponible est épuisé.')]];
+
+		$pret = Class_Pret::newInstance(['idabon' => $user->getIdabon(),
 																		 'en_cours' => 1,
-																		 'date_pret' => $this->startDate(),
-																		 'date_retour' => $this->endDate(),
+																		 'date_pret' => urlencode($this->startDate()),
+																		 'date_retour' => urlencode($this->endDate()),
 																		 'id_notice_origine' => $album->getIdOrigine()]);
+
+		$params = ['id_album' => $album->getId()];
+
+		$item = Class_Album_Item::findFirstBy($params);
+		$item->incrementLoanCount()
+				 ->incrementQuantity()
+				 ->save();
+
 		$pret->save();
 
 		$response = $this->dilicomCall('loanBook',
-															['orderLineId' => $this->getOrderLineId($album),
-															 'accessMedium' => 'STREAMING',
-															 'localization' => 'IN_SITU',
-															 'loanEndDate' => $this->endDate(),
-															 'ean13' => $album->getISBN(),
-															 'loanId' =>  $pret->getId(),
-															]);
+																	 ['orderLineId' => $this->getOrderLineId($album),
+																		'accessMedium' => 'STREAMING',
+																		'localization' => 'IN_SITU',
+																		'loanEndDate' => urlencode($this->endDate()),
+																		'ean13' => $album->getISBN(),
+																		'loanId' =>  $pret->getId(),
+																	 ]);
 
 		$content = json_decode($response);
 
 		if ($content->returnMessage)
 			$pret->delete();
 
+		$pret->setLoanLink($content->link->url);
+
 		return $content;
 	}
 
@@ -73,7 +97,7 @@ class Class_WebService_BibNumerique_Dilicom_Hub extends Class_WebService_Abstrac
 															['orderLineId' => $this->getOrderLineId($album),
 															 'accessMedium' => 'STREAMING',
 															 'localization' => 'IN_SITU',
-															 'consultEndDate' => $this->endDate(),
+															 'consultEndDate' => urlencode($this->endDate()),
 															 'ean13' => $album->getISBN(),
 															 'ipAddress' => $ip_address,
 															 'loanId' =>  implode('',
@@ -105,7 +129,7 @@ class Class_WebService_BibNumerique_Dilicom_Hub extends Class_WebService_Abstrac
 
 
 	protected function iso8601($timestamp) {
-		return urlencode(date(DATE_ISO8601, $timestamp));
+		return date(DATE_ISO8601, $timestamp);
 	}
 
 
diff --git a/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php b/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
index d5e999147763acb8605038935549a917b6c30180..d91a9cd9fb83e9734f6141ef170b901ced17d044 100644
--- a/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
+++ b/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
@@ -49,11 +49,18 @@ abstract class BibNumeriqueContollerDilicomTestCase extends AbstractControllerTe
 																	'external_uri' => 'http://www.edenlivres.fr/p/23416',
 																	'type_doc_id' => Class_TypeDoc::DILICOM,
 																	'isbn' => '435465',
+																	'items' => [$this->fixture('Class_Album_Item',
+																														 ['id' => 1,
+																															'id_album' => 3,
+																															'loan_count' => 2,
+																															'quantity' => 4])],
 																	'usage_constraints' => [$this->fixture('Class_Album_UsageConstraint',
 																																				 ['id' => 1,
 																																					'id_album' => 3,
 																																					'titre ' => 'Totem et Thora',
 																																					'usage_type' => Class_Album_UsageConstraint::LOAN_CONSTRAINT,
+																																					Class_Album_UsageConstraint::MAX_NB_OF_USERS => 3,
+																																					Class_Album_Usageconstraint::QUANTITY => 50,
 																																					'order_line_id' => 'x321'])]]);
 
 
@@ -183,6 +190,18 @@ class BibNumeriqueControllerDilicomLoanBookActionTest extends BibNumeriqueContol
 	public function bokehLoanShouldHaveBeenSaved() {
 		$this->assertNotNull(Class_Pret::findFirstBy(['id_notice_origine' => 'Dilicom-88817216']));
 	}
+
+
+ 	/** @test */
+	public function albumItemLoanCountShouldBeThree() {
+		$this->assertEquals(3, $this->book->getItems()[0]->getLoanCount());
+	}
+
+
+	/** @test */
+	public function albumItemQuantityShouldBeFive() {
+		$this->assertEquals(5, $this->book->getItems()[0]->getQuantity());
+	}
 }
 
 
@@ -305,4 +324,103 @@ class BibNumeriqueControllerDilicomEndLoanBookErrorTest extends BibNumeriqueCont
 		$this->dispatch('/bib-numerique/end-loan-book/id/3', true);
 		$this->assertFlashMessengerContains('The loan with orderlineId \'524ade40bbd31c6240a30dff\' and loanId \'loanId\' is already ended');
 	}
-}
\ No newline at end of file
+}
+
+
+
+class BibNumeriqueControllerDilicomLoanBookActionTwiceWithSameUserTest extends BibNumeriqueContollerDilicomTestCase {
+	public function setUp() {
+		parent::setUp();
+		$_SERVER['HTTP_REFERER'] = '/viewnotice/id/3';
+
+		$this->_http
+			->whenCalled('open_url')
+			->never();
+
+		$this->fixture('Class_Pret',
+									 ['id' => 5,
+										'idabon' => '12345',
+										'id_notice_origine' => 'Dilicom-88817216',
+										'en_cours' => 1,
+										'date_retour' => '2014-05-02T18:14:14+0200',
+										'loan_link' => 'https://pnb-dilicom.centprod.com/v2//link/3025594195810/LOAN/WIKI001/9782021153057-NUMOIY0785CYO0IGCV83DE9DOAOC1Y1O.do']);
+
+		$this->dispatch('/bib-numerique/loan-book/id/3', true);
+	}
+
+
+	/** @test */
+	public function responseShouldReturnDownloadUrl() {
+		$this->assertRedirectTo('https://pnb-dilicom.centprod.com/v2//link/3025594195810/LOAN/WIKI001/9782021153057-NUMOIY0785CYO0IGCV83DE9DOAOC1Y1O.do');
+	}
+}
+
+
+
+abstract class BibNumeriqueContollerDilicomSecondUserTestCase extends BibNumeriqueContollerDilicomTestCase {
+	public function setUp() {
+		parent::setUp();
+		$_SERVER['HTTP_REFERER'] = '/viewnotice/id/3';
+
+		$second_user = $this->fixture('Class_Users',
+																	['id' => 78,
+																	 'nom'=>'Dily',
+																	 'login'=>'Chaton',
+																	 'password'=>'123456',
+																	 'id_site' => 1,
+																	 'idabon' => '654321',
+																	 'user_groups' => [Class_UserGroup::find(20)]]);
+
+		$second_user->beAbonneSIGB()->assertSave();
+		ZendAfi_Auth::getInstance()->logUser($second_user);
+
+		$this->_http
+			->whenCalled('open_url')
+			->never();
+	}
+}
+
+
+
+
+class BibNumeriqueControllerDilicomLoanBookActionWithASecondUserAndLoanCountExcededTest extends BibNumeriqueContollerDilicomSecondUserTestCase {
+	public function setUp() {
+		parent::setUp();
+		Class_Album_Item::find(1)->setLoanCount(3)->save();
+		$this->dispatch('/bib-numerique/loan-book/id/3', true);
+	}
+
+
+	/** @test */
+	public function responseShouldRedirectToReferer() {
+		$this->assertRedirectTo('/viewnotice/id/3');
+	}
+
+
+	/** @test */
+	public function notificationShouldReturnNoLoansAvailable() {
+ 		$this->assertFlashMessengerContains('Emprunt impossible. Le nombre d\'emprunts simultanés est atteint.');
+	}
+}
+
+
+
+class BibNumeriqueControllerDilicomLoanBookActionWithASecondUserAndTotalLoanCountExcededTest extends BibNumeriqueContollerDilicomSecondUserTestCase {
+	public function setUp() {
+		parent::setUp();
+		Class_Album_Item::find(1)->setQuantity(50)->save();
+		$this->dispatch('/bib-numerique/loan-book/id/3', true);
+	}
+
+
+	/** @test */
+	public function responseShouldRedirectToReferer() {
+		$this->assertRedirectTo('/viewnotice/id/3');
+	}
+
+
+	/** @test */
+	public function notificationShouldContainsNoLoansAvailable() {
+ 		$this->assertFlashMessengerContains('Emprunt impossible. Le nombre d\'emprunts disponible est épuisé.', $this->_getFlashMessengerMessages()[0]);
+	}
+}
diff --git a/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php b/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
index cba6a0806fc2957a2cc592ef2db454152f8fefda..6d6744b4efc0990d5139a69398467c9c8d524817 100644
--- a/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
+++ b/tests/library/Class/WebService/Dilicom/PNBOffersParserTest.php
@@ -95,6 +95,15 @@ class DilicomPNBOfferParserTest extends Storm_Test_ModelTestCase {
 	}
 
 
+	/**
+	 * @depends firstAlbumShouldBePlusJamaisSansElle
+	 * @test
+	 */
+	public function firstAlbumShouldHaveOneItem($album) {
+		$this->assertCount(1, $album->getItems());
+	}
+
+
 	/**
 	 * @depends firstAlbumShouldBePlusJamaisSansElle
 	 * @test