diff --git a/VERSIONS_WIP/51538 b/VERSIONS_WIP/51538
new file mode 100644
index 0000000000000000000000000000000000000000..324c170bdfbab59cf366e3a77506271910a988b0
--- /dev/null
+++ b/VERSIONS_WIP/51538
@@ -0,0 +1 @@
+ - ticket #51538 : Administration : Ajout de la possibilité de spécifier les jours de lancement des batchs
\ No newline at end of file
diff --git a/application/modules/admin/controllers/BatchController.php b/application/modules/admin/controllers/BatchController.php
index d51f363ebfc604184d3383fe2aef0593283ae16f..fc774d80779c828e4f82c96667e3fa075a578e3d 100644
--- a/application/modules/admin/controllers/BatchController.php
+++ b/application/modules/admin/controllers/BatchController.php
@@ -23,20 +23,89 @@ class Admin_BatchController extends ZendAfi_Controller_Action {
 
   public function getPlugins() {
     return ['ZendAfi_Controller_Plugin_ResourceDefinition_Batch',
-            'ZendAfi_Controller_Plugin_Manager_Manager'];
+            'ZendAfi_Controller_Plugin_Manager_Batch'];
+  }
+
+
+  public function indexAction() {
+    parent::indexAction();
+    $this->view->definitions = Class_Batch::getAvailableBatchDefinitions();
+  }
+
+
+  public function activateAction() {
+    if ((!$type = $this->_getParam('id'))
+        || !Class_Batch::isAvailableType($type))
+      return $this->_redirectToIndex();
+
+    Class_Batch::newInstance(['type' => $type])
+      ->save();
+
+    $this->_helper->notify('Tâche activée');
+    $this->_redirectToIndex();
+  }
+
+
+  public function deleteAction() {
+    if ((!$type = $this->_getParam('id'))
+        || (!$batch = Class_Batch::findFirstBy(['type' => $type]))
+        || !$batch->isDeletable())
+      return $this->_redirectToIndex();
+
+    $batch->delete();
+
+    $this->_helper->notify('Tâche désactivée');
+    $this->_redirectToIndex();
+  }
+
+
+  public function planAction() {
+    if (!Class_Users::isCurrentUserSuperAdmin()
+        || (!$type = $this->_getParam('id'))
+        || !$batch = Class_Batch::findFirstBy(['type' => $type]))
+      return $this->_redirectToIndex();
+
+    $this->view->titre = $this->_('Planifier la tâche "%s"', $batch->getLibelle());
+    $form = (new ZendAfi_Form_Admin_Batch())
+      ->setAction($this->view->url(['module' => 'admin',
+                                    'controller' => 'batch',
+                                    'action' => 'plan',
+                                    'id' => $type],
+                                   null, true));
+    $form->populate($batch->getRawAttributes());
+    $this->view->form = $form;
+
+    if (!$this->_request->isPost()
+        || !$form->isValid($this->_request->getPost()))
+      return;
+
+    $batch->setPickDay($form->getValue('pick_day'))
+          ->save();
+
+    $this->_helper->notify('Planification de la tâche modifiée');
+    $this->_redirectClose('/admin/batch');
   }
 
 
   public function runAction() {
-    Class_Batch::find($this->_getParam('id'))->run();
+    if ((!$batch = Class_Batch::findFirstBy(['type' => $this->_getParam('id')]))
+        || !$batch->isManuallyRunnable())
+      return $this->_redirectToIndex();
+
+    $batch->run();
+
     $this->_helper->notify($this->_('Tâche executée'));
-    $this->_redirect('/admin/batch');
+    $this->_redirectToIndex();
   }
 
 
   public function runAjaxAction() {
-    $batch = Class_Batch::find($this->_getParam('id'));
-    $this->view->titre = $this->view->_('Exécution du traitement "%s"', $batch->getLibelle());
+    if ((!$batch = Class_Batch::findFirstBy(['type' => $this->_getParam('id')]))
+        || !$batch->isManuallyRunnable())
+      return $this->_redirectToIndex();
+
+    $this->view->titre = $this->view->_('Exécution du traitement "%s"',
+                                        $batch->getLibelle());
     $this->view->batch = $batch;
   }
 
@@ -47,5 +116,3 @@ class Admin_BatchController extends ZendAfi_Controller_Action {
       ->runStep($this->_request->getParams()));
   }
 }
-
-?>
\ No newline at end of file
diff --git a/application/modules/admin/views/scripts/batch/add.phtml b/application/modules/admin/views/scripts/batch/add.phtml
deleted file mode 100644
index dc46f2831c7f803cf1fe92106a4a72f2e9d8c066..0000000000000000000000000000000000000000
--- a/application/modules/admin/views/scripts/batch/add.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?php echo $this->renderForm($this->form); ?>
\ No newline at end of file
diff --git a/application/modules/admin/views/scripts/batch/edit.phtml b/application/modules/admin/views/scripts/batch/edit.phtml
deleted file mode 100644
index dc46f2831c7f803cf1fe92106a4a72f2e9d8c066..0000000000000000000000000000000000000000
--- a/application/modules/admin/views/scripts/batch/edit.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?php echo $this->renderForm($this->form); ?>
\ No newline at end of file
diff --git a/application/modules/admin/views/scripts/batch/index.phtml b/application/modules/admin/views/scripts/batch/index.phtml
index 827623b90f929a01db9c0cb3cb413c1136d47289..6bc950081245e673621100acbb82f313c88f21b0 100644
--- a/application/modules/admin/views/scripts/batch/index.phtml
+++ b/application/modules/admin/views/scripts/batch/index.phtml
@@ -1,40 +1,17 @@
 <?php
