diff --git a/application/modules/admin/controllers/MultimediaController.php b/application/modules/admin/controllers/MultimediaController.php
index 8cfcb77623915a4dbb641918dda4f9c0c44097e5..aab04669bb71c47e712178ac5f1bb32c84d32319 100644
--- a/application/modules/admin/controllers/MultimediaController.php
+++ b/application/modules/admin/controllers/MultimediaController.php
@@ -11,87 +11,121 @@
  *
  * AFI-OPAC 2.0 is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with AFI-OPAC 2.0; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301	 USA 
  */
 class Admin_MultimediaController extends ZendAfi_Controller_Action {
-		public function getRessourceDefinitions() {
-			return array(
-					'model' => array('class' => 'Class_Multimedia_Location', 'name' => 'site'),
-					'messages' => array('successful_save' => 'Site %s sauvegardé'),
-					'actions' => array('edit' => array('title' => 'Modifier un site multimédia'),
-						                 'index' => array('title' => 'Sites multimédia')),
-					'display_groups' => array('config' => array(
-							'legend' => 'Configuration',
-							'elements' => array(
-									'slot_size' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Réservation minimale (slot) *',
-													'title'=> 'en minutes',
-													'size'	=> 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits'))),
-									'max_slots' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Réservation maximale *',
-													'title' => 'en nombre de "slots"',
-													'size' => 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits'))),
-									'hold_delay_min' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Délai minimum de réservation *',
-													'title' => 'en jours, 0 autorise les réservations le jour même',
-													'size' => 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits'))),
-									'hold_delay_max' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Délai maximum de réservation *',
-													'title' => 'en jours, doit être supérieur au délai minimum',
-													'size' => 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits', new ZendAfi_Validate_FieldGreater('hold_delay_min', 'Délai minimum de réservation')))),
-									'auth_delay' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Délai de connection *',
-													'title' => 'en minutes, passé ce délai la réservation est annulée',
-													'size' => 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits'))),
-									'autohold' => array(
-											'element' => 'checkbox',
-											'options' => array(
-													'label' => 'Autoriser la réservation automatique *',
-													'title' => 'quand un abonné se connecte sur un poste non réservé, une réservation lui est attribuée',
-													'required' => true,
-													'allowEmpty' => false)),
-									'autohold_slots_max' => array(
-											'element' => 'text',
-											'options' => array(
-													'label' => 'Réservation automatique maximale *',
-													'title' => 'en nombre de "slots"',
-													'size' => 4,
-													'required' => true,
-													'allowEmpty' => false,
-													'validators' => array('digits'))),
+	public function getRessourceDefinitions() {
+		return array(
+				'model' => array('class' => 'Class_Multimedia_Location', 'name' => 'site'),
+				'messages' => array('successful_save' => 'Site %s sauvegardé'),
+				'actions' => array('edit' => array('title' => 'Modifier un site multimédia'),
+					                 'index' => array('title' => 'Sites multimédia')),
+				'display_groups' => array(
+					'config' => array(
+						'legend' => 'Réservation',
+						'elements' => array(
+							'slot_size' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Réservation minimale (slot) *',
+									'title'=> 'en minutes',
+									'size'	=> 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits'))),
+							'max_slots' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Réservation maximale *',
+									'title' => 'en nombre de "slots"',
+									'size' => 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits'))),
+							'hold_delay_min' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Délai minimum de réservation *',
+									'title' => 'en jours, 0 autorise les réservations le jour même',
+									'size' => 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits'))),
+							'hold_delay_max' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Délai maximum de réservation *',
+									'title' => 'en jours, doit être supérieur au délai minimum',
+									'size' => 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits', new ZendAfi_Validate_FieldGreater('hold_delay_min', 'Délai minimum de réservation')))),
+							'auth_delay' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Délai de connection *',
+									'title' => 'en minutes, passé ce délai la réservation est annulée',
+									'size' => 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits'))),
+							'autohold' => array(
+								'element' => 'checkbox',
+								'options' => array(
+									'label' => 'Autoriser la réservation automatique *',
+									'title' => 'quand un abonné se connecte sur un poste non réservé, une réservation lui est attribuée',
+									'required' => true,
+									'allowEmpty' => false)),
+							'autohold_slots_max' => array(
+								'element' => 'text',
+								'options' => array(
+									'label' => 'Réservation automatique maximale *',
+									'title' => 'en nombre de "slots"',
+									'size' => 4,
+									'required' => true,
+									'allowEmpty' => false,
+									'validators' => array('digits'))),
+						)),
+					'planning' => array(
+						'legend' => 'Planning',
+						'elements' => array(
+							'days' => array(
+								'element' => 'multiCheckbox',
+								'options' => array(
+									'label' => 'Jours d\'ouverture *',
+									'multioptions' => Class_Multimedia_Location::getLoader()->getPossibleDays(),
+									'separator' => '',
+								)
+							),
+							'open_hour' => array(
+								'element' => 'select',
+								'options' => array(
+									'label' => 'Heure d\'ouverture *',
+									'multioptions' => Class_Multimedia_Location::getLoader()->getPossibleHours(15),
+									'required' => true,
+								  'allowEmpty' => false,
+									'validators' => array(new Zend_Validate_Regex('/[0-9]{2}:[0-9]{2}/')),
+								)
+							),
+							'close_hour' => array(
+								'element' => 'select',
+								'options' => array(
+									'label' => 'Heure de fermeture *',
+									'title' => 'Doit être après l\'heure d\'ouverture',
+									'multioptions' => Class_Multimedia_Location::getLoader()->getPossibleHours(15),
+									'required' => true,
+								  'allowEmpty' => false,
+									'validators' => array(new Zend_Validate_Regex('/[0-9]{2}:[0-9]{2}/')),
+								)
 							)
-					))
-			);
+						)
+					)
+				));
 	}
 
 
@@ -103,14 +137,15 @@ class Admin_MultimediaController extends ZendAfi_Controller_Action {
 
 		$devices = $location->getDevices();
 		$this->view->subview = $this->view->partial('multimedia/browse.phtml',
-																								array('titre' => sprintf('Postes du site multimédia "%s"', $location->getLibelle()),
-																											'devices' => $devices));
+			                                          array('titre' => sprintf('Postes du site multimédia "%s"', $location->getLibelle()),
+																									    'devices' => $devices));
 		$this->_forward('index');
 	}
 		
 
 	protected function _postEditAction($model) {
 		$this->view->titre = 'Modification du site multimédia "' . $this->view->escape($model->getLibelle()) . '"';
+		$this->view->form->getElement('days')->setValue($model->getDaysAsArray());
 	}
 		
 
diff --git a/application/modules/opac/controllers/AbonneController.php b/application/modules/opac/controllers/AbonneController.php
index b5ebb70ef0695a1932ba945127d7bba066ca1ab1..a301644dbe8a41a07b61747ecd33b05e087da0ad 100644
--- a/application/modules/opac/controllers/AbonneController.php
+++ b/application/modules/opac/controllers/AbonneController.php
@@ -565,6 +565,12 @@ class AbonneController extends Zend_Controller_Action {
 
 		$this->view->minDate = $location->getMinDate();
 		$this->view->maxDate = $location->getMaxDate();
+		$this->view->beforeShowDay = '
+		var result = [true, \'\'];
+		if (-1 == $.inArray(date.getDay(), [' . $location->getDays() . '])) {
+			result[0] = false;
+		}
+	  return result;';
 		$this->view->timelineActions = $this->_getTimelineActions('day');
 	}
 
@@ -586,14 +592,21 @@ class AbonneController extends Zend_Controller_Action {
 			$start = $holdLoader->getTimeFromDayAndTime($bean->day, $this->_getParam('time'));
 			$end = $holdLoader->getTimeFromStartAndDuration($start, $this->_getParam('duration'));
 
-			if (0 == $holdLoader->countBetweenTimesForUser($start, $end, $this->_user)) {
+			if (0 < $holdLoader->countBetweenTimesForUser($start, $end, $this->_user)) {
+				$this->view->error = $this->view->_('Vous avez déjà une réservation dans ce créneau horaire');
+			}
+
+			if ($start < $location->getMinTimeForDate($bean->day)
+				|| $end > $location->getMaxTimeForDate($bean->day)) {
+				$this->view->error = $this->view->_('Ce créneau n\'est pas dans les heures d\'ouverture.');
+			}
+
+			if (!$this->view->error) {
 				$bean->time = $this->_getParam('time');
 				$bean->duration = (int)$this->_getParam('duration');
 				$this->_redirect('/abonne/multimedia-hold-device');
 				return;
 			}
-
-			$this->view->error = $this->view->_('Vous avez déjà une réservation dans ce créneau horaire');
 		}
 		
 		$this->view->timelineActions = $this->_getTimelineActions('hours');
diff --git a/application/modules/opac/views/scripts/abonne/multimedia-hold-day.phtml b/application/modules/opac/views/scripts/abonne/multimedia-hold-day.phtml
index 0035f08de9eae78ce952f6efef21fb56ce6de54c..66d7a14d1c5634ed2f50c4b33458927b58eb97fb 100644
--- a/application/modules/opac/views/scripts/abonne/multimedia-hold-day.phtml
+++ b/application/modules/opac/views/scripts/abonne/multimedia-hold-day.phtml
@@ -10,7 +10,8 @@ Class_ScriptLoader::getInstance()
 										  {onSelect: function (dateText, inst){location.href = location.href + "/day/" + dateText;},
 										   dateFormat: "yy-mm-dd",
 											 minDate: "' . $this->minDate . '",
-											 maxDate: "' . $this->maxDate . '"}
+											 maxDate: "' . $this->maxDate . '",
+											 beforeShowDay: function(date){' . $this->beforeShowDay . '}}
 										);');
 ?>
 <div id="hold-day" class="calendar"></div>
diff --git a/library/Class/Multimedia/Location.php b/library/Class/Multimedia/Location.php
index 09b62dff26ac4d4dc71d00e3f10a5a5e17ce7130..9dd847a39a902cd217dbb280c559bd7edc9c333d 100644
--- a/library/Class/Multimedia/Location.php
+++ b/library/Class/Multimedia/Location.php
@@ -20,6 +20,44 @@
  */
 
 class Multimedia_LocationLoader extends Storm_Model_Loader {
+	/**
+	 * @return array
+	 */
+	public function getPossibleDays() {
+		$days = array();
+		$day = strtotime('next monday');
+		for ($i = 0; $i < 7; ++$i) {
+			$days[strftime('%w', $day)] = strftime('%A', $day);
+			$day = strtotime('+1 day', $day);
+		}
+		return $days;
+	}
+
+
+	/**
+	 * @param $increment int
+	 * @return array
+	 */
+	public function getPossibleHours($increment, $from = null, $to = null) {
+		if (0 == $increment)
+			return array();
+
+		if (null == $from)
+			$from = strtotime('today');
+
+		if (null == $to)
+			$to = strtotime('tomorrow');
+
+		$steps = range($from, $to, 60 * $increment);
+
+		$hours = array();
+		foreach ($steps as $step)
+			$hours[date('H:i', $step)] = date('H\hi', $step);
+
+		return $hours;
+	}
+
+
 	/**
 	 * @param $json_model stdClass
 	 * @return Class_Multimedia_Location
@@ -53,21 +91,30 @@ class Class_Multimedia_Location extends Storm_Model_Abstract {
 	 * @return array
 	 */
 	public function getStartTimesForDate($date) {
-		if (0 == $this->getSlotSize())
-			return array();
-
-		$steps = range(strtotime('today'),
-			             strtotime('tomorrow'),
-			             60 * $this->getSlotSize());
+		return $this->getLoader()->getPossibleHours($this->getSlotSize(),
+			                                          $this->getMinTimeForDate($date),
+			                                          $this->getMaxTimeForDate($date));
+	}
 
-		$start_times = array();
-		foreach ($steps as $step)
-			$start_times[date('H:i', $step)] = date('H\hi', $step);
 
-		return $start_times;
+	/**
+	 * @param $date string (YYYY-MM-DD)
+	 * @return int
+	 */
+	public function getMinTimeForDate($date) {
+		return strtotime($date . ' ' . $this->getOpenHour() . ':00');
 	}
 
 
+	/**
+	 * @param $date string (YYYY-MM-DD)
+	 * @return int
+	 */
+	public function getMaxTimeForDate($date) {
+		return strtotime($date . ' ' . $this->getCloseHour() . ':00');
+	}
+	
+
 	/** @return array */
 	public function getDurations() {
 		if (0 == $this->getSlotSize())
@@ -119,6 +166,20 @@ class Class_Multimedia_Location extends Storm_Model_Abstract {
 	}
 
 
+	/**
+	 * @return array
+	 */
+	public function getDaysAsArray() {
+		return explode(',', $this->getDays());
+	}
+
+		
+	public function beforeSave() {
+		if (is_array($days = $this->getDays()))
+			$this->setDays(implode(',', $days));
+	}
+
+
 	/**
    * @param $duration int in minutes
 	 * @return string
diff --git a/library/ZendAfi/Controller/Action.php b/library/ZendAfi/Controller/Action.php
index b5cf2c93a08a7c03bed68c4c1ccaf6b1d9028a26..a32f5f36c8a1f39e001a3f402c9453951d89711f 100644
--- a/library/ZendAfi/Controller/Action.php
+++ b/library/ZendAfi/Controller/Action.php
@@ -87,8 +87,9 @@ class ZendAfi_Controller_Action extends Zend_Controller_Action {
 		$this->view->form = $form;
 
 		if ($this->_request->isPost() && $form->isValid($this->_request->getPost())) {
+			$values = $form->getValues();
 			return $model
-				->updateAttributes($this->_request->getPost())
+				->updateAttributes($values)
 				->save();
 		}
 		return false;
@@ -114,10 +115,6 @@ class ZendAfi_Controller_Action extends Zend_Controller_Action {
 	 * Hook appelé en fin d'action d'édition
 	 * @param $model Storm_Model_Abstract
 	 */
-	protected function _postEditAction($model) {
-
-	}
+	protected function _postEditAction($model) {}
 }
-
-
 ?>
\ No newline at end of file
diff --git a/tests/application/modules/admin/controllers/MultimediaControllerTest.php b/tests/application/modules/admin/controllers/MultimediaControllerTest.php
index 7a2c92bcb570677d9846cb28caf5ac7ca01675c1..dcd8f8c6fe58ca5e21afd146f98218cf9622bd42 100644
--- a/tests/application/modules/admin/controllers/MultimediaControllerTest.php
+++ b/tests/application/modules/admin/controllers/MultimediaControllerTest.php
@@ -75,7 +75,8 @@ class Admin_MultimediaControllerEditTest extends Admin_AbstractControllerTestCas
 		Class_Multimedia_Location::getLoader()->newInstanceWithId(33)
 				->setLibelle('Antibe')
 				->setSlotSize(15)
-				->setMaxSlots(4);
+				->setMaxSlots(4)
+				->setDays('3,4');
 				
 		$this->dispatch('/admin/multimedia/edit/id/33', true);
 	}
@@ -127,6 +128,18 @@ class Admin_MultimediaControllerEditTest extends Admin_AbstractControllerTestCas
 	public function autoHoldMaxSlotsInputShouldBePresent() {
 		$this->assertXPath('//input[@name="autohold_slots_max"]');
 	}
+
+
+	/** @test */
+	public function openHourShouldBePresent() {
+		$this->assertXPath('//select[@name="open_hour"]');
+	}
+
+
+	/** @test */
+	public function closeHourShouldBePresent() {
+		$this->assertXPath('//select[@name="close_hour"]');
+	}
 }
 
 
diff --git a/tests/application/modules/opac/controllers/AbonneControllerMultimediaTest.php b/tests/application/modules/opac/controllers/AbonneControllerMultimediaTest.php
index 7e5cb356331cce36fe3401ce243f07df47f17225..08fb4ca18d9d4cc4e5599540157745f38964c989 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerMultimediaTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerMultimediaTest.php
@@ -249,7 +249,10 @@ abstract class AbonneControllerMultimediaHoldTestCase extends AbstractController
 				->setSlotSize(30)
 				->setMaxSlots(4)
 				->setHoldDelayMin(0)
-				->setHoldDelayMax(60);
+				->setHoldDelayMax(60)
+				->setDays('3,4')
+				->setOpenHour('08:30')
+				->setCloseHour('17:45');
 	}
 
 
@@ -399,7 +402,7 @@ class AbonneControllerMultimediaHoldHoursTest extends AbonneControllerMultimedia
 
 	/** @test */
 	public function listOfStartTimesShouldBePresent() {
-		$this->assertXPathCount('//select[@id="time"]/option', 48);
+		$this->assertXPathCount('//select[@id="time"]/option', 19);
 	}