diff --git a/VERSIONS_WIP/49276 b/VERSIONS_WIP/49276
new file mode 100644
index 0000000000000000000000000000000000000000..d185538a7c03513cce44bbe384f9100b74749aa3
--- /dev/null
+++ b/VERSIONS_WIP/49276
@@ -0,0 +1 @@
+ - ticket #49276 : Espace abonné : modification de l'affichage des formations
\ No newline at end of file
diff --git a/application/modules/opac/controllers/AbonneController.php b/application/modules/opac/controllers/AbonneController.php
index 05f0122b4e21658be923e3d69e6aebdbd23a6dac..b3a1d86280c351a52cebcf0176be2361bb638da2 100644
--- a/application/modules/opac/controllers/AbonneController.php
+++ b/application/modules/opac/controllers/AbonneController.php
@@ -70,7 +70,7 @@ class AbonneController extends ZendAfi_Controller_Action {
   public function inscrireSessionAction() {
     $this->_redirect('/formations');
 
-    if ((!$session = Class_SessionFormation::getLoader()->find((int)$this->_getParam('id')))
+    if ((!$session = Class_SessionFormation::find((int)$this->_getParam('id')))
         || $session->isInscriptionClosed())
       return $this->_helper->notify($this->_('L\'inscription à cette session est fermée'));
 
@@ -87,9 +87,9 @@ class AbonneController extends ZendAfi_Controller_Action {
 
 
   public function desinscrireSessionAction() {
-    if (!$session = Class_SessionFormation::getLoader()->find((int)$this->_getParam('id'))) {
+    if (!$session = Class_SessionFormation::find((int)$this->_getParam('id'))) {
       $this->_helper->notify($this->_('Session non trouvée'));
-      $this->_redirect('/formations');
+      $this->_redirectToReferer();
       return;
     }
 
@@ -102,7 +102,7 @@ class AbonneController extends ZendAfi_Controller_Action {
       (new Class_Formation_UnregistrationMail($session, $this->_user))->send();
     };
 
-    $this->_redirect('/formations');
+    $this->_redirectToReferer();
   }
 
 
diff --git a/application/modules/opac/controllers/FormationsController.php b/application/modules/opac/controllers/FormationsController.php
index 2ad6163032b50e8a7b8b8268123ca6e17f6d5c84..cf677978caf86b0f713a6a4473d91cff526aad3b 100644
--- a/application/modules/opac/controllers/FormationsController.php
+++ b/application/modules/opac/controllers/FormationsController.php
@@ -28,9 +28,8 @@ class FormationsController extends ZendAfi_Controller_Action {
 
 
   public function indexAction() {
-    $this->sessions_inscrit = [];
-    $this->view->formations_by_year = Class_Formation::indexByYear(Class_Formation::findAll());
-    $this->view->user = $this->_user;
+    $this->view->titre = $this->_('S\'inscrire à une formation');
+    $this->view->sessions = Class_SessionFormation::findAllAvailable($this->_user);
   }
 
 
@@ -47,5 +46,16 @@ class FormationsController extends ZendAfi_Controller_Action {
                          null, true);
     $this->view->session = $session;
   }
-}
-?>
\ No newline at end of file
+
+
+  public function registeredAction() {
+    $this->view->titre = $this->_('Mes inscriptions en cours');
+    $this->view->sessions = Class_SessionFormation::findAllRegistered($this->_user);
+  }
+
+
+  public function doneAction() {
+    $this->view->titre = $this->_('Mes formations suivies');
+    $this->view->sessions = Class_SessionFormation::findAllDone($this->_user);
+  }
+}
\ No newline at end of file
diff --git a/application/modules/opac/views/scripts/abonne/_formation.phtml b/application/modules/opac/views/scripts/abonne/_formation.phtml
deleted file mode 100644
index 4d6924ab2534735fc147ef97537bdf25cfb3b297..0000000000000000000000000000000000000000
--- a/application/modules/opac/views/scripts/abonne/_formation.phtml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-echo $this->renderFormation($this->formation);
-?>
diff --git a/application/modules/opac/views/scripts/formations/done.phtml b/application/modules/opac/views/scripts/formations/done.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..5792b31b0066ddf54134fc5f79d2fc1e73a481ce
--- /dev/null
+++ b/application/modules/opac/views/scripts/formations/done.phtml
@@ -0,0 +1,29 @@
+<?php
+$this->openBoite($this->titre);
+
+$details_link = $this->url(['action' => 'detail-session',
+                            'id' => null]);
+
+$current_link = $this->url();
+
+echo $this->tagModelTable(
+  $this->sessions,
+  [$this->_('Formation'),
+   $this->_('Date'),
+   $this->_('Lieu')],
+  ['libelle_formation',
+   'date_debut_texte',
+   'libelle_lieu'],
+  [function($model) use($details_link, $current_link) {
+    return $this->modelActions($model,
+                               [['url' => $details_link . '/id/%s?retour=' . $current_link,
+                                 'icon'  => 'view',
+                                 'label' => $this->_('Details de la session %s',
+                                                     $model->getLabel())]]);
+  }],
+  'done_sessions'
+);
+
+$this->closeBoite();
+
+echo $this->abonne_RetourFiche();
diff --git a/application/modules/opac/views/scripts/formations/index.phtml b/application/modules/opac/views/scripts/formations/index.phtml
index 865911adc5c220d07d66917eb976501391f710e8..c1566795908dd9c036dd79c6e1cbcb7b84783d11 100644
--- a/application/modules/opac/views/scripts/formations/index.phtml
+++ b/application/modules/opac/views/scripts/formations/index.phtml
@@ -1,20 +1,44 @@
 <?php
-echo $this->openBoite('Formations');
+echo $this->openBoite($this->titre);
 
-if ($this->user && !$this->user->hasRightSuivreFormation())
-  echo sprintf('<p class="error">%s</p>',
-               $this->_("Vous n'avez pas les droits suffisants pour vous inscrire à une formation"));
+$details_link = $this->url(['action' => 'detail-session',
+                            'id' => null]);
 
-foreach($this->formations_by_year as $year => $formations) {
-  echo '<div class="formations">';
-  echo $this->partialCycle('formations/_formation.phtml',
-                           'formation',
-                           $formations,
-                           ['first', 'second']);
-  echo '</div>';
-}
+$register_link = $this->url(['controller' => 'abonne',
+                             'action' => 'inscrire-session',
+                             'id' => null]);
 
-echo $this->closeBoite();
-?>
+$current_link = $this->url();
 
-<?php if ($this->user) echo $this->abonne_RetourFiche(); ?>
+echo $this->tagModelTable(
+  $this->sessions,
+  [$this->_('Formation'),
+   $this->_('Date'),
+   $this->_('Lieu'),
+   $this->_('Informations')],
+  ['libelle_formation',
+   'date_debut_texte',
+   'libelle_lieu',
+   'infos'],
+  [function($model) use($details_link, $register_link, $current_link) {
+    return $this->modelActions($model,
+                               [['url' => $details_link . '/id/%s?retour=' . $current_link,
+                                 'icon'  => 'view',
+                                 'label' => $this->_('Details de la session %s',
+                                                     $model->getLabel())],
+                                ['url' => $register_link . '/id/%s',
+                                 'icon'  => 'add_user',
+                                 'label' => $this->_('S\'inscrire à la session %s',
+                                                     $model->getLabel())]]
+                               );}],
+  'available_sessions',
+  null,
+  ['infos' => function($model) {
+    return $this->_('Date limite d\'inscription : %s',
+                    $model->getDateLimiteInscriptionHumanRead());
+  }]
+);
+
+$this->closeBoite();
+
+echo $this->abonne_RetourFiche();
diff --git a/application/modules/opac/views/scripts/formations/registered.phtml b/application/modules/opac/views/scripts/formations/registered.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..cedc05fb65ef486c36be93eb591b3eec5bde53a3
--- /dev/null
+++ b/application/modules/opac/views/scripts/formations/registered.phtml
@@ -0,0 +1,51 @@
+<?php
+$this->openBoite($this->titre);
+
+$details_link = $this->url(['action' => 'detail-session',
+                            'id' => null]);
+
+$unregister_link = $this->url(['controller' => 'abonne',
+                               'action' => 'desinscrire-session',
+                               'id' => null]);
+$current_link = $this->url();
+
+Class_ScriptLoader::getInstance()
+->addJQueryReady('
+$(".actions a[href*=\'desinscrire\']").click(function(event) {
+  return confirm($(this).find("img").attr("alt") + " ?");
+});
+');
+
+echo $this->tagModelTable(
+  $this->sessions,
+  [$this->_('Formation'),
+   $this->_('Date'),
+   $this->_('Lieu'),
+   $this->_('Informations')],
+  ['libelle_formation',
+   'date_debut_texte',
+   'libelle_lieu',
+   'infos'],
+  [function($model) use($details_link, $unregister_link, $current_link) {
+    return $this->modelActions($model,
+                               [['url' => $details_link . '/id/%s?retour=' . $current_link,
+                                 'icon'  => 'view',
+                                 'label' => $this->_('Details de la session %s',
+                                                     $model->getLabel())],
+
+                                ['url' => $unregister_link . '/id/%s',
+                                 'icon'  => 'delete',
+                                 'label' => $this->_('Se désinscrire de la session %s',
+                                                     $model->getLabel())]]);
+  }],
+  'registered_sessions',
+  null,
+  ['infos' => function($model) {
+    return $this->_('Date limite d\'inscription : %s',
+                    $model->getDateLimiteInscriptionHumanRead());
+  }]
+);
+
+$this->closeBoite();
+
+echo $this->abonne_RetourFiche();
diff --git a/library/Class/SessionFormation.php b/library/Class/SessionFormation.php
index cc23ef3d06ca5762257ba0437f13967633c439a4..894b15e30d1b99411e67c40cc260ed68ec480831 100644
--- a/library/Class/SessionFormation.php
+++ b/library/Class/SessionFormation.php
@@ -21,10 +21,50 @@
 
 class SessionFormationLoader extends Storm_Model_Loader {
 
+  public function findAllAvailable($user) {
+    if(!$user)
+      return [];
+
+    return (new Storm_Model_Collection(Class_SessionFormation::findAllBy(['order' => 'date_debut'])))
+      ->reject(function($session) use ($user)
+               {
+                 return in_array($session, $user->getSessionFormations());
+               })
+      ->select(function($session) use ($user)
+               {
+                 return $session->isSubscriableFor($user)
+                   && $session->isVisible();
+               })
+      ->getArrayCopy();
+  }
+
+
+  public function findAllRegistered($user) {
+    if (!$user)
+      return [];
+
+    return (new Storm_Model_Collection($user->getSessionFormations()))
+      ->reject('alreadyStarted')
+      ->getArrayCopy();
+  }
+
+
+  public function findAllDone($user) {
+    if(!$user)
+      return [];
+
+    return (new Storm_Model_Collection($user->getSessionFormations()))
+        ->select('alreadyStarted')
+        ->getArrayCopy();
+  }
+
+
   public function getAllSessionsForYear($year) {
     return Class_SessionFormation::findAllBy(['where' => 'left(date_debut, 4)="'.$year.'"',
                                               'order' => 'date_debut']);
   }
+
+
   public function getYears() {
     $sessions = Class_SessionFormation::findAllBy(['order' => 'id desc']);
     $years =  [];
@@ -35,10 +75,10 @@ class SessionFormationLoader extends Storm_Model_Loader {
     return $years;
   }
 
+
   public function getCurrentYear() {
     return self::getCurrentYear();
   }
-
 }
 
 
@@ -90,24 +130,24 @@ class Class_SessionFormation extends Storm_Model_Abstract {
     return $this->getLibelleFormation().', '.Class_Date::humanDate($this->getDateDebut(), 'd MMMM YYYY');
   }
 
+
   public function getLibelle() {
     return $this->getLabel();
   }
 
+
+  public function alreadyStarted() {
+    return strtotime($this->getDateDebut()) < strtotime($this->getTimeSource()->dateYmd());
+  }
+
   /**
    * @return bool
    */
   public function isInscriptionClosed() {
-    if (strtotime($this->getDateDebut()) < strtotime(self::getTimeSource()->dateYmd()))
-      return true;
-
-    if ($this->isAnnule())
-      return true;
-
-    if(!$this->hasDateLimiteInscription())
-      return true;
-
-    return $this->isDateSubscriptionExhausted();
+    return $this->alreadyStarted()
+      || $this->isAnnule()
+      || (!$this->hasDateLimiteInscription())
+      || $this->isDateSubscriptionExhausted();
   }
 
 
@@ -247,7 +287,7 @@ class Class_SessionFormation extends Storm_Model_Abstract {
     if($user && !$user->hasRightSuivreFormation())
       return false;
 
-    if(!$this->isValid() || $this->isFull() || $this->isAnnule() || $this->isInscriptionClosed())
+    if((!$this->isValid()) || $this->isFull() || $this->isAnnule() || $this->isInscriptionClosed())
       return false;
 
     return true;
diff --git a/library/ZendAfi/View/Helper/Abonne/Formations.php b/library/ZendAfi/View/Helper/Abonne/Formations.php
index 190a4c73968a106f5298359f27d8085d5992ca60..60766ac6627fae89ea4213dd421d2ea25b447f61 100644
--- a/library/ZendAfi/View/Helper/Abonne/Formations.php
+++ b/library/ZendAfi/View/Helper/Abonne/Formations.php
@@ -18,9 +18,11 @@
  * 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_Abonne_Formations extends ZendAfi_View_Helper_Abonne_Abstract {
   public function abonne_formations($user) {
-    if (!Class_AdminVar::isFormationEnabled() || !$user->hasRightSuivreFormation())
+    if (!Class_AdminVar::isFormationEnabled()
+        || !$user->hasRightSuivreFormation())
       return '';
 
     $action_url = $this->view->url(['controller' => 'formations',
@@ -31,25 +33,22 @@ class ZendAfi_View_Helper_Abonne_Formations extends ZendAfi_View_Helper_Abonne_A
     $html = $this->view->tagAnchor($action_url,
                                    $this->view->_("S'inscrire à une formation"));
 
-    $html .= '<ul>';
-
-
-
-    foreach ($user->getSessionFormations() as $session) {
-      $html .= sprintf('<li><a href="%s">%s, %s</li>',
-                       $this->view->url(['controller' => 'formations',
-                                         'action' => 'detail-session',
-                                         'id' => $session->getId()],
-                                        null, true)
-                       . '?retour=' . $this->view->url(),
-                       $session->getLibelleFormation(),
-                       $this->view->humanDate($session->getDateDebut(), 'd MMMM YYYY'));
-    }
-
-    $html .= '</ul>';
+    $html .= $this->_renderSubscriptions();
 
     return $this->tagFicheAbonne($html, 'formations', $action_url);
   }
-}
 
-?>
\ No newline at end of file
+
+  protected function _renderSubscriptions() {
+    return $this
+      ->_tag('ul',
+             $this->_tag('li',
+                         $this->view->tagAnchor(['controller' => 'formations',
+                                                 'action' => 'done'],
+                                                $this->_('Mes formations suivies')))
+             . $this->_tag('li',
+                           $this->view->tagAnchor(['controller' => 'formations',
+                                                   'action' => 'registered'],
+                                                  $this->_('Mes inscriptions en cours'))));
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Admin/SubscribeUsers.php b/library/ZendAfi/View/Helper/Admin/SubscribeUsers.php
index abcfa3af027e9df7136b8a900b6f1e702cbd5a13..752cd3ee36bbb12e68c15c0388e81103299e9273 100644
--- a/library/ZendAfi/View/Helper/Admin/SubscribeUsers.php
+++ b/library/ZendAfi/View/Helper/Admin/SubscribeUsers.php
@@ -99,6 +99,9 @@ class ZendAfi_View_Helper_Admin_SubscribeUsers extends ZendAfi_View_Helper_BaseH
 
 
   protected function _renderUser($user, $odd) {
+    if(!$user)
+      $user = new Class_Users();
+
     return sprintf('<tr class="%s"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',
                    $odd ? 'first' : 'second',
                    $user->getNom(),
diff --git a/public/admin/skins/bokeh74/config.json b/public/admin/skins/bokeh74/config.json
index fa1ce6497409c0fb7d48706e80c299cc97de597b..d8f18231dbb60fc18ecd6a8ca899fd54174c4bf1 100644
--- a/public/admin/skins/bokeh74/config.json
+++ b/public/admin/skins/bokeh74/config.json
@@ -80,7 +80,7 @@
     "add_user": "icons/menu/demande_inscri_24.png",
 
     "edit": "icons/actions/edit_24.png",
-    "delete": "icons/actions/delete_24.png",
+    "delete": "icons/actions/delete_16.png",
     "print": "icons/actions/print_16.png",
 
     "copy": "icons/actions/copier_16.png",
diff --git a/tests/application/modules/opac/controllers/AbonneControllerFormationsTest.php b/tests/application/modules/opac/controllers/AbonneControllerFormationsTest.php
index de283d41216d91642241ae53a4261cd7b3047dc0..80d376e551e370e9975a40dbb528ffe02cd4b3b1 100644
--- a/tests/application/modules/opac/controllers/AbonneControllerFormationsTest.php
+++ b/tests/application/modules/opac/controllers/AbonneControllerFormationsTest.php
@@ -18,7 +18,9 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-abstract class AbstractAbonneControllerFormationsTestCase extends AbstractControllerTestCase {
+abstract class AbstractAbonneControllerFormationsTestCase
+  extends AbstractControllerTestCase {
+
   protected
     $_storm_default_to_volatile = true,
     $_amadou,
@@ -94,7 +96,10 @@ abstract class AbstractAbonneControllerFormationsTestCase extends AbstractContro
                                                         'effectif_min' => 1,
                                                         'effectif_max' => 10,
                                                         'lieu' => $this->_gallice_cafe,
-                                                        'date_debut' => '2014-01-10']);
+                                                        'date_debut' => '2015-01-10',
+                                                        'date_fin' => '2015-01-10',
+                                                        'date_limite_inscription' => '2015-01-10',
+                                                        'stagiaires' => []]);
 
     $this->_session_smalltalk_juillet = $this->fixture('Class_SessionFormation',
                                                        ['id' => 12,
@@ -103,7 +108,9 @@ abstract class AbstractAbonneControllerFormationsTestCase extends AbstractContro
                                                         'effectif_max' => 10,
                                                         'lieu' => $this->_gallice_cafe,
                                                         'stagiaires' => [],
-                                                        'date_debut' => '2014-07-11']);
+                                                        'date_debut' => '2014-07-11',
+                                                        'date_fin' => '2014-07-15',
+                                                        'date_limite_inscription' => '2014-07-11']);
 
     $this->_learn_smalltalk = $this->fixture('Class_Formation',
                                              ['id' => 1,
@@ -129,16 +136,20 @@ abstract class AbstractAbonneControllerFormationsTestCase extends AbstractContro
                                                 'effectif_min' => 2,
                                                 'effectif_max' => 5,
                                                 'lieu' => $this->_gallice_cafe,
-                                                'date_debut' => '2014-03-01',
+                                                'date_debut' => '2015-03-01',
                                                 'stagiaires' => [],
-                                                'date_limite_inscription' => '2014-03-01']);
+                                                'date_limite_inscription' => '2015-03-01']);
 
     $this->_session_java_septembre = $this->fixture('Class_SessionFormation',
                                                     ['id' => 30,
                                                      'formation_id' => 3,
-                                                     'date_debut' => '2014-09-1',
+                                                     'effectif_min' => 2,
+                                                     'effectif_max' => 5,
+                                                     'date_debut' => '2014-09-10',
+                                                     'date_fin' => '2014-09-10',
                                                      'stagiaires' => [],
-                                                     'date_limit_inscription' => '2014-08-15']);
+                                                     'lieu' => $this->_gallice_cafe,
+                                                     'date_limit_inscription' => '2014-09-10']);
     $this->_session_java_septembre->beAnnule();
 
     $this->_learn_java = $this->fixture('Class_Formation',
@@ -153,6 +164,8 @@ abstract class AbstractAbonneControllerFormationsTestCase extends AbstractContro
                                                     ['id' => 121,
                                                      'formation_id' => 12,
                                                      'date_debut' => '2014-07-10',
+                                                     'date_fin' => '2014-07-14',
+                                                     'date_limit_inscription' => '2014-07-10',
                                                      'contenu' => 'Introduction a la syntaxe',
                                                      'objectif' => 'Ecrire un premier programme',
                                                      'effectif_min' => 1,
@@ -175,7 +188,7 @@ abstract class AbstractAbonneControllerFormationsTestCase extends AbstractContro
                                                                                         'nom' => 'Cerisier',
                                                                                         'prenom' => 'Christophe',
                                                                                         'mail' => 'cc@bokeh.fr'])
-                                                       ]]);
+                                                     ]]);
 
     $this->_learn_python = $this->fixture('Class_Formation',
                                           ['id' => 12,
@@ -202,13 +215,13 @@ class AbonneControllerFormationsListWithLearnJavaNotVisibleTest extends Abstract
   }
 
 
-    /** @test */
+  /** @test */
   function noH2ShouldContainsLearnJava() {
     $this->assertNotXPathContentContains('//h2', 'Learn Java');
   }
 
 
-    /** @test */
+  /** @test */
   function sessionMarsShouldNotBeVisible() {
     $this->assertNotXPathContentContains('//tbody//tr//td', '1 mars 2014');
   }
@@ -218,17 +231,16 @@ class AbonneControllerFormationsListWithLearnJavaNotVisibleTest extends Abstract
 
 
 class AbonneControllerFormationsSessionListWithLearnSmalltalkNotVisibleTest extends AbstractAbonneControllerFormationsTestCase {
-  public function setUp() {
-    parent::setUp();
 
-  }
 
   /** @test */
   public function trainingJavaShouldBeDisplayed() {
     $this->dispatch('/opac/formations', true);
-    $this->assertXPathContentContains('//h2', 'Learn Java',$this->response->getBody());
+    $this->assertXPathContentContains('//td', 'Learn Java');
   }
-    /** @test */
+
+
+  /** @test */
   function noH2ShouldContainsLearnSmalltalk() {
     $this->_learn_smalltalk->hide()->save();
     $this->dispatch('/opac/formations', true);
@@ -236,7 +248,7 @@ class AbonneControllerFormationsSessionListWithLearnSmalltalkNotVisibleTest exte
   }
 
 
-    /** @test */
+  /** @test */
   function sessionJuilletShouldNotBeVisibleIfParentTrainingIsHidden() {
     $this->_learn_smalltalk->hide()->save();
     $this->dispatch('/opac/formations', true);
@@ -244,7 +256,7 @@ class AbonneControllerFormationsSessionListWithLearnSmalltalkNotVisibleTest exte
   }
 
 
-    /** @test */
+  /** @test */
   function sessionJuilletShouldNotBeVisibleIfHidden() {
     $this->_learn_smalltalk->show()->save();
     $this->_session_smalltalk_juillet->hide()->save();
@@ -252,12 +264,13 @@ class AbonneControllerFormationsSessionListWithLearnSmalltalkNotVisibleTest exte
     $this->assertNotXPathContentContains('//tbody//tr//td', '11 juillet 2014');
   }
 
-    /** @test */
+
+  /** @test */
   function sessionJuilletShouldBeVisibleIfShow() {
     $this->_learn_smalltalk->show()->save();
     $this->_session_smalltalk_juillet->show()->save();
     $this->dispatch('/opac/formations', true);
-    $this->assertXPathContentContains('//tbody//tr//td', '11 juillet 2014');
+    $this->assertXPathContentContains('//td', '11 juillet 2014');
   }
 
 }
@@ -273,33 +286,32 @@ class AbonneControllerFormationsListTest extends AbstractAbonneControllerFormati
       ->setBarreNavOn(true)
       ->setLibelle('Mon compte')
       ->setParentProfil(
-        Class_Profil::newInstanceWithId(42,
-                                        ['cfg_modules' => ['abonne' =>  ['formations' => ['barre_nav' => 'Les formations']]]]));
+                        Class_Profil::newInstanceWithId(42,
+                                                        ['cfg_modules' => ['abonne' =>  ['formations' => ['barre_nav' => 'Les formations']]]]));
 