-echo $this->Button_New((new Class_Entity())
-                       ->setText($this->_('Ajouter une tâche')));
-
-$id_placeholder = 'MODEL_ID';
-
-$delete_url = $this->url(['action' => 'delete',
-                          'id' => $id_placeholder]);
-
-$run_url = $this->url(['action' => 'run',
-                       'id' => $id_placeholder]);
-
-$run_ajax_url = $this->url(['action' => 'run-ajax',
-                            'id' => $id_placeholder]);
-
-echo $this->tagModelTable(
-  $this->batchs,
-  [$this->_('Libelle'), $this->_('Dernière exécution')],
-  ['Libelle', 'last_run'],
-  [
-    function($batch) use ($id_placeholder, $delete_url) {
-      if(!$batch->isDeletable())
-        return '';
-
-      return $this->tagAnchor(str_replace($id_placeholder, $batch->getId(), $delete_url),
-                              $this->boutonIco('type=del'));
-    },
-
-    function($batch) use ($id_placeholder, $run_url, $run_ajax_url) {
-      if(!$batch->isManuallyRunnable())
-        return '';
-
-      $url = $batch->isAjaxRunnable() ? $run_ajax_url : $run_url;
-
-      return $this->tagAnchor(str_replace($id_placeholder, $batch->getId(), $url),
-                              $this->boutonIco('type=test', 'bulle=Lancer'));
-    }
-  ],
-  'batchs');
-?>
+$description = (new Class_TableDescription('batchs'))
+  ->addColumn($this->_('Libellé'), function($model) { return $model->getLabel(); })
+  ->addColumn($this->_('Planification'),
+              function($model)
+              {
+                return (new Class_Repeat_WeekDays())->humanReadable($model->getPickDay());
+              })
+  ->addColumn($this->_('Dernière exécution'), function($model) { return $model->getLastRun(); })
+  ->addRowAction(function($batch)
+                 {
+                   return $this->renderPluginsActions($batch);
+                 })
+  ;
+
+echo $this->renderTable($description, $this->definitions, ['sorter' => true])
+  ;
diff --git a/application/modules/admin/views/scripts/batch/plan.phtml b/application/modules/admin/views/scripts/batch/plan.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c52ca489f905555642d9f8210fc3130ba4abfdcd
--- /dev/null
+++ b/application/modules/admin/views/scripts/batch/plan.phtml
@@ -0,0 +1 @@
+<?php echo $this->renderForm($this->form); ?>
diff --git a/cosmogramme/sql/patch/patch_335.php b/cosmogramme/sql/patch/patch_335.php
new file mode 100644
index 0000000000000000000000000000000000000000..12fae2847321c1efe7d84f2e782a1b1fcb823f48
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_335.php
@@ -0,0 +1,13 @@
+<?php
+$adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
+$week_days = new Class_Repeat_WeekDays();
+
+try {
+  $adapter->query('select pick_day from batchs limit 1');
+} catch (Exception $e) {
+  $adapter->query('ALTER TABLE `batchs` ADD COLUMN `pick_day` VARCHAR(255) NOT NULL DEFAULT "' . $week_days->allDaysSerialized() . '";');
+  $adapter->query('update `batchs` set `pick_day`="' . $week_days->saturdaySerialized() . '" where type="' . Class_Batch_ArteVOD::TYPE . '";');
+  $adapter->query('update `batchs` set `pick_day`="' . $week_days->sundaySerialized() . '" where type="' . Class_Batch_Cyberlibris::TYPE . '";');
+  $adapter->query('update `batchs` set `pick_day`="' . $week_days->sundaySerialized() . '" where type="' . Class_Batch_Jamendo::TYPE . '";');
+}
+?>
\ No newline at end of file
diff --git a/library/Class/Batch.php b/library/Class/Batch.php
index e5d7f861b7328ca79f2e68f364e1a5a15ae7ce64..71ebf92bd7d8ed36464f43457f589a0510b097a8 100644
--- a/library/Class/Batch.php
+++ b/library/Class/Batch.php
@@ -20,7 +20,6 @@
  */
 
 class Class_BatchLoader extends Storm_Model_Loader {
-
   public function findAllWithDefaults($params = []) {
     if(! Class_Batch::findFirstBy(['type' => Class_Batch_NoveltyFacet::TYPE]))
       Class_Batch::newInstance(['type' => Class_Batch_NoveltyFacet::TYPE])->save();
@@ -65,7 +64,10 @@ class Class_BatchLoader extends Storm_Model_Loader {
 
 
   public function getKnownType($type) {
-    return Class_Batch::getKnownTypes()[$type];
+    $known_types = Class_Batch::getKnownTypes();
+    return array_key_exists($type, $known_types)
+      ? $known_types[$type]
+      : null;
   }
 
 
@@ -91,7 +93,9 @@ class Class_BatchLoader extends Storm_Model_Loader {
 
 
   public function getBatchLibelle($type) {
-    return Class_Batch::getKnownType($type)->getLabel();
+    return ($model = Class_Batch::getKnownType($type))
+      ? $model->getLabel()
+      : '';
   }
 
 
@@ -105,15 +109,65 @@ class Class_BatchLoader extends Storm_Model_Loader {
     return $result;
   }
 
+
+  public function isAvailableType($type) {
+    return array_key_exists($type, $this->getAvailableType());
+  }
+
+
+  public function getAvailableBatchDefinitions() {
+    $result = [];
+    $types = Class_Batch::getKnownTypes();
+    foreach($types as $type => $batch) {
+      if ($batch->isEnabled())
+        $result[$type] = new Class_Batch_Definition($batch);
+    }
+
+    return $result;
+  }
+
+
+  public function getDefaultPickDayFor($type) {
+    $week_days = new Class_Repeat_WeekDays();
+
+    if (Class_Batch_ArteVOD::TYPE == $type)
+      return $week_days->saturdaySerialized();
+
+    return in_array($type, [Class_Batch_Cyberlibris::TYPE,
+                            Class_Batch_Jamendo::TYPE])
+      ? $week_days->sundaySerialized()
+      : $week_days->allDaysSerialized();
+
+  }
 }
 
 
+
+
 class Class_Batch extends Storm_Model_Abstract {
+  use Trait_TimeSource;
+
   protected $_table_name = 'batchs';
   protected $_loader_class = 'Class_BatchLoader';
   protected $_default_attribute_values = ['type'=> '',
+                                          'pick_day' => '',
                                           'last_run' => ''];
 
+  public function beforeSave() {
+    $this->_ensureDefaultPickDay();
+  }
+
+
+  protected function _ensureDefaultPickDay() {
+    if (!$this->isNew())
+      return;
+
+    if (!$this->getPickDay()) {
+      $pick_day = $this->getLoader()->getDefaultPickDayFor($this->getType());
+      $this->setPickDay($pick_day);
+    }
+  }
+
 
   public function getLibelle() {
     return $this->withBatchDo(function($batch) { return $batch->getLabel(); },
@@ -166,7 +220,10 @@ class Class_Batch extends Storm_Model_Abstract {
 
 
   public function isManuallyRunnable() {
-    return $this->getType() != Class_Batch_Cyberlibris::TYPE;
+    return !in_array($this->getType(),
+                     [Class_Batch_Cyberlibris::TYPE,
+                      Class_Batch_ArteVOD::TYPE,
+                      Class_Batch_Jamendo::TYPE]);
   }
 
 
@@ -176,4 +233,21 @@ class Class_Batch extends Storm_Model_Abstract {
                      Class_Batch_AutocompleteRecordAuthor::TYPE,
                      Class_Batch_IndexRessourcesNumeriques::TYPE]);
   }
+
+
+  public function setPickDay($value) {
+    if (is_array($value))
+      $value = (new Class_Repeat_WeekDays())->serialize($value);
+
+    return parent::_set('pick_day', $value);
+  }
+
+
+  public function shouldRun() {
+    $now = $this->getCurrentTime();
+    $today = date('w', $now);
+
+    return in_array($today,
+                    (new Class_Repeat_WeekDays())->unserialize($this->getPickDay()));
+  }
 }
diff --git a/library/Class/Batch/Abstract.php b/library/Class/Batch/Abstract.php
index 32e6cb1f6f747a8065c47c1c6674fb999dd054ad..788a8d5ac15e35b4b835b261f36d3477e0ef2d03 100644
--- a/library/Class/Batch/Abstract.php
+++ b/library/Class/Batch/Abstract.php
@@ -45,6 +45,11 @@ class Class_Batch_Abstract {
 
 
   public function getModel() {
-    return Class_Batch::findFirstBy(['type' => static::TYPE]);
+    return Class_Batch::findFirstBy(['type' => $this->getType()]);
+  }
+
+
+  public function getType() {
+    return static::TYPE;
   }
 }
\ No newline at end of file
diff --git a/library/Class/Batch/Definition.php b/library/Class/Batch/Definition.php
new file mode 100644
index 0000000000000000000000000000000000000000..0a84103377e642a283d2b697949214e15eae9b34
--- /dev/null
+++ b/library/Class/Batch/Definition.php
@@ -0,0 +1,75 @@
+<?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 Class_Batch_Definition {
+  use Trait_Translator;
+
+  protected
+    $_type,
+    $_model;
+
+  public function __construct($type) {
+    $this->_type = $type;
+    $this->_model = $type->getModel();
+  }
+
+
+  public function __call($name, $params) {
+    $map = ['getPickDay' => '',
+            'isDeletable' => false,
+            'isManuallyRunnable' => false,
+            'isAjaxRunnable' => false];
+
+    if (array_key_exists($name, $map))
+      return $this->_model
+        ? call_user_func_array([$this->_model, $name], $params)
+        : $map[$name];
+
+    throw new RuntimeException('Call to undefined method '. get_class($this) . '::' . $name);
+  }
+
+
+  public function isActive() {
+    return null !== $this->_model;
+  }
+
+
+  public function getLabel() {
+    return $this->_type->getLabel();
+  }
+
+
+  public function getId() {
+    return $this->_type->getType();
+  }
+
+
+  public function getLastRun() {
+    if (!$this->isActive())
+      return $this->_('Aucune');
+
+    return ('0000-00-00 00:00:00' == ($last_run = $this->_model->getLastRun()))
+      ? $this->_('Aucune')
+      : $last_run;
+  }
+
+}
diff --git a/library/Class/Batch/PremierChapitre.php b/library/Class/Batch/PremierChapitre.php
index c5b151595e7c80cedd275b403f26dd52c548b53e..14a54aba38d8c947c7ed8c50558c50556b1d8da0 100644
--- a/library/Class/Batch/PremierChapitre.php
+++ b/library/Class/Batch/PremierChapitre.php
@@ -40,7 +40,7 @@ class Class_Batch_PremierChapitre extends Class_Batch_Abstract {
 
     $contenu = date('H:i:s')." ".$this->_('Le référentiel a bien été mise à jour')."\n";
     if (!$data = $pc_ws->getDatafile()) {
-      $this->content = $contenu . 
+      $this->content = $contenu .
                           $this->_('Une erreur est survenue')."\n".
                           $this->_('le référentiel n\'a pas pu être téléchargé')."\n".
                           $this->_('Veuillez réessayer ultérieurement')."\n";
@@ -86,7 +86,12 @@ class Class_Batch_PremierChapitre extends Class_Batch_Abstract {
                     '* '.$this->_plural($data['total'],'aucune oeuvre n\'a été traitée','%d oeuvre a été traitée','%d oeuvres ont été traitées',$data['total'])."\n";
     if ($data['add']) $contenu .= '* '.$this->_plural($data['add'],'','%d a été ajoutée','%d ont été ajoutées',$data['add'])."\n";
     if ($data['del']) $contenu .= '* '.$this->_plural($data['del'],'','%d a été supprimée','%d ont été supprimées',$data['del'])."\n";
-       
+
     $this->content = $contenu;
   }
+
+
+  public function isEnabled() {
+    return Class_AdminVar::isPremierChapitreEnabled();
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/PhaseBatchs.php b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
index 4386ec6685d8d75be0ad75446de11625ed083e1f..e59cc2b5b251523c0b4df432cb7d04ee12120448 100644
--- a/library/Class/Cosmogramme/Integration/PhaseBatchs.php
+++ b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
@@ -60,6 +60,13 @@ class Class_Cosmogramme_Integration_PhaseBatchs
 
 
   protected function _runOne($batch) {
+    if (!$batch->shouldRun()) {
+      $this->_log->success($this->_('La tâche %s n\'est pas plannifiée aujourd\'hui',
+                                    $batch->getLibelle()));
+      $this->_chrono->startOnFile();
+      return;
+    }
+
     $this->_log->success($batch->getLibelle());
     $this->_setData('pointeur_reprise', $batch->getId());
 
@@ -70,7 +77,7 @@ class Class_Cosmogramme_Integration_PhaseBatchs
 
     } catch (Exception $e) {
       $this->_log->error($this->_('Erreur lors de l\'execution du batch %s',
-                                     $batch->getLibelle()));
+                                  $batch->getLibelle()));
       $this->_log->error($e->getMessage());
       $this->_log->error($e->getTraceAsString());
     }
diff --git a/library/Class/DigitalResource/Batch.php b/library/Class/DigitalResource/Batch.php
index 698e5885f70f5f7d9e344d78725edc5f5bf91d1e..341777fb34e20789a335a3cddd2089cd3ca41a3b 100644
--- a/library/Class/DigitalResource/Batch.php
+++ b/library/Class/DigitalResource/Batch.php
@@ -37,4 +37,9 @@ class Class_DigitalResource_Batch extends Class_Batch_RessourceNumerique{
   public function isEnabled() {
     return $this->_config->isEnabled();
   }
-}
+
+
+  public function getType() {
+    return get_class($this);
+  }
+}
\ No newline at end of file
diff --git a/library/Class/Repeat/WeekDays.php b/library/Class/Repeat/WeekDays.php
new file mode 100644
index 0000000000000000000000000000000000000000..db54e22796959f730a2ab2b615f42c003c7e67ad
--- /dev/null
+++ b/library/Class/Repeat/WeekDays.php
@@ -0,0 +1,94 @@
+<?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 Class_Repeat_WeekDays {
+  use Trait_Translator;
+
+  const SEPARATOR = ';';
+
+  protected $_days;
+
+  public function __construct() {
+    $this->_days = ['1' => $this->_('lundi'),
+                    '2' => $this->_('mardi'),
+                    '3' => $this->_('mercredi'),
+                    '4' => $this->_('jeudi'),
+                    '5' => $this->_('vendredi'),
+                    '6' => $this->_('samedi'),
+                    '0' => $this->_('dimanche')];
+  }
+
+
+  public function allDaysSerialized() {
+    return implode(static::SEPARATOR, array_keys($this->_days));
+  }
+
+
+  public function saturdaySerialized() {
+    return '6';
+  }
+
+
+  public function sundaySerialized() {
+    return '0';
+  }
+
+
+  public function allDays() {
+    return $this->_days;
+  }
+
+
+  public function unserialize($value) {
+    $values = explode(static::SEPARATOR, $value);
+    return array_filter($values,
+                        function($item)
+                        {
+                          return $item !== null && $item !== '';
+                        });
+  }
+
+
+  public function serialize($value) {
+    return implode(static::SEPARATOR, $value);
+  }
+
+
+  public function humanReadable($value) {
+    $values = $this->unserialize($value);
+
+    if (!$values)
+      return $this->_('Aucune');
+
+    if (count($values) == count($this->_days))
+      return $this->_('Tous les jours');
+
+    $days = [];
+    foreach($this->_days as $k => $v) {
+      if (in_array($k, $values))
+        $days[] = substr($v, 0, 3);
+      continue;
+    }
+
+    return implode(', ', $days);
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/Acl/AdminControllerRoles.php b/library/ZendAfi/Acl/AdminControllerRoles.php
index 6913a8aa1dda39ff7f898ab70e8cf11cd2697c9d..8b7b1921877fb6b33d2e03bb54938ead62c03a5e 100644
--- a/library/ZendAfi/Acl/AdminControllerRoles.php
+++ b/library/ZendAfi/Acl/AdminControllerRoles.php
@@ -90,6 +90,7 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->add(new Zend_Acl_Resource('print'));
     $this->add(new Zend_Acl_Resource('external-agendas'));
     $this->add(new Zend_Acl_Resource('systeme'));
+    $this->add(new Zend_Acl_Resource('batch'));
 
     //Roles
     $this->addRole(new Zend_Acl_Role('invite'));
@@ -159,6 +160,7 @@ class ZendAfi_Acl_AdminControllerRoles extends Zend_Acl {
     $this->deny('modo_portail','users');
     $this->deny('modo_portail','usergroup');
     $this->deny('modo_portail','systeme');
+    $this->deny('modo_portail','batch');
 
     $this->allow('modo_portail');
     $this->allow('admin_portail');
diff --git a/library/ZendAfi/Controller/Plugin/Manager/Batch.php b/library/ZendAfi/Controller/Plugin/Manager/Batch.php
new file mode 100644
index 0000000000000000000000000000000000000000..801abe1a1db8946b9cb93e7bcf309bf0f17fc560
--- /dev/null
+++ b/library/ZendAfi/Controller/Plugin/Manager/Batch.php
@@ -0,0 +1,86 @@
+<?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_Batch extends ZendAfi_Controller_Plugin_Manager_Manager {
+  public function getActions($model) {
+    return [
+            ['url' => '#',
+             'icon' => 'help',
+             'label' => $this->_('Tâche système non désactivable'),
+             'condition' => function($model)
+              {
+                return !$model->isDeletable() && $model->isActive();
+              },
+             'anchorOptions' => ['onclick' => 'return false;']],
+
+            ['url' => '/admin/batch/activate/id/%s',
+             'icon' => 'hide',
+             'label' => $this->_('Activer la tâche'),
+             'condition' => function($model) {
+                return Class_Users::isCurrentUserSuperAdmin()
+                && !$model->isActive();
+             }],
+
+            ['url' => '/admin/batch/delete/id/%s',
+             'icon' => 'show',
+             'label' => $this->_('Désactiver la tâche'),
+             'condition' => function($model)
+              {
+                return $model->isDeletable();
+              },
+             'anchorOptions' => ['onclick' => 'return confirm(\''
+                                 . str_replace(['\'', '"'], '\\\'',
+                                               $this->_('Etes-vous sur de vouloir désactiver cette tâche ?'))
+                                 . '\')']],
+
+            ['url' => '/admin/batch/plan/id/%s',
+             'icon' => 'calendar',
+             'label' => $this->_('Plannifier la tâche'),
+             'condition' => function($model) {
+                return Class_Users::isCurrentUserSuperAdmin()
+                && $model->isActive();
+             },
+             'anchorOptions' => ['data-popup' => 'true']],
+
+
+            ['url' => '/admin/batch/run/id/%s',
+             'icon' => 'test',
+             'label' => $this->_('Lancer manuellement'),
+             'condition' => function($model)
+              {
+                return $model->isManuallyRunnable() && (!$model->isAjaxRunnable());
+              }],
+
+            ['url' => '/admin/batch/run-ajax/id/%s',
+             'icon' => 'test',
+             'label' => $this->_('Lancer'),
+             'condition' => function($model)
+              {
+                return $model->isManuallyRunnable() && $model->isAjaxRunnable();
+              }]];
+  }
+
+
+  protected function _canEdit($model) {
+    return Class_Users::isCurrentUserSuperAdmin();
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Batch.php b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Batch.php
index 319f2646d50bb3888a75ba8336a727637c02f1a7..e4e223efe849f3a45cdae4ac79be40f844369f5e 100644
--- a/library/ZendAfi/Controller/Plugin/ResourceDefinition/Batch.php
+++ b/library/ZendAfi/Controller/Plugin/ResourceDefinition/Batch.php
@@ -28,10 +28,12 @@ class ZendAfi_Controller_Plugin_ResourceDefinition_Batch extends ZendAfi_Control
                         'order' => 'type',
                         'findAll' => 'findAllWithDefaults'],
 
-            'messages' => ['successful_add' => $this->_('Tâche ajoutée'),
+            'messages' => ['successful_save' => $this->_('Tâche sauvegardée'),
+                           'successful_add' => $this->_('Tâche ajoutée'),
                            'successful_delete' => $this->_('Tâche supprimée')],
 
             'actions' => ['add' => ['title' => $this->_('Nouvelle Tâche')],
+                          'edit' => ['title' => $this->_('Modifier la tâche')],
                           'index' => ['title' => $this->_('Tâches')]],
 
             'after_add' => function() {$this->_redirect('/admin/batch');},
diff --git a/library/ZendAfi/Form/Admin/Batch.php b/library/ZendAfi/Form/Admin/Batch.php
index 8bc12c09edbb6dadcddaf34a93e8194343b96bc4..3c7d6d024bf14226a40063bb104b8ae68eb4d2bf 100644
--- a/library/ZendAfi/Form/Admin/Batch.php
+++ b/library/ZendAfi/Form/Admin/Batch.php
@@ -25,12 +25,11 @@ class ZendAfi_Form_Admin_Batch extends ZendAfi_Form {
     parent::init();
 
     $this
-      ->setAttrib('data-disable-onchange', 'true')
+      ->setAttrib('id', 'batch_plan')
+      ->addElement('weekDays',
+                   'pick_day',
+                   ['label' => $this->_('Lancer tous les')]);
 
-      ->addElement('select', 'type',
-                   ['multiOptions' => Class_Batch::getAvailableType(),
-                    'required' => true])
-
-      ->addDisplayGroup(['type'], 'ajout_tache', []);
+    $this->addUniqDisplayGroup('batch');
   }
 }
diff --git a/library/ZendAfi/Form/Element/WeekDays.php b/library/ZendAfi/Form/Element/WeekDays.php
new file mode 100644
index 0000000000000000000000000000000000000000..4fbe72d00d7cc0d701e1051047598af17d923aca
--- /dev/null
+++ b/library/ZendAfi/Form/Element/WeekDays.php
@@ -0,0 +1,37 @@
+<?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_Element_WeekDays extends Zend_Form_Element_MultiCheckbox {
+  public function __construct($spec, $options=null) {
+    parent::__construct($spec, $options);
+    $this
+      ->setMultiOptions((new Class_Repeat_WeekDays())->allDays())
+      ->setSeparator(' ');
+  }
+
+
+  public function setValue($value) {
+    return is_string($value)
+      ? parent::setValue((new Class_Repeat_WeekDays())->unserialize($value))
+      : parent::setValue($value);
+  }
+}
diff --git a/library/ZendAfi/View/Helper/Admin/ContentNav.php b/library/ZendAfi/View/Helper/Admin/ContentNav.php
index a3999e2a70ba6d0a6b32c73c42309fdd54a63af1..85a7bc95df7b73aacf5144ca28ebd3ae5a08c374 100644
--- a/library/ZendAfi/View/Helper/Admin/ContentNav.php
+++ b/library/ZendAfi/View/Helper/Admin/ContentNav.php
@@ -138,7 +138,7 @@ class ZendAfi_View_Helper_Admin_ContentNav extends ZendAfi_View_Helper_BaseHelpe
                    [['cosmogramme', $this->_('Accès à Cosmogramme'), '/cosmogramme',
                      ['target' => '_blank'], $is_admin],
 
-                    ['batches', $this->_('Batchs'), '/admin/batch', [], $is_admin],
+                    ['batches', $this->_('Batchs'), '/admin/batch'],
                     ['variables', $this->_('Variables'), '/admin/index/adminvar', [], $is_admin],
 
                     ['webservice_tests', $this->_('Test des web-services'), '/admin/systeme/webservices',
diff --git a/library/digital_resources/Lekiosk/tests/LeKioskTest.php b/library/digital_resources/Lekiosk/tests/LeKioskTest.php
index a9944472cf241ed5467fdfcf4f9bba0dcee0fcf9..989189ca42c981be5f9f4c1a22fc3869d7e7b41c 100644
--- a/library/digital_resources/Lekiosk/tests/LeKioskTest.php
+++ b/library/digital_resources/Lekiosk/tests/LeKioskTest.php
@@ -454,8 +454,6 @@ class LeKioskRenderAlbumFromRecordTest extends LekioskServiceTestCase {
 
 
 
-
-
 class LekioskAdminUserGroupControllerRessourcesNumeriquesTest extends Admin_AbstractControllerTestCase {
   protected $_storm_default_to_volatile = true;
 
@@ -500,18 +498,21 @@ class LekioskAdminUserGroupControllerRessourcesNumeriquesTest extends Admin_Abst
 class LekioskBatchIndexTest extends Admin_AbstractControllerTestCase {
   protected $_storm_default_to_volatile = true;
 
-
-  public function setUp() {
-    parent::setUp();
+  /** @test */
+  public function whenActiveLekioskBatchShouldBePresent() {
     LekioskAdminVars::activate();
-    $this->dispatch('/admin/batch/add', true);
+    $this->dispatch('/admin/batch', true);
+    $this->assertXPathContentContains('//td',
+                                      'Moissonner catalogue Lekiosk');
   }
 
 
   /** @test */
-  public function lekioskBatchShouldBePresent() {
-    $this->assertXPathContentContains('//form//select//option[@value="Lekiosk_Batch"]',
-                                      'Moissonner catalogue Lekiosk');
+  public function whenNotActiveLekioskBatchShouldNotBePresent() {
+    LekioskAdminVars::deactivate();
+    $this->dispatch('/admin/batch', true);
+    $this->assertNotXPathContentContains('//td',
+                                         'Moissonner catalogue Lekiosk');
   }
 }
 
diff --git a/tests/application/modules/admin/controllers/BatchControllerTest.php b/tests/application/modules/admin/controllers/BatchControllerTest.php
index bb673bdc9c607a5ed720b9af91ea7038989daf12..3750b2bc44d7e0e0ec6cc3d797b9b7c04f3e3e83 100644
--- a/tests/application/modules/admin/controllers/BatchControllerTest.php
+++ b/tests/application/modules/admin/controllers/BatchControllerTest.php
@@ -28,27 +28,84 @@ abstract class BatchControllerTestCase extends AbstractControllerTestCase {
     $_storm_default_to_volatile = true,
     $_batch_import;
 
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN;
+  }
+
   public function setUp() {
     parent::setUp();
 
     RessourcesNumeriquesFixtures::activateTypo3();
     RessourcesNumeriquesFixtures::activateVodeclic();
-    RessourcesNumeriquesFixtures::deactivateArteVod();
+    RessourcesNumeriquesFixtures::activateArteVod();
+    RessourcesNumeriquesFixtures::activateCyberlibris();
     RessourcesNumeriquesFixtures::deactivateToutApprendre();
     RessourcesNumeriquesFixtures::deactivateNumilog();
+
     $this->_batch_import = $this->fixture('Class_Batch',
                                           ['id' => 3,
                                            'type' => 'IMPORT_TYPO3',
+                                           'pick_day' => '5;6',
                                            'last_run' => '2012-05-01 10:23:00']);
   }
 }
 
 
 
+class BatchControllerWithoutAdminAccountTest extends BatchControllerTestCase {
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::MODO_PORTAIL;
+  }
+
+
+  /** @test */
+  public function shouldBeRedirectedToOpac() {
+    $this->dispatch('/admin/batch', true);
+    $this->assertRedirectTo('/opac/index/index/id_profil/1');
+  }
+}
+
+
+
+class BatchControllerWithAdminPortalTest extends BatchControllerTestCase {
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL;
+  }
+
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/batch', true);
+  }
+
+
+  /** @test */
+  public function planLinkShouldNotBePresent() {
+    $this->assertNotXPath('//a[contains(@href, "/batch/plan/id/")]');
+  }
+}
+
+
 
 class BatchControllerWithBatchInDb extends BatchControllerTestCase {
   public function setUp() {
     parent::setUp();
+
+    $this->fixture('Class_Batch',
+                   ['id' => 4,
+                    'type' => Class_Batch_PanierUser::TYPE,
+                    'pick_day' => '1;2;3;4;5;6;0']);
+
+    $this->fixture('Class_Batch',
+                   ['id' => 5,
+                    'type' => Class_Batch_AvisNotice::TYPE,
+                    'pick_day' => '']);
+
+    $this->fixture('Class_Batch',
+                   ['id' => 6,
+                    'type' => Class_Batch_AutocompleteRecordTitle::TYPE,
+                    'pick_day' => '0']);
+
     $this->dispatch('/admin/batch', true);
   }
 
@@ -62,130 +119,182 @@ class BatchControllerWithBatchInDb extends BatchControllerTestCase {
 
   /** @test */
   public function batchNoveltyCouldNotBeDelete() {
-    $this->assertNotXPath('//a[contains(@href, "batch/delete/id/' . Class_Batch::findFirstBy(['type' => Class_Batch_NoveltyFacet::TYPE])->getId() . '")]', $this->_response->getBody());
+    $this->assertNotXPath('//a[contains(@href, "batch/delete/id/' . Class_Batch_NoveltyFacet::TYPE . '")]');
   }
 
 
   /** @test */
-  public function tableShouldContainsMoissonnageArteVod() {
-    $this->assertXPathContentContains('//tbody//tr[1]//td',
+  public function tableShouldContainsTypo3() {
+    $this->assertXPathContentContains('//tbody//td',
                                       Class_Batch::getBatchLibelle('IMPORT_TYPO3'));
   }
 
 
   /** @test */
-  public function buttonShouldLinkToAdd() {
-    $this->assertXPath('//button[contains(@onclick, "batch/add")]');
+  public function tableShouldContainsTypo3PickDay() {
+    $this->assertXPathContentContains('//tbody//td', 'ven, sam');
+  }
+
+
+  /** @test */
+  public function tableShouldContainsAllDays() {
+    $this->assertXPathContentContains('//tbody//td', 'Tous les jours');
+  }
+
+
+  /** @test */
+  public function tableShouldContainsNeverEver() {
+    $this->assertXPathContentContains('//tbody//td', 'Aucune');
+  }
+
+
+  /** @test */
+  public function tableShouldContainsOneSundayOnly() {
+    $this->assertXPathCount('//tbody//td[text()="dim"]', 1);
   }
 
 
   /** @test */
-  public function batchActionShouldDeleteMyTask() {
+  public function deleteLinkShouldBePresent() {
     $this->assertXPath('//a[contains(@href, "batch/delete")]');
   }
 
 
   /** @test */
-  public function batchActionShouldRunMyTask() {
+  public function runLinkShouldBePresent() {
     $this->assertXPath('//a[contains(@href, "batch/run")]');
   }
+
+
+  /** @test */
+  public function activateLinkShouldBePresent() {
+    $this->assertXPath('//a[contains(@href, "/batch/activate")]');
+  }
+
+
+  /** @test */
+  public function planLinkShouldBePresent() {
+    $this->assertXPath('//a[contains(@href, "batch/plan/id")]');
+  }
 }
 
 
 
 
-class BatchControllerAddTest extends BatchControllerTestCase {
-  public function setUp() {
-    parent::setUp();
-    $this->dispatch('/admin/batch/add', true);
+class BatchControllerActivateTest extends BatchControllerTestCase {
+  protected function _expectNotSave() {
+    $this->onLoaderOfModel('Class_Batch')
+         ->whenCalled('save')
+         ->willDo(function()
+                  {
+                    throw new RuntimeException('Save called on Class_Batch');
+                  });
   }
 
 
   /** @test */
-  public function selectElementBatchShouldBePresent() {
-    $this->assertXPath('//select[@name="type"]');
+  public function withoutIdShouldRedirectWithoutAdding() {
+    $this->_expectNotSave();
+    $this->dispatch('/admin/batch/activate', true);
+    $this->assertRedirectTo('/admin/batch/index');
   }
 
 
-  public function datas() {
-    return [['MOISSONNAGE_VODECLIC', 'Moissonner catalogue Vodeclic', true],
-            ['MOISSONNAGE_ARTEVOD', 'Moissonner catalogue ArteVOD', false],
-            ['MOISSONNAGE_NUMILOG', 'Moissonner catalogue Numilog', false],
-            ['MOISSONNAGE_TOUTAPPRENDRE', 'Moissonner catalogue Tout apprendre', false],
-            ['AUTOCOMPLETE_RECORD_TITLE', 'Indexer les titres de notice pour l\'autocompletion', true],
-            ['AUTOCOMPLETE_RECORD_AUTHOR', 'Indexer les auteurs de notice pour l\'autocompletion', true],
-            ['BUILD_SITE_MAP', 'Régénère le sitemap XML', true],
-            ['NOVELTY_FACET', 'Supprimer les facettes de nouveauté périmées', true],
-            ['EXTERNAL_AGENDA', 'Moissonner les agendas externes',true]];
+  /** @test */
+  public function withUnknownIdShouldRedirectWithoutAdding() {
+    $this->_expectNotSave();
+    $this->dispatch('/admin/batch/activate/id/UNKNOWN_TYPE', true);
+    $this->assertRedirectTo('/admin/batch/index');
   }
 
 
+  /** @test */
+  public function withUnavailableIdShouldRedirectWithoutAdding() {
+    $this->_expectNotSave();
+    $this->dispatch('/admin/batch/activate/id/IMPORT_TYPO3', true);
+    $this->assertRedirectTo('/admin/batch/index');
+  }
+
+
+  public function datas() {
+    return [
+            [Class_Batch_Vodeclic::TYPE, '1;2;3;4;5;6;0'],
+            [Class_Batch_ArteVOD::TYPE, '6'],
+            [Class_Batch_Cyberlibris::TYPE, '0'],
+    ];
+  }
+
   /**
    * @test
    * @dataProvider datas
    */
-  public function selectElementShouldBePresent($value, $label, $should_be_present){
-    $path = sprintf('//select[@name="type"]/option[@value="%s"][@label="%s"][not(@selected)]',
-                    $value, $label);
+  public function shouldAddWithDays($type, $days) {
+    $this->dispatch('/admin/batch/activate/id/' . $type, true);
+    $this->assertNotNull($batch = Class_Batch::findFirstBy(['type' => $type]));
+    $this->assertEquals($days, $batch->getPickDay());
+  }
+}
+
+
 
-    $should_be_present
-      ? $this->assertXPath($path, $this->_response->getBody())
-      : $this->assertNotXPath($path, $this->_response->getBody());
+class BatchControllerPlanWithoutSysadminTest extends BatchControllerTestCase {
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::ADMIN_PORTAIL;
   }
 
 
   /** @test */
-  public function submitButtonShouldNotBeDisabled() {
-    $this->assertNotXPath('//button[contains(@class, "validate")][@disabled]');
+  public function shouldRedirect() {
+    $this->dispatch('/admin/batch/plan/id/IMPORT_TYPO3', true);
+    $this->assertRedirectTo('/admin/batch/index');
   }
 }
 
 
 
-class BatchControllerAddWithNumilogAndToutApprendreTest extends BatchControllerTestCase {
+class BatchControllerPlanWithSysadminTest extends BatchControllerTestCase {
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN;
+  }
+
+
   public function setUp() {
     parent::setUp();
-    RessourcesNumeriquesFixtures::activateNumilog();
-    RessourcesNumeriquesFixtures::activateToutApprendre();
-    $this->dispatch('/admin/batch/add', true);
+    $this->dispatch('/admin/batch/plan/id/IMPORT_TYPO3', true);
   }
 
 
   /** @test */
-  public function selectElementShouldContainsMoissonnageNumilog(){
-    $this->assertXPath('//select[@name="type"]/option[@value="MOISSONNAGE_NUMILOG"][@label="Moissonner catalogue Numilog"][not(@selected)]', $this->_response->getBody());
+  public function pickDayShouldBePresent() {
+    $this->assertXPath('//input[@type="checkbox"][@name="pick_day[]"]');
   }
+}
 
 
-  /** @test */
-  public function selectElementShouldContainsMoissonnageToutApprendre(){
-    $this->assertXPath('//select[@name="type"]/option[@value="MOISSONNAGE_TOUTAPPRENDRE"][@label="Moissonner catalogue Tout Apprendre"][not(@selected)]', $this->_response->getBody());
-  }
 
-  /** @test */
-  public function selectElementShouldContainsIndexerRessourcesNumeriques(){
-    $this->assertXPath('//select[@name="type"]/option[@value="INDEX_RESSOURCES_NUMERIQUES"][@label="Indexer les ressources numériques"][not(@selected)]', $this->_response->getBody());
+class BatchControllerPlanWithSysadminPostTest extends BatchControllerTestCase {
+  protected function _loginHook($account) {
+    $account->ROLE_LEVEL = ZendAfi_Acl_AdminControllerRoles::SUPER_ADMIN;
   }
-}
-
 
 
-class BatchControllerAddPostTest extends BatchControllerTestCase {
   public function setUp() {
     parent::setUp();
-    $this->postDispatch('/admin/batch/add',
-                        ['type' => 'MOISSONNAGE_VODECLIC'], true);
+    $this->postDispatch('/admin/batch/plan/id/IMPORT_TYPO3',
+                        ['pick_day' => ['3', '6']]);
   }
 
 
   /** @test */
-  public function batchShouldBeCreated() {
-    $this->assertNotNull(Class_Batch::findFirstBy(['type' => 'MOISSONNAGE_VODECLIC']));
+  public function batchPickDayShouldBeCome3and6() {
+    $this->assertEquals('3;6',
+                        Class_Batch::findFirstBy(['type' => 'IMPORT_TYPO3'])
+                        ->getPickDay());
   }
 
 
   /** @test */
-  public function clicValiderButtonShouldRedirectToAdminBatch(){
+  public function shouldRedirectToIndex() {
     $this->assertRedirectTo('/admin/batch');
   }
 }
@@ -196,15 +305,14 @@ class BatchControllerRunMoissonnageVodeclicTest extends BatchControllerTestCase
   public function setUp() {
     parent::setUp();
 
-    $this->mock_batch = Storm_Test_ObjectWrapper::mock()
-      ->whenCalled('run')->answers(true);
+    $this->mock_batch = $this->mock()->whenCalled('run')->answers(true);
 
     $this->fixture('Class_Batch', ['id' => 6, 'type' => 'MOCKED']);
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Batch')
-      ->whenCalled('getKnownType')->with('MOCKED')
-      ->answers($this->mock_batch);
+    $this->onLoaderOfModel('Class_Batch')
+         ->whenCalled('getKnownType')->with('MOCKED')
+         ->answers($this->mock_batch);
 
-    $this->dispatch('/admin/batch/run/id/6', true);
+    $this->dispatch('/admin/batch/run/id/MOCKED', true);
   }
 
 
@@ -227,20 +335,22 @@ class BatchControllerRunMoissonnageVodeclicTest extends BatchControllerTestCase
 class BatchControllerRunAjaxAutocompleteTest extends BatchControllerTestCase {
   public function setUp() {
     parent::setUp();
-    $this->fixture('Class_Batch', ['id' => 42, 'type' => 'AUTOCOMPLETE_RECORD_TITLE']);
+    $this->fixture('Class_Batch',
+                   ['id' => 42,
+                    'type' => Class_Batch_AutocompleteRecordTitle::TYPE]);
     $this->dispatch('/admin/batch', true);
   }
 
 
   /** @test */
   public function batchActionShouldRunAjaxMyTask() {
-    $this->assertXPath('//a[contains(@href, "batch/run-ajax/id/42")]');
+    $this->assertXPath('//a[contains(@href, "batch/run-ajax/id/' . Class_Batch_AutocompleteRecordTitle::TYPE . '")]');
   }
 
 
   /** @test */
   public function batchActionShouldNotRunSimpleMyTask() {
-    $this->assertNotXPath('//a[contains(@href, "batch/run/id/42")]');
+    $this->assertNotXPath('//a[contains(@href, "batch/run/id/' . Class_Batch_AutocompleteRecordTitle::TYPE . '")]');
   }
 }
 
@@ -249,23 +359,14 @@ class BatchControllerRunAjaxAutocompleteTest extends BatchControllerTestCase {
 class BatchControllerRunMoissonnageOrpheaTest extends BatchControllerTestCase {
   protected $_web_client;
 
-
-  public function tearDown() {
-    Storm_Model_Loader::defaultToDb();
-    parent::tearDown();
-  }
-
-
   public function setUp() {
     parent::setUp();
 
-    Storm_Model_Loader::defaultToVolatile();
-    $this->_web_client = Storm_Test_ObjectWrapper::mock()
-    ->whenCalled('open_url')->answers('');
+    $this->_web_client = $this->mock()->whenCalled('open_url')->answers('');
 
     $this->batch_orphea = $this->fixture('Class_Batch',
                                          ['id' => 4,
-                                          'type' => 'MOISSONNAGE_ORPHEA',
+                                          'type' => Class_Batch_Orphea::TYPE,
                                           'last_run' => '2012-05-01 10:23:00']);
 
     Class_WebService_BibNumerique_Orphea::setDefaultHttpClient($this->_web_client);
@@ -299,7 +400,7 @@ class BatchControllerRunMoissonnageOrpheaTest extends BatchControllerTestCase {
 
     ->beStrict();
 
-    $this->dispatch('/admin/batch/run/id/4', true);
+    $this->dispatch('/admin/batch/run/id/' . Class_Batch_Orphea::TYPE, true);
   }
 
 
@@ -312,19 +413,9 @@ class BatchControllerRunMoissonnageOrpheaTest extends BatchControllerTestCase {
 
 
 class BatchControllerIndexOrpheaTest extends BatchControllerTestCase {
-
-
-  public function tearDown() {
-    Storm_Model_Loader::defaultToDb();
-    parent::tearDown();
-  }
-
-
   public function setUp() {
     parent::setUp();
 
-    Storm_Model_Loader::defaultToVolatile();
-
     $this->fixture('Class_Album',
                    ['id' => 1,
                     'titre' => 'Orphea Album',
@@ -351,8 +442,6 @@ class BatchControllerIndexWithCyberlibrisTest extends BatchControllerTestCase {
   public function setUp() {
     parent::setUp();
 
-    RessourcesNumeriquesFixtures::activateCyberlibris();
-
     $this->fixture('Class_Batch',
                    ['id' => 1001528,
                     'type' => Class_Batch_Cyberlibris::TYPE]);
@@ -369,12 +458,12 @@ class BatchControllerIndexWithCyberlibrisTest extends BatchControllerTestCase {
 
   /** @test */
   public function cyberlibrisShouldNotBeRunnable() {
-    $this->assertNotXpath('//a[contains(@href, "batch/run/id/1001528")]');
+    $this->assertNotXpath('//a[contains(@href, "batch/run/id/' . Class_Batch_Cyberlibris::TYPE . '")]');
   }
 
 
   /** @test */
   public function cyberlibrisShouldNotBeAjaxRunnable() {
-    $this->assertNotXpath('//a[contains(@href, "batch/run-ajax/id/1001528")]');
+    $this->assertNotXpath('//a[contains(@href, "batch/run-ajax/id/' . Class_Batch_Cyberlibris::TYPE . '")]');
   }
-}
\ No newline at end of file
+}
diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php
index 7a1303bbd2183a2782a3f2993414663f099deff8..ecf28c4294d7ad4df8183a7aca38c8d6d792be2e 100644
--- a/tests/db/UpgradeDBTest.php
+++ b/tests/db/UpgradeDBTest.php
@@ -177,6 +177,12 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase {
   }
 
 
+  protected function assertFieldDefault($table, $column, $default, $message='') {
+    return $this->assertField($table, $column, $default, 'Default', $message);
+  }
+
+
+
   protected function assertField($table, $column, $expected, $field, $message = '') {
     try {
       $fields = [];
@@ -1662,6 +1668,7 @@ class UpgradeDB_333_Test extends UpgradeDBTestCase {
 
 
 
+
 class UpgradeDB_334_Test extends UpgradeDBTestCase {
   public function prepare() {
     try {
@@ -1677,4 +1684,53 @@ class UpgradeDB_334_Test extends UpgradeDBTestCase {
   public function columnAutoharvestShouldBePresent() {
     $this->assertColumn('external_agenda','autoharvest');
   }
+}
+
+
+
+
+class UpgradeDB_335_Test extends UpgradeDBTestCase {
+  public function prepare() {
+    try {
+      $this->query('alter table `batchs` drop `pick_day`');
+    } catch(Exception $e) {}
+
+    foreach([Class_Batch_ArteVOD::TYPE,
+             Class_Batch_Cyberlibris::TYPE,
+             Class_Batch_Jamendo::TYPE,
+             Class_Batch_PanierUser::TYPE]
+            as $type)
+      if (!$this->fetchBatchByType($type))
+        $this->query('insert into batchs(type, last_run) values("' . $type . '", "")');
+  }
+
+
+  protected function fetchBatchByType($type) {
+    return $this->query('select * from batchs where type="' . $type . '"')
+                ->fetch();
+  }
+
+
+  /** @test */
+  public function pickDayDefaultShouldBeAllWeekDays() {
+    $this->assertFieldDefault('batchs', 'pick_day', '1;2;3;4;5;6;0');
+  }
+
+
+  public function datas() {
+    return [[Class_Batch_ArteVOD::TYPE, '6'],
+            [Class_Batch_Cyberlibris::TYPE, '0'],
+            [Class_Batch_Jamendo::TYPE, '0'],
+            [Class_Batch_PanierUser::TYPE, '1;2;3;4;5;6;0'],
+    ];
+  }
+
+  /**
+   * @test
+   * @dataProvider datas
+   */
+  public function batchShouldHaveTypedPickDay($type, $pick_day) {
+    $batch = $this->fetchBatchByType($type);
+    $this->assertEquals($pick_day, $batch['pick_day']);
+  }
 }
\ No newline at end of file
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
index 6506350642719bfbaa3db99830525f858d59cfb2..1da13472e240efd5ae2f2ddfde5590bd4bee0993 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
@@ -32,8 +32,12 @@ abstract class PhaseBatchsTestCase extends Class_Cosmogramme_Integration_PhaseTe
 
 
   protected function _prepareFixtures() {
+    $time = new TimeSourceForTest('2017-08-29');
+    Class_Batch::setTimeSource($time); // tuesday for pick_day
+
     $this->fixture('Class_Batch',
                    ['id' => 34,
+                    'pick_day' => '2',
                     'type' => 'TestingTest']);
 
     $this->_batch = $this->mock();
@@ -42,9 +46,20 @@ abstract class PhaseBatchsTestCase extends Class_Cosmogramme_Integration_PhaseTe
       ->whenCalled('run')->answers(true)
       ->whenCalled('setLogger')->answers($this->_batch);
 
+    $this->_not_runnable = $this->fixture('Class_Batch',
+                                          ['id' => 99,
+                                           'pick_day' => '3',
+                                           'type' => 'TestingNotRunnableTest']);
+
+    $this->_not_runnable_batch = $this->mock();
+    $this->_not_runnable_batch
+      ->whenCalled('getLabel')->answers('Testing Not Runnable Batch');
+
+
     $this
       ->onLoaderOfModel('Class_Batch')
-      ->whenCalled('getKnownType')->with('TestingTest')->answers($this->_batch);
+      ->whenCalled('getKnownType')->with('TestingTest')->answers($this->_batch)
+      ->whenCalled('getKnownType')->with('TestingNotRunnableTest')->answers($this->_not_runnable_batch);
   }
 
 
@@ -61,6 +76,7 @@ abstract class PhaseBatchsTestCase extends Class_Cosmogramme_Integration_PhaseTe
 
 
   public function tearDown() {
+    Class_Batch::setTimeSource(null);
     Zend_Registry::set('httpClient', $this->_registry_http_client);
     parent::tearDown();
   }
@@ -125,6 +141,12 @@ class PhaseBatchsCronRunTest extends PhaseBatchsTestCase {
   }
 
 
+  /** @test */
+  public function shouldDisplayNotRunnableBatchisNotPlanned() {
+    $this->assertLogContains('La tâche Testing Not Runnable Batch n\'est pas plannifiée aujourd\'hui');
+  }
+
+
   /**
    * @test
    * @see http://forge.afi-sa.fr/issues/28103
@@ -147,11 +169,13 @@ class PhaseBatchsCronRunWithLoggerTest extends PhaseBatchsTestCase {
   protected function _prepareFixtures() {
     $this->fixture('Class_Batch',
                    ['id' => 33,
-                    'type' => 'ThrowingBatch']);
+                    'type' => 'ThrowingBatch',
+                    'pick_day' => '1;2;3;4;5;6;0']);
 
     $this->fixture('Class_Batch',
                    ['id' => 34,
-                    'type' => 'TestingTest']);
+                    'type' => 'TestingTest',
+                    'pick_day' => '1;2;3;4;5;6;0']);
 
     $this->_batch = new Class_Cosmogramme_Integration_PhaseTestingBatch();
     $throwing = $this->mock();