-    $this->dispatch('/opac/formations', true);
-  }
+    $this->_session_python_juillet
+      ->show()
+      ->assertSave();
 
-  /** @test */
-  function aH2ShouldContainsLearnJava() {
-    $this->assertXPathContentContains('//h2', 'Learn Java');
+    $this->dispatch('/opac/formations', true);
   }
 
 
   /** @test */
-  function aDivForDescriptionShouldContainsIfYouWantTo() {
-    $this->assertXPathContentContains('//div', 'whaaat ?');
+  function aTdShouldContainsLearnJava() {
+    $this->assertXPathContentContains('//td', 'Learn Java');
   }
 
 
   /** @test */
-  function aH2ShouldContainsLearnPython() {
-    $this->assertXPathContentContains('//h2', 'Learn Python');
+  function aTdShouldNotContainsLearnPythonBeCauseAmadouAlreadyRegistered() {
+    $this->assertNotXPathContentContains('//td', 'Learn Python');
   }
 
 
   /** @test */
-  function session_java_mars_ShouldNotHaveLinkForInscrireAsInscriptionClosed() {
-    $this->assertNotXPath('//a[contains(@href, "abonne/inscrire-session/id/32")]');
+  function session_java_mars_ShouldHaveLinkForInscrire() {
+    $this->assertXPath('//a[contains(@href, "abonne/inscrire-session/id/32")]');
   }
 
 
@@ -310,8 +322,8 @@ class AbonneControllerFormationsListTest extends AbstractAbonneControllerFormati
 
 
   /** @test */
-  function session_janvier_smalltalk_ShouldNotHaveLinkForInscrireAsFinished() {
-    $this->assertNotXPath('//a[contains(@href, "abonne/inscrire-session/id/11")]');
+  function session_janvier_smalltalk_ShouldHaveLinkForInscrire() {
+    $this->assertXPath('//a[contains(@href, "abonne/inscrire-session/id/11")]');
   }
 
 
@@ -322,21 +334,20 @@ class AbonneControllerFormationsListTest extends AbstractAbonneControllerFormati
 
 
   /** @test */
-  function sessionJanuary2014ShouldBeFirst() {
-    $this->assertXPathContentContains('//tbody//tr[1]//td', '10 janvier 2014');
+  function sessionJanuary2015ShouldBeFirst() {
+    $this->assertXPathContentContains('//tr[2]//td', '10 janvier 2015');
   }
 
 
-
   /** @test */
   function sessionMarsShouldBeFirst() {
-    $this->assertXPathContentContains('//tbody//tr[1]//td', '1 mars 2014');
+    $this->assertXPathContentContains('//tr[4]//td', '1 mars 2015');
   }
 
 
-    /** @test */
-  function sessionSeptemberShouldBeSecond() {
-    $this->assertXPathContentContains('//tbody//tr[2]//td', ' septembre 2014');
+  /** @test */
+  function sessionJavaSeptemberShouldNotBeVisibleBecauseItHasBeenCancel() {
+    $this->assertNotXPathContentContains('//tr//td', '10 septembre 2014');
   }
 
 
@@ -347,160 +358,243 @@ class AbonneControllerFormationsListTest extends AbstractAbonneControllerFormati
 
 
   /** @test */
-   function session10Juillet2014ShouldBeFirst() {
-     $this->assertXPathContentContains('//tbody//tr[1]//td', '10 juillet 2014');
-   }
+  function sessionPython10Juillet2014ShouldNotBePresentBecauseAlreadyRegistered() {
+    $this->assertNotXPathContentContains('//tr//td', '10 juillet 2014');
+  }
 
 
-   /** @test */
-   function session11Juillet2014ShouldSecond() {
-     $this->assertXPathContentContains('//tbody//tr[2]//td', '11 juillet 2014');
-   }
+  /** @test */
+  function session11Juillet2014ShouldBePresend() {
+    $this->assertXPathContentContains('//tr//td', '11 juillet 2014');
+  }
 
 
-   /** @test */
-   function session_fevrier_17_lieuBonlieuShouldBeDisplayed() {
-     $this->assertXPathContentContains('//tbody//tr//td', 'Bonlieu');
-   }
+  /** @test */
+  function session_fevrier_17_lieuBonlieuShouldBeDisplayed() {
+    $this->assertXPathContentContains('//tbody//tr//td', 'Bonlieu');
+  }
 
 
-   /** @test */
-   function session_fevrier_17_ShouldHaveLinkForInscrire() {
-     $this->assertXPathContentContains('//tbody//tr//a[contains(@href, "abonne/inscrire-session/id/31")]',
-                                       "S'inscrire");
-   }
+  /** @test */
+  function session_fevrier_17_ShouldHaveLinkForInscrire() {
+    $this->assertXPathContentContains('//tbody//tr//a[contains(@href, "abonne/inscrire-session/id/31")]',
+                                      "S'inscrire");
+  }
 
 
-   /** @test */
-   function session_fevrier_17_ShouldDisplayDateLimite15Fevrier() {
-     $this->assertXPathContentContains('//tbody//tr/td',
-                                       '20 janvier 2015');
-   }
+  /** @test */
+  function session_fevrier_17_ShouldDisplayDateLimite15Fevrier() {
+    $this->assertXPathContentContains('//tbody//tr/td',
+                                      '20 janvier 2015');
+  }
 
 
-   /** @test */
-   function session_fevrier_17_ShouldHaveLinkForDetailSessionFormation() {
-     $this->assertXPathContentContains('//tbody//tr//a[contains(@href, "formations/detail-session/id/31")]',
-                                       'Détails de la session');
-   }
+  /** @test */
+  function session_fevrier_17_ShouldHaveLinkForDetailSessionFormation() {
+    $this->assertXPath('//tr//a[contains(@href, "formations/detail-session/id/31")]');
+  }
 
 
-   /** @test */
-   function session_mars_27_ShouldBeDisplayedUnderLearnJavaInFirstPosition() {
-     $this->assertXPathContentContains('//tbody//tr[1]', '1 mars 2014');
-   }
+  /** @test */
+  function session_mars_27_ShouldBeDisplayed() {
+    $this->assertXPathContentContains('//tr', '1 mars 2015');
+  }
 
 
-   /** @test */
-   function session_septembre_java_ShouldBeAnnule() {
-     $this->assertXPathContentContains('//tr/td/span[@class="error"]', 'Annul');
-   }
 
+  /** @test */
+  function boiteTitleShouldBeFormations() {
+    $this->assertXPathContentContains('//h1', 'S\'inscrire à une formation');
+  }
 
-   /** @test */
-   function session_python_juillet_ShouldHaveLinkForDesinscrire() {
-     $this->assertXPathContentContains('//tr//a[contains(@href, "abonne/desinscrire-session/id/121")]',
-                                       "Se désinscrire");
-   }
 
+  /**
+   * @test
+   * @group pagetitles
+   */
+  public function barreNavShouldContainsMonCompte() {
+    $this->assertXPathContentContains('//div[@class="barre_nav"]//span//a[contains(@href, "index/index/id_profil/2")]',
+                                      'Mon compte');
+  }
 
-   /** @test */
-   function boiteTitleShouldBeFormations() {
-     $this->assertXPathContentContains('//h1', 'Formations');
-   }
 
+  /** @test */
+  public function barreNavShouldContainsAccueilThatLinksToProfilOne() {
+    $this->assertXPathContentContains('//div[@class="barre_nav"]//a[contains(@href, "index/index/id_profil/1")]',
+                                      'Accueil');
+  }
+}
 
-   /**
-    * @test
-    * @group pagetitles
-    */
-   public function barreNavShouldContainsMonCompte() {
-     $this->assertXPathContentContains('//div[@class="barre_nav"]//span//a[contains(@href, "index/index/id_profil/2")]',
-                                       'Mon compte');
-   }
 
 
-   /** @test */
-   public function barreNavShouldContainsAccueilThatLinksToProfilOne() {
-     $this->assertXPathContentContains('//div[@class="barre_nav"]//a[contains(@href, "index/index/id_profil/1")]',
-                                       'Accueil');
-   }
- }
 
+class AbonneControllerFormationsFicheAbonneTest extends AbstractAbonneControllerFormationsTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/opac/abonne/fiche?retour=/opac/abonne/fiche', true);
+  }
 
 
+  /** @test */
+  public function pageShouldContainsLinkToFormations() {
+    $this->assertXPathContentContains('//a[contains(@href, "/formations")]',
+                                      'S\'inscrire à une formation');
+  }
 
- class AbonneControllerFormationsFicheAbonneTest extends AbstractAbonneControllerFormationsTestCase {
-   public function setUp() {
-     parent::setUp();
-     $this->dispatch('/opac/abonne/fiche?retour=/opac/abonne/fiche');
-   }
 
-   /** @test */
-   public function pageShouldContainsLinkToFormations() {
-     $this->assertXPathContentContains('//a[contains(@href, "formations")]', 'S\'inscrire à une formation');
-   }
+  /** @test */
+  public function pageShouldNotContainsVousEtesInscritFormationPython() {
+    $this->assertNotXPathContentContains('//ul//li', 'Learn Python, 10 juillet 2014');
+  }
+
+
+  /** @test */
+  public function pageShouldContainsLinkToRegistrations() {
+    $this->assertXPathContentContains('//a[contains(@href, "/formations/registered")]',
+                                      'Mes inscriptions en cours');
+  }
+
+
+  /** @test */
+  public function pageShouldContainsLinkToDone() {
+    $this->assertXPathContentContains('//a[contains(@href, "/formations/done")]',
+                                      'Mes formations suivies');
+  }
+}
 
 
-   /** @test */
-   public function pageShouldContainsVousEtesInscritFormationPython() {
-     $this->assertXPathContentContains('//ul//li', 'Learn Python, 10 juillet 2014');
-   }
 
 
-   /** @test */
-   public function pageShouldContainsLinkToDetailSessionPyhton() {
-     $this->assertXPath('//li//a[contains(@href, "formations/detail-session/id/121?retour=/abonne/fiche")]',$this->_response->getBody());
-   }
- }
+class AbonneControllerFormationsRegisteredActionTest
+  extends AbstractAbonneControllerFormationsTestCase {
 
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/formations/registered', true);
+  }
 
 
+  /** @test */
+  public function titleShouldBeMesInscriptionsEnCours() {
+    $this->assertXPathContentContains('//h1', 'Mes inscriptions en cours');
+  }
 
- Class AbonneControllerFormationsFicheAbonneWithoutSufficientRigthsTest extends AbstractAbonneControllerFormationsTestCase {
-   /** @test */
-   public function whenFormationsDisabledPageShouldNotContainsLinkToFormations() {
-     Class_AdminVar::getLoader()
-       ->newInstanceWithId('FORMATIONS')
-       ->setValeur('0');
-     $this->dispatch('/opac/abonne/fiche');
-     $this->assertNotXPath('//a[contains(@href, "formations")]');
-   }
+
+  /** @test */
+  public function learnPythonShouldBePresent() {
+    $this->assertXPathContentContains('//td', 'Learn Python');
+  }
 
 
-   /** @test */
-   public function whenUserNotStagiairePageShouldNotContainsLinkToFormations() {
-     $this->_amadou->setUserGroups(array());
-     $this->dispatch('/opac/abonne/fiche');
-     $this->assertNotXPath('//a[contains(@href, "formations")]');
+  /** @test */
+  public function dateShouldBePresent() {
+    $this->assertXPathContentContains('//td', '10 juillet 2014');
+  }
+
+
+  /** @test */
+  public function locationShouldBePresent() {
+    $this->assertXPathContentContains('//td', 'Bibliothèque des romains');
+  }
+
+
+  /** @test */
+  public function limitDateShouldBePresent() {
+    $this->assertXPathContentContains('//td', 'Date limite d\'inscription');
+  }
+
+
+  /** @test */
+  public function detailLinkShouldBePresent() {
+    $this->assertXPath('//a[contains(@href, "formations/detail-session/id/121")]');
+  }
+
+
+  /** @test */
+  public function unregisterLinkShouldBePresent() {
+    $this->assertXPath('//a[contains(@href, "abonne/desinscrire-session/id/121")]');
   }
 }
 
 
 
-class AbonneControllerFormationsListWithoutRightSuivreFormationTest extends AbstractAbonneControllerFormationsTestCase {
+
+class AbonneControllerFormationsDoneActionTest
+  extends AbstractAbonneControllerFormationsTestCase {
+
   public function setUp() {
+
     parent::setUp();
-    $this->_amadou->setUserGroups([]);
-    $this->dispatch('/opac/formations');
+    $this->_session_python_juillet->setDateDebut('2006-09-09')->assertSave();
+    $this->dispatch('/formations/done', true);
   }
 
 
   /** @test */
-  function linkForInscrireShouldNotExists() {
-    $this->assertNotXPath('//a[contains(@href, "abonne/inscrire-session")]');
+  public function titleShouldBeMesInscriptionsEnCours() {
+    $this->assertXPathContentContains('//h1', 'Mes formations suivies');
+  }
+
+
+  /** @test */
+  public function learnPythonShouldBePresent() {
+    $this->assertXPathContentContains('//td', 'Learn Python');
+  }
+
+
+  /** @test */
+  public function dateShouldBePresent() {
+    $this->assertXPathContentContains('//td', '9 septembre 2006');
+  }
+
+
+  /** @test */
+  public function locationShouldBePresent() {
+    $this->assertXPathContentContains('//td', 'Bibliothèque des romains');
   }
 
 
   /** @test */
-  function linkForDesinscrireShouldExists() {
-    $this->assertXPath('//a[contains(@href, "abonne/desinscrire-session")]');
+  public function detailLinkShouldBePresent() {
+    $this->assertXPath('//a[contains(@href, "formations/detail-session/id/121")]');
   }
+}
 
 
+
+
+Class AbonneControllerFormationsFicheAbonneWithoutSufficientRigthsTest extends AbstractAbonneControllerFormationsTestCase {
   /** @test */
-  public function messageVousNavezPasLesDroitsSuffisantsShouldBeVisible() {
-    $this->assertXPathContentContains('//p', "Vous n'avez pas les droits");
+  public function whenFormationsDisabledPageShouldNotContainsLinkToFormations() {
+    Class_AdminVar::getLoader()
+      ->newInstanceWithId('FORMATIONS')
+      ->setValeur('0');
+    $this->dispatch('/opac/abonne/fiche');
+    $this->assertNotXPath('//a[contains(@href, "formations")]');
+  }
+
+
+  /** @test */
+  public function whenUserNotStagiairePageShouldNotContainsLinkToFormations() {
+    $this->_amadou->setUserGroups(array());
+    $this->dispatch('/opac/abonne/fiche');
+    $this->assertNotXPath('//a[contains(@href, "formations")]');
+  }
+}
+
+
+
+class AbonneControllerFormationsListWithoutRightSuivreFormationTest extends AbstractAbonneControllerFormationsTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->_amadou->setUserGroups([]);
+    $this->dispatch('/opac/formations');
+  }
+
+
+  /** @test */
+  function linkForInscrireShouldNotExists() {
+    $this->assertNotXPath('//a[contains(@href, "abonne/inscrire-session")]');
   }
 }
 
@@ -509,6 +603,10 @@ class AbonneControllerFormationsListWithoutRightSuivreFormationTest extends Abst
 class AbonneControllerFormationsAmadouInscritSessionMarsJavaClosedTest extends AbstractAbonneControllerFormationsTestCase {
   public function setUp() {
     parent::setUp();
+    $this->_session_java_mars
+      ->setDateDebut('2014-03-01')
+      ->setDateLimiteInscription('2014-03-01')
+      ->assertSave();
     $this->dispatch('/opac/abonne/inscrire-session/id/32');
   }
 
@@ -726,12 +824,6 @@ class AbonneControllerFormationsSessionJavaFevrierFullListTest extends AbonneCon
   function session_fevrier_17_ShouldNotHaveLinkForInscrire() {
     $this->assertNotXPath('//a[contains(@href, "abonne/inscrire-session/id/31")]');
   }
-
-
-  /** @test */
-  public function sessionShouldDisplayFull() {
-    $this->assertXPathContentContains('//tbody//tr/td/span[@class="error"]', 'Complet');
-  }
 }
 
 
@@ -741,7 +833,7 @@ class AbonneControllerFormationsSessionJavaFevrierFullAndInscritListTest extends
   public function pageShouldHaveLinkToDesinscrire() {
     $this->_session_java_fevrier->addStagiaire($this->_amadou);
     $this->_amadou->setSessionFormations(array($this->_session_java_fevrier));
-    $this->dispatch('/opac/formations');
+    $this->dispatch('/opac/formations/registered');
     $this->assertXPath('//a[contains(@href, "abonne/desinscrire-session/id/31")]');
   }
 }
@@ -792,16 +884,31 @@ class AbonneControllerFormationsInscritSessionWithoutRightSuivreFormationTest ex
 
 
 
-class AbonneControllerFormationsAmadouDesinscritSessionJuilletPythonTest extends AbstractAbonneControllerFormationsTestCase {
-  protected $_mails;
+class AbonneControllerFormationsAmadouDesinscritSessionJuilletPythonTest
+  extends AbstractAbonneControllerFormationsTestCase {
+  protected $_mails, $_previous_referer;
 
   public function setUp() {
     parent::setUp();
-    $this->dispatch('/opac/abonne/desinscrire-session/id/121', true);
+    $this->_previous_referer = isset($_SERVER['HTTP_REFERER'])
+      ? $_SERVER['HTTP_REFERER']
+      : null;
 
+    $_SERVER['HTTP_REFERER'] = '/formations';
+
+    $this->dispatch('/opac/abonne/desinscrire-session/id/121', true);
     $this->_mails = $this->_mail_transport->getSentMails();
   }
 
+
+  public function tearDown() {
+    if ($this->_previous_referer)
+      $_SERVER['HTTP_REFERER'] = $this->_previous_referer;
+
+    parent::tearDown();
+  }
+
+
   /** @test */
   function answerShouldRedirectToFormationList() {
     $this->assertRedirectTo('/formations');
@@ -991,121 +1098,43 @@ class AbonneControllerFormationsSessionJuilletPythonDetailRetourFicheTest extend
 
 
 class AbonneControllerFormationsWrongIdsTest extends AbstractAbonneControllerFormationsTestCase {
-  /** @test */
-  public function onDetailSessionShouldRedirectToFormations() {
-    $this->dispatch('/opac/formations/detail-session/id/9999');
-    $this->assertRedirectTo('/formations/index');
-  }
+  protected $_previous_referer;
 
+  public function setUp() {
+    parent::setUp();
 
-  /** @test */
-  public function onInscrireSessionShouldRedirectToFormations() {
-    $this->dispatch('/opac/abonne/inscrire-session/id/9999');
-    $this->assertRedirectTo('/formations');
-  }
-
+    $this->_previous_referer = isset($_SERVER['HTTP_REFERER'])
+      ? $_SERVER['HTTP_REFERER']
+      : null;
 
-  /** @test */
-  public function ondesinscrireSessionShouldRedirectToFormations() {
-    $this->dispatch('/opac/abonne/desinscrire-session/id/9999');
-    $this->assertRedirectTo('/formations');
+    $_SERVER['HTTP_REFERER'] = '/formations';
   }
 
-}
 
+  public function tearDown() {
+    if ($this->_previous_referer)
+      $_SERVER['HTTP_REFERER'] = $this->_previous_referer;
 
-
-Class AbonneControllerFormationsInformationsTest extends AbstractControllerTestCase {
-
-  public function setup() {
-    parent::setup();
-
-    $test_time = new TimeSourceForTest('2014-05-09 14:00:00');
-
-    Class_Formation::setTimeSource($test_time);
-    Class_SessionFormation::setTimeSource($test_time);
-
-
-    $current_user = $this->fixture('Class_Users', [
-      'id' => 1,
-      'login' => 'log',
-      'password' => 'pwd',
-      'id_site' => 1,
-      'idabon' => '00044958',
-      'role_level' => 2,
-      'user_groups' => [$this->fixture('Class_UserGroup',['id' => 23])->addRightSuivreFormation()]
-    ]);
-
-    ZendAfi_Auth::getInstance()->logUser($current_user);
-
-    $session_full = $this->fixture('Class_SessionFormation',
-                                  ['id' => 1,
-                                   'formation_id' => 1,
-                                   'date_debut' => '2014-07-10',
-                                   'date_limite_inscription' => '2014-07-01',
-                                   'effectif_min' => 1,
-                                   'effectif_max' => 1,
-                                   'stagiaires' => [$current_user]]);
-
-    $session_canceled = $this->fixture('Class_SessionFormation',
-                                       ['id' => 1,
-                                        'formation_id' => 1,
-                                        'date_debut' => '2014-07-10',
-                                        'effectif_min' => 1,
-                                        'effectif_max' => 10,
-                                        'stagiaires' => []]);
-    $session_canceled->beAnnule();
-
-    $session_subscription_exhausted = $this->fixture('Class_SessionFormation',
-                                                     ['id' => 1,
-                                                      'formation_id' => 1,
-                                                      'date_debut' => '2014-07-10',
-                                                      'date_limite_inscription' => '2014-01-10',
-                                                      'effectif_min' => 1,
-                                                      'effectif_max' => 10,
-                                                      'stagiaires' => []]);
-
-    $formation = $this->fixture('Class_Formation',
-                   ['id' => 1,
-                    'libelle' => 'Farming cerths',
-                    'sessions' => [$session_full,
-                                   $session_canceled,
-                                   $session_subscription_exhausted]]);
-
-
-    $current_user->setSessionFormationInscriptions([$this->fixture('Class_SessionFormationInscription',
-                                                                  ['id' => 1,
-                                                                   'stagiaire' => $current_user,
-                                                                   'session_formation' => $formation])]);
-    $this->dispatch('/opac/formations', true);
+    parent::tearDown();
   }
 
-
   /** @test */
-  function sessionShouldBeFull() {
-    $this->assertXPathContentContains('//tbody//tr/td/span[@class="error"]',
-                                      'Complet');
-  }
-
-
-  /** @test */
-  function sessionShouldBeCanceld() {
-    $this->assertXPathContentContains('//tbody//tr/td/span[@class="error"]',
-                                      'Annul');
+  public function detailSessionShouldRedirectToFormations() {
+    $this->dispatch('/opac/formations/detail-session/id/9999');
+    $this->assertRedirectTo('/formations/index');
   }
 
 
   /** @test */
-  function sessionShouldBeDisplaySubscribeTimeExhaust() {
-    $this->assertXPathContentContains('//tbody//tr/td/span[@class="error"]',
-                                      'Date de limite d\'inscription dépassée:');
+  public function inscrireSessionShouldRedirectToFormations() {
+    $this->dispatch('/opac/abonne/inscrire-session/id/9999');
+    $this->assertRedirectTo('/formations');
   }
 
 
   /** @test */
-  function sessionShouldDisplaySubscribeTime() {
-    $this->assertXPathContentContains('//tbody//tr/td/span',
-                                      'Date de limite d\'inscription:');
+  public function desinscrireSessionShouldRedirectToFormations() {
+    $this->dispatch('/opac/abonne/desinscrire-session/id/9999');
+    $this->assertRedirectTo('/formations');
   }
-}
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/tests/application/modules/opac/controllers/FormationsControllerTest.php b/tests/application/modules/opac/controllers/FormationsControllerTest.php
index 7716f7ebbbac74fc2224f1bebd140dd53646e5c6..7bfdd5e7c8997b130fea130c200f727e1baf1864 100644
--- a/tests/application/modules/opac/controllers/FormationsControllerTest.php
+++ b/tests/application/modules/opac/controllers/FormationsControllerTest.php
@@ -127,25 +127,6 @@ class FormationsControllerFormationsSessionFevrierJavaTest extends AbstractForma
 
 
 
-
-class FormationsControllerAnonymousTest extends AbstractFormationsControllerTestCase {
-  public function setUp() {
-    parent::setUp();
-    $this->dispatch('/opac/formations', true);
-
-  }
-
-  /** @test */
-  function sessionShouldDisplaySubscribeTime() {
-
-    $this->assertXPathContentContains('//tbody//tr/td/span',
-                                      'Date de limite d\'inscription:');
-  }
-}
-
-
-
-
 class FormationsControllerFormationsSessionJuilletPythonDetailRetourFicheTest extends AbstractFormationsControllerTestCase {
   public function setUp() {
     parent::setUp();
@@ -157,6 +138,4 @@ class FormationsControllerFormationsSessionJuilletPythonDetailRetourFicheTest ex
     $this->assertXPathContentContains('//a[contains(@href, "abonne/fiche")]', 'Retour', $this->_response->getBody());
   }
 
-}
-
-?>
\ No newline at end of file
+}
\ No newline at end of file