diff --git a/app/controller/admin.php b/app/controller/admin.php
index ddd7551f2c4063b246785b99fdab109dfa944b17..43a20011428169aea6edac30ee4d3679b58ce8fa 100644
--- a/app/controller/admin.php
+++ b/app/controller/admin.php
@@ -15,6 +15,10 @@ class Admin extends Controller
     public function beforeRoute($f3, $args)
     {
         parent::beforeRoute($f3, $args);
+
+        // Template de base par défaut
+        $this->template = "backend/base.html";
+
         // URL de base à utiliser sur le site
         $f3->set('DONS_STATUTS', array(
             0 => "Ponctuel non validé",
@@ -41,19 +45,6 @@ class Admin extends Controller
             100 => "non applicable",
         ));
 
-        $f3->set('TAILLES', array(
-            1 => _('Coupe Homme, Taille') . ' S',
-            2 => _('Coupe Homme, Taille') . ' M',
-            3 => _('Coupe Homme, Taille') . ' L',
-            4 => _('Coupe Homme, Taille') . ' XL',
-            5 => _('Coupe Femme, Taille') . ' S',
-            6 => _('Coupe Femme, Taille') . ' M',
-            7 => _('Coupe Femme, Taille') . ' L',
-            8 => _('Coupe Femme, Taille') . ' XL',
-            9 => _('Coupe Homme, Taille') . ' XXL',
-            10 => _('Coupe Femme, Taille') . ' XXL',
-        ));
-
         if (!$f3->get('SESSION.admin')) {
             $mapper = new\DB\SQL\Mapper($f3->get('DB'), 'admins');
             $auth = new \Auth($mapper, array('id'=>'user_id', 'pw'=>'password'));
@@ -109,6 +100,102 @@ class Admin extends Controller
         $f3->set('block_content', 'backend/dons.html');
     }
 
+    public function validate($f3, $args)
+    {
+        $id = '';
+        $error = '';
+        $db = $f3->get('DB');
+        if ($f3->get('VERB')=='GET') {
+            if ($f3->exists('PARAMS.id')) {
+                $id = $f3->get('PARAMS.id');
+            } else {
+                $error= 'Pas d\'id associé à ce don';
+            }
+            if ($id != '') {
+                $result = $db->query("SELECT status,
+                    somme,
+                    adresse_id,
+                    user_id
+                    FROM dons
+                    WHERE id = ".\Utils::asl($id));
+                $result = $result->fetch(\PDO::FETCH_ASSOC);
+                $user_amount = $db->query("SELECT total, cumul FROM users
+                    WHERE id = ".\Utils::asl($result['user_id']));
+                $user_amount = $user_amount->fetch(\PDO::FETCH_ASSOC);
+            }
+            if ($result['status'] >= 100) {
+                $status = 101;
+            } else {
+                $status = 1;
+            }
+            $total = $user_amount['total'] + $result['somme'];
+            $cumul = $user_amount['total'] + $result['somme'];
+        }
+        if ($error != '') {
+        } else {
+            $db->query(
+                "UPDATE dons
+                SET status = $status
+                WHERE id = ".\Utils::asl($id)
+                );
+            $db->query("UPDATE users
+                SET total = $total,
+                cumul = $cumul
+                WHERE id = ".\Utils::asl($result['user_id']));
+        }
+        $f3->reroute("/admin/users/".$result['user_id']);
+    }
+
+
+    public function invalidate($f3, $args)
+    {
+        $id = '';
+        $error = '';
+        $db = $f3->get('DB');
+        if ($f3->get('VERB')=='GET') {
+            if ($f3->exists('PARAMS.id')) {
+                $id = $f3->get('PARAMS.id');
+            } else {
+                $error= 'Pas d\'id associé à ce don';
+            }
+            if ($id != '') {
+                $result = $db->query("SELECT status,
+                    somme,
+                    adresse_id,
+                    user_id
+                    FROM dons
+                    WHERE id = ".\Utils::asl($id));
+                $result = $result->fetch(\PDO::FETCH_ASSOC);
+                $user_amount = $db->query("SELECT total, cumul FROM users
+                    WHERE id = ".\Utils::asl($result['user_id']));
+                $user_amount = $user_amount->fetch(\PDO::FETCH_ASSOC);
+            }
+            if ($result['status'] >= 100) {
+                $status = 100;
+            } else {
+                $status = 0;
+            }
+            $total = $user_amount['total'] - $result['somme'];
+            $cumul = $user_amount['total'] - $result['somme'];
+            if ($cumul < 0) {
+                $error = "Impossible d'invalider, une contrepartie a été demandée";
+            }
+        }
+        if ($error != '') {
+        } else {
+            $db->query(
+                "UPDATE dons
+                SET status = $status
+                WHERE id = ".\Utils::asl($id)
+                );
+            $db->query("UPDATE users
+                SET total = $total,
+                cumul = $cumul
+                WHERE id = ".\Utils::asl($result['user_id']));
+        }
+        $f3->reroute("/admin/users/".$result['user_id']);
+    }
+
     public function support($f3, $args)
     {
         $id = '';
@@ -126,6 +213,7 @@ class Admin extends Controller
             if ($f3->exists('PARAMS.id')) {
                 $id = $f3->get('PARAMS.id');
             }
+            $f3->set('block_content', 'backend/don.html');
         } else {
             $id = $f3->get('POST.id');
             $pseudo = $f3->get('POST.pseudo');
@@ -184,11 +272,6 @@ class Admin extends Controller
 							1)");
                     // Récupération de l'id pour passage en mode édition
                     $id = $db->lastInsertId();
-                    if ($adresse_id != '') {
-                        $db->query("UPDATE dons
-							SET adresse_id = $adresse_id
-							WHERE id = $id");
-                    }
                 } else {
                     // We will get the ids associated to the gift first
                     $result = $db->query("SELECT adresse_id,
@@ -197,26 +280,6 @@ class Admin extends Controller
 						WHERE id = ".\Utils::asl($f3->get('POST.id')));
                     $result = $result->fetch(\PDO::FETCH_ASSOC);
                     // Let's update the adresse first or create the adress
-                    if ($result['adresse_id'] == '0') {
-                        $db->query("INSERT INTO adresses
-								(nom, adresse, adresse2, codepostal, ville, pays)
-							VALUES ('".\Utils::asl($nom)."',
-								'".\Utils::asl($adresse)."',
-								'".\Utils::asl($adresse2)."',
-								'".\Utils::asl($codepostal)."',
-								'".\Utils::asl($ville)."',
-								'".\Utils::asl($pays)."')");
-                        $result['adresse_id'] = $db->lastInsertId();
-                    } else {
-                        $db->query("UPDATE adresses
-							SET nom='".\Utils::asl($nom)."',
-								adresse='".\Utils::asl($adresse)."',
-								adresse2='".\Utils::asl($adresse2)."',
-								codepostal='".\Utils::asl($codepostal)."',
-								ville='".\Utils::asl($ville)."',
-								pays='".\Utils::asl($pays)."'
-							WHERE id={$result['adresse_id']}");
-                    }
                     $db->query("UPDATE users
 						SET email='".\Utils::asl($email)."',
 							pseudo='".\Utils::asl($pseudo)."'
@@ -580,17 +643,17 @@ class Admin extends Controller
 							ville='".\Utils::asl($ville)."',
 							pays='".\Utils::asl($pays)."')");
                     $adresse_id = $db->lastInsertId();
-                }
-            
-                // Updating the adresses first
-                $db->query("UPDATE adresses
-					SET nom='".\Utils::asl($nom)."',
-						adresse='".\Utils::asl($adresse)."',
-						adresse2='".\Utils::asl($adresse2)."',
-						codepostal='".\Utils::asl($codepostal)."',
-						ville='".\Utils::asl($ville)."',
-						pays='".\Utils::asl($pays)."'
-					WHERE id = $adresse_id");
+                } else {
+                    // Updating the adresses first
+                    $db->query("UPDATE adresses
+                        SET nom='".\Utils::asl($nom)."',
+                            adresse='".\Utils::asl($adresse)."',
+                            adresse2='".\Utils::asl($adresse2)."',
+                            codepostal='".\Utils::asl($codepostal)."',
+                            ville='".\Utils::asl($ville)."',
+                            pays='".\Utils::asl($pays)."'
+                        WHERE id = $adresse_id");
+                };
                 $db->query("UPDATE contreparties
 					SET quoi='".\Utils::asl($quoi)."',
 						taille='".\Utils::asl($taille)."',
@@ -601,27 +664,8 @@ class Admin extends Controller
             }
         }
 
-        $contrepartie = array();
         if ($id!='') {
-            // Récupération de la contrepartie
-            $result = $db->query("SELECT c.id AS id,
-					c.user_id AS user_id,
-					c.quoi AS quoi,
-					c.taille AS taille,
-					c.status AS status,
-					a.nom AS nom,
-					a.adresse AS adresse,
-					a.codepostal AS codepostal,
-					a.ville AS ville,
-					a.pays AS pays,
-					u.commentaire AS commentaire
-				FROM contreparties c
-					JOIN users u ON c.user_id = u.id
-					LEFT JOIN adresses a ON c.adresse_id = a.id
-				WHERE c.id=".$id);
-            if ($result->fetch(\PDO::FETCH_ASSOC)) {
-                $contrepartie = $result->fetch(\PDO::FETCH_ASSOC);
-            }
+            $contrepartie = $f3->get('container')['counterpart_finder']->findById((int) $id);
         } else {
             $contrepartie = array(
                 'id'=>$id,
@@ -663,6 +707,52 @@ class Admin extends Controller
         $f3->set('block_content', 'backend/contrepartie.html');
     }
 
+    public function adresse($f3, $args)
+    {
+        $id = '';
+        $form_name = '';
+        $user_id = '';
+        $db = $f3->get('DB');
+        if ($f3->get('VERB') == 'POST') {
+            $id = \Utils::asl($f3->get('POST.id'));
+            $form_name = $f3->get('POST.action');
+        }
+        if ($form_name == 'delete') {
+            $result = $db->query("SELECT user_id FROM adresses WHERE id = $id");
+            $result = $result->fetch(\PDO::FETCH_ASSOC);
+            $user_id = \Utils::asl($result["user_id"]);
+            $db->query("UPDATE dons SET adresse_id = NULL
+                WHERE user_id = $user_id");
+            $db->query("UPDATE contreparties SET adresse_id = NULL
+                WHERE user_id = $user_id");
+            $db->query(
+                "DELETE FROM adresses
+                WHERE id = $id"
+        );
+        } else {
+            $result = $db->query("SELECT user_id FROM adresses WHERE id = $id");
+            $result = $result->fetch(\PDO::FETCH_ASSOC);
+            $user_id = \Utils::asl($result["user_id"]);
+            $nom = \Utils::asl($f3->get('POST.nom'));
+            $adresse = \Utils::asl($f3->get('POST.adresse'));
+            $adresse2 = \Utils::asl($f3->get('POST.adresse2'));
+            $codepostal = \Utils::asl($f3->get('POST.codepostal'));
+            $ville = \Utils::asl($f3->get('POST.ville'));
+            $pays = \Utils::asl($f3->get('POST.pays'));
+            $db->query(
+                "UPDATE adresses SET
+                nom = '".$nom."',
+                adresse = '".$adresse."',
+                adresse2 = '".$adresse2."',
+                codepostal = '".$codepostal."',
+                ville = '".$ville."',
+                pays = '".$pays."'
+                WHERE id = $id"
+            );
+        }
+        $f3->reroute("/admin/users/$user_id");
+    }
+
     public function user($f3, $args)
     {
         $id = array_key_exists('id', $args) ? \Utils::asl($args['id']) : '';
@@ -689,7 +779,7 @@ class Admin extends Controller
 
         // Let's get everything we have related to our user
         $user = $f3->get('container')['user_finder']->findById($id);
-        $user['adresses'] = $f3->get('container')['address_finder']->findByUserId($user['id']);
+        $user['adresse'] = $f3->get('container')['address_finder']->findByUserId($user['id']);
         $user['dons'] = $f3->get('container')['donation_finder']->findByUserId($user['id']);
         $user['contreparties'] = $f3->get('container')['counterpart_finder']->findByUserId($user['id']);
 
diff --git a/app/controller/bank.php b/app/controller/bank.php
index 86ce1a71e171eb516ac27823d301e45bf88a2005..c10d87aca90102aa4617625c9de5609f372b17d9 100644
--- a/app/controller/bank.php
+++ b/app/controller/bank.php
@@ -1,6 +1,9 @@
 <?php
 namespace Controller;
 
+use LQDN\Command\UserUpdateCumulCommand;
+use LQDN\Command\UserUpdateTotalCommand;
+
 class Bank extends Controller
 {
     /* We want to ignore the sanitizing on this page */
@@ -150,13 +153,13 @@ class Bank extends Controller
         $status = $res->fetch(\PDO::FETCH_ASSOC);
         $status = $status['status'];
 
-        $res = $db->query("SELECT * FROM users WHERE id='".$don['user_id']."';");
-        $user = $res->fetch(\PDO::FETCH_ASSOC);
+        $user = $f3->get('container')['user_finder']->findById($don['user_id']);
         $cb_log->write("Utilisation d'un utilisateur existant");
         // Ajout du nouveau don au cumul actuel
         if ($status!=101) {
             $cb_log->write("Ajout de ".$don['somme']);
-            $db->query("UPDATE users set cumul = cumul + " . $don['somme'] . ", total = total + " . $don['somme'] . " WHERE id='".$don['user_id']."'");
+            $f3->get('container')['command_handler']->handle(new UpdateUserTotalCommand($user['id'], (int) $user['total'] + $don['somme']));
+            $f3->get('container')['command_handler']->handle(new UpdateUserCumulCommand($user['id'], (int) $user['cumul'] + $don['cumul']));
         }
         $result = $db->query("SELECT cumul FROM users WHERE id='".$don['user_id']."'");
         $cumul = $result->fetch(\PDO::FETCH_ASSOC);
@@ -199,7 +202,7 @@ Toute l'équipe de La Quadrature du Net
 ")."\n\n";
 
             // Création de l'url d'administration
-            $admin_url = "https://support.laquadrature.net/perso";
+            $admin_url = "https://don.laquadrature.net/perso";
             foreach ($f3->get('languages') as $key => $language) {
                 if ($lang==$language[1]) {
                     $admin_url = "https://".$language[0].$f3->get('dev').".laquadrature.net/perso";
diff --git a/app/controller/campaign.php b/app/controller/campaign.php
index f8a71a439f9f04ebf6bda7526b8f9d5cd59b6037..b589886ec571c3d0ef947b6d5915fa338a59e2b2 100644
--- a/app/controller/campaign.php
+++ b/app/controller/campaign.php
@@ -1,6 +1,10 @@
 <?php
 namespace Controller;
 
+use LQDN\Command\UserUpdateTotalCommand;
+use LQDN\Command\UserCreateCommand;
+use LQDN\Command\DonationCreateCommand;
+
 class Campaign extends Controller
 {
     /*
@@ -93,8 +97,7 @@ class Campaign extends Controller
         $db = $f3->get('DB');
         // Si l'utilisateur est déjà connecté, on le récupère
         if ($f3->get('SESSION.user', true)) {
-            $user = $db->query("SELECT * FROM users WHERE id = ".$f3->get('SESSION.id'));
-            $user = $user->fetch(\PDO::FETCH_ASSOC);
+            $user = $f3->get('container')['user_finder']->findById($f3->get('SESSION.id'));
             $email = $user['email'];
             $user_id = $user['id'];
             $cumul_id = $user['cumul'];
@@ -103,10 +106,9 @@ class Campaign extends Controller
             $email = \Utils::asl($f3->get('email'));
             $hash = hash('sha256', $f3->get('password'));
 
-            $sql = "SELECT id FROM users WHERE email = '".\Utils::asl($email)."';";
-            $result = $db->query($sql);
+            $user = $f3->get('container')['user_finder']->findByEmail(\Utils::asl($email));
 
-            if ($result->fetchColumn() > 0) {
+            if (len($user) > 0) {
                 // We have an existing user, we should try to login with the provided password
                 // or 403.
                 $mapper = new \DB\SQL\Mapper($f3->get('DB'), 'users');
@@ -114,11 +116,6 @@ class Campaign extends Controller
                 $login = $auth->login($email, $hash);
                 if (!$login) {
                     $f3->error(403);
-                } else {
-                    $result = $db->query("SELECT id, cumul FROM users WHERE email = '".\Utils::asl($email)."'");
-                    $user = $result->fetch(\PDO::FETCH_ASSOC);
-                    $user_id = $user['id'];
-                    $cumul_id = $user['cumul'];
                 }
             } else {
                 // The user does not exist, so let's create it
diff --git a/app/controller/perso.php b/app/controller/perso.php
index 3673e7c29ffaee57e82fa111593e9d073b1c5663..42c53ab7c922404346afb23aa7202af52152e7ad 100644
--- a/app/controller/perso.php
+++ b/app/controller/perso.php
@@ -4,6 +4,11 @@ namespace Controller;
 use LQDN\Command\AddressCreateCommand;
 use LQDN\Command\AddressDeleteCommand;
 use LQDN\Command\AddressUpdateCommand;
+use LQDN\Command\CounterpartCreateCommand;
+use LQDN\Command\CounterpartDeleteCommand;
+use LQDN\Command\UserUpdateCumulCommand;
+use LQDN\Command\UserUpdateTotalCommand;
+use LQDN\Command\UserCreateCommand;
 
 class Perso extends Controller
 {
@@ -38,41 +43,14 @@ class Perso extends Controller
     {
         // Chargement des informations de l'utilisateur
         $db = $f3->get('DB');
-        // Let's update the total first
-        $total = 0;
-        $total_res = $db->query("SELECT SUM(somme) as total FROM dons WHERE status in (1, 4, 101, 102) AND user_id='".$f3->get('SESSION.id')."'");
-        $total_res = $total_res->fetch(\PDO::FETCH_ASSOC);
-        $total = $total_res['total'];
-        // While we're at it, let's remove the price of each asked contreparties
-        // printed piplome is 30, pibag is 50, pishirt is 100 and hoodie is 250
-        // We first need to have the number of each counterpart claimed by the
-        // user
-        $cumul_counterpart = $db->query("SELECT sum(if(quoi='piplome', 1, 0)) as piplomes,
-            sum(if(quoi='pibag', 1, 0)) as pibags,
-            sum(if(quoi='pishirt', 1, 0)) as pishirts,
-            sum(if(quoi='hoodie', 1, 0)) as hoodies
-            FROM contreparties
-            WHERE user_id = '".$f3->get('SESSION.id')."';");
-        $cumul_counterpart = $cumul_counterpart->fetch(\PDO::FETCH_ASSOC);
-        foreach (['hoodies', 'pishirts', 'pibags', 'piplomes'] as $key) {
-            if (!array_key_exists($key, $cumul_counterpart)) {
-                $cumul_counterpart[$key] = 0;
-            }
-        }
-        $cumul = $cumul_counterpart['hoodies'] * 250 + max(($cumul_counterpart['pishirts'] - $cumul_counterpart['hoodies']), 0) * 100 + max(($cumul_counterpart['pibags'] - $cumul_counterpart['pishirts'] - $cumul_counterpart['hoodies']), 0) * 50 + max(($cumul_counterpart['piplomes'] - $cumul_counterpart['pibags'] - $cumul_counterpart['pishirts'] - $cumul_counterpart['hoodies']), 0) * 30;
-
-        $cumul = $total - $cumul;
-
-        $db->query("UPDATE users SET total = '".$total."', cumul = '".$cumul."' WHERE id = '".$f3->get('SESSION.id')."'");
-        $result = $db->query("SELECT id, pseudo, email, total, cumul FROM users WHERE id='".$f3->get('SESSION.id')."' ");
-        $data = $result->fetch(\PDO::FETCH_ASSOC);
-        $f3->set('infos', $data);
-        $result = $db->query("SELECT id, pdf, decimale FROM dons WHERE user_id='".$data['id']."' and pdf!='' ");
+        $user = $f3->get('container')['user_finder']->findById($f3->get('SESSION.id'));
+        $f3->set('infos', $user);
+        $result = $db->query("SELECT id, pdf, decimale FROM dons WHERE user_id='".$user['id']."' and pdf!='' ");
         $pdfs = array();
         foreach ($result->fetchAll(\PDO::FETCH_ASSOC) as $row) {
             $pdfs[$row['pdf']] = $row;
         }
-        $addresse = $f3->get('container')['address_finder']->findByUserId((int) $data['id']);
+        $addresse = $f3->get('container')['address_finder']->findByUserId((int) $user['id']);
         $f3->set('adresse', $addresse);
         $f3->set('pdfs', $pdfs);
     }
@@ -80,25 +58,19 @@ class Perso extends Controller
     public function get_contreparties($f3)
     {
         // Chargement des contreparties de l'utilisateur
-        $db = $f3->get('DB');
-        $result =$db->query("SELECT datec, status, quoi, taille, adresse_id FROM contreparties WHERE user_id='".$f3->get('SESSION.id')."' ORDER BY datec DESC");
-        $data = array();
-        foreach ($result->fetchAll(\PDO::FETCH_ASSOC) as $row) {
-            $data[] = $row;
-        }
-        $f3->set('contreparties', $data);
+        $contreparties = $f3->get('container')['counterpart_finder']->findByUserId((int) $f3->get('SESSION.id'));
+        $f3->set('contreparties', $contreparties);
     }
 
     public function get_dons($f3)
     {
         // Chargement des dons de l'utilisateur
         $db = $f3->get('DB');
-        $result = $db->query("SELECT datec, somme, id, pdf, status FROM dons WHERE user_id='".$f3->get('infos.id')."' AND status IN (1,4,102) ORDER BY datec DESC");
-        $data = array();
-        foreach ($result->fetchAll(\PDO::FETCH_ASSOC) as $row) {
-            $data[] = $row;
-        }
-        $f3->set('dons', $data);
+        $dons = $f3->get('container')['donation_finder']->findByUserId((int) $f3->get('SESSION.id'));
+        $dons = array_filter($dons, function ($id) {
+            return in_array((int) $id, [1, 4, 102]);
+        });
+        $f3->set('dons', $dons);
     }
 
     public function get_recurrents($f3)
@@ -115,8 +87,6 @@ class Perso extends Controller
 
     public function login($f3, $args)
     {
-        $f3->clear('SESSION.error');
-        $f3->clear('SESSION.message');
         $f3->set('form_visible', 'login');
 
         if ($f3->get('action')=='renew_password') {
@@ -240,8 +210,7 @@ class Perso extends Controller
         if ($f3->get('email')!='') {
             // On vérifie que l'adresse mail n'existe pas
             $db = $f3->get('DB');
-            $query = $db->query("SELECT email FROM users WHERE email='".$f3->get('email')."';");
-            $result = $query->fetch(\PDO::FETCH_ASSOC);
+            $user = $f3->get('container')['user_finder']->findByEmail($f3->get('email'));
             $cumul = 0;
             if ($result['email']!=$f3->get('email')) {
                 $hash = hash('sha256', $f3->get('password'));
@@ -337,11 +306,8 @@ class Perso extends Controller
         if (!$f3->exists('SESSION.user')) {
             $f3->error('401');
         }
-        // Récupération du cumul actuel de l'utilisateur
-        $db = $f3->get('DB');
-        $result = $db->query("SELECT cumul FROM users WHERE id='".$f3->get('SESSION.id')."' ");
-        $me = $result->fetch(\PDO::FETCH_ASSOC);
-        $cumul = $me['cumul'];
+
+        $user = $f3->get('container')['user_finder']->findById($f3->get('SESSION.id'));
 
         // Récupération des valeurs du formulaire
         $adresse_id = $f3->get('adresse_id');
@@ -351,7 +317,6 @@ class Perso extends Controller
         $piplome_id = intval(substr($f3->get('piplome_id'), 0, strpos($f3->get('piplome_id'), '_')));
         $taille = intval($f3->get('taille'));
         $taille_h = intval($f3->get('taille_h'));
-        $f3->clear('SESSION.error');
         switch ($quoi) {
         case 'piplome':
             $valeur = 30;
@@ -368,24 +333,28 @@ class Perso extends Controller
         }
 
         // Ajout d'une demande de contrepartie pour chaque contrepartie
-        if ($cumul >= $valeur) {
+        if ((int) $user['cumul'] >= $valeur) {
             switch ($quoi) {
             case 'piplome':
-                $db->query("INSERT INTO contreparties (user_id,datec,quoi,taille,adresse_id,status,commentaire) VALUES ('".$f3->get('SESSION.id')."',NOW(),'piplome','".\Utils::asl($piplome_id)."','".\Utils::asl($adresse_id)."',1, '".\Utils::asl($commentaire)."')");
+                $f3->get('container')['command_handler']->handle(new CounterpartCreateCommand(\Utils::asl($adresse_id), $f3->get('SESSION.id'), 'piplome', \Utils::asl($piplome_id), 1, date("Y-m-d H:i:s"), \Utils::asl($commentaire)));
                 break;
             case 'pibag':
-                $db->query("INSERT INTO contreparties (user_id,datec,quoi,taille,adresse_id,status,commentaire) VALUES ('".$f3->get('SESSION.id')."',NOW(),'pibag','','".\Utils::asl($adresse_id)."',1, '".\Utils::asl($commentaire)."')");
+                $f3->get('container')['command_handler']->handle(new CounterpartCreateCommand(\Utils::asl($adresse_id), $f3->get('SESSION.id'), 'pibag', '', 1, date("Y-m-d H:i:s"), \Utils::asl($commentaire)));
                 break;
             case 'pishirt':
-                $db->query("INSERT INTO contreparties (user_id,datec,quoi,taille,adresse_id,status,commentaire) VALUES ('".$f3->get('SESSION.id')."',NOW(),'pishirt','".\Utils::asl($taille)."','".\Utils::asl($adresse_id)."',1, '".\Utils::asl($commentaire)."')");
+                $f3->get('container')['command_handler']->handle(new CounterpartCreateCommand(\Utils::asl($adresse_id), $f3->get('SESSION.id'), 'pishirt', \Utils::asl($taille), 1, date("Y-m-d H:i:s"), \Utils::asl($commentaire)));
                 break;
             case 'hoopie':
-                $db->query("INSERT INTO contreparties (user_id,datec,quoi,taille,adresse_id,status,commentaire) VALUES ('".$f3->get('SESSION.id')."',NOW(),'hoodie','".\Utils::asl($taille_h)."','".\Utils::asl($adresse_id)."',1, '".\Utils::asl($commentaire)."')");
+                $f3->get('container')['command_handler']->handle(new CounterpartCreateCommand(\Utils::asl($adresse_id), $f3->get('SESSION.id'), 'hoopie', \Utils::asl($taille_h), 1, date("Y-m-d H:i:s"), \Utils::asl($commentaire)));
+                break;
             }
+            // Puis diminution du cumul de la valeur des contreparties
+            $f3->get('container')['command_handler']->handle(new UserUpdateCumulCommand($user['id'], $user['cumul'] - $valeur));
+            $f3->set('SESSION.message', _("Merci, vos contreparties seront envoyées dès que possible !".$valeur));
+        } else {
+            $f3->set('SESSION.error', _("Désolé, mais vous n'avez pas cumulé suffisament de dons pour avoir un ").$quoi);
+            $f3->clear('SESSION.message');
         }
-        // Puis diminution du cumul de la valeur des contreparties
-        $db->query("UPDATE users SET cumul = cumul - ".$valeur." WHERE id='".$f3->get('SESSION.id')."'");
-        $f3->set('SESSION.message', _("Merci, vos contreparties seront envoyées dès que possible !"));
         $f3->reroute('/perso');
     }
 
diff --git a/app/routes.ini b/app/routes.ini
index a91702093a1b12fd199c470558850dd4292628c5..44c221971667389cf2dafb744037a71d451bb699 100644
--- a/app/routes.ini
+++ b/app/routes.ini
@@ -27,6 +27,8 @@ GET|POST @admin:/admin=Controller\Admin->show
 GET @add_support:/admin/support/add=Controller\Admin->support
 GET @edit_support:/admin/support/edit/@id=Controller\Admin->support
 POST @modify_support:/admin/support/edit=Controller\Admin->support
+GET @invalidate_support:/admin/support/invalidate/@id=Controller\Admin->invalidate
+GET @validate_support:/admin/support/validate/@id=Controller\Admin->validate
 
 GET|POST @admin_accounts:/admin/accounts=Controller\Admin->accounts
 
diff --git a/app/view/backend/base.html b/app/view/backend/base.html
index b42b86d67a423a5f0fe4156eafc3c62ca0100c0c..3ea0abd0cff409f9b02bc296878480544470b053 100644
--- a/app/view/backend/base.html
+++ b/app/view/backend/base.html
@@ -1,4 +1,4 @@
 <include href="backend/header.html" />
 <include href="backend/toolbar.html" />
 <include href="{{ @block_content }}" />
-<include href="backend/footer.html" />
+<!-- <include href="backend/footer.html" /> <!-- No need for scripts right now -->
diff --git a/app/view/backend/contrepartie.html b/app/view/backend/contrepartie.html
index 2742f99b1334bb921c0b0240946a15749e20a506..eed4b98d101e4264ca170b66daefe1f3ded8d24d 100644
--- a/app/view/backend/contrepartie.html
+++ b/app/view/backend/contrepartie.html
@@ -7,13 +7,13 @@
 	<h2>Ajout d'une contrepartie</h2>
 	</false>
 	</check>
-	<form name="f" method="POST" action="{{ 'edit_counterpart', 'id='+@id | alias }}">
+	<form name="f" method="POST" action="{{ 'edit_counterpart', 'id='.@id | alias }}">
 		<input type="hidden" name="taille" id="taille" value="{{ @contrepartie.taille }}" />
 		<input type="hidden" name="user_id" id="user_id" value="{{ @contrepartie.user_id }}" />
 		<input type="hidden" id="csrf" name="csrf" value="{{ @CSRF }}" />
 
 		<label for="quoi">Quoi</label>
-		<select id="quoi" name="quoi" onchange="select_span()">
+		<select id="quoi" name="quoi">
 			<option value="piplome" <check if="{{ @contrepartie.quoi=='piplome' }}">selected</check> >piplome</option>
 			<option value="pishirt" <check if="{{ @contrepartie.quoi=='pishirt' }}">selected</check> >pishirt</option>
 			<option value="hoodie" <check if="{{ @contrepartie.quoi=='hoodie' }}">selected</check> >hoodie</option>
@@ -22,15 +22,15 @@
 
 		<span id="quoi_taille">
 			<label for="size">Taille</label>
-			<select id="size" name="size" onchange="select_taille()">
-				<repeat group="{{ @TAILLES }}" key="{{ @key }}" value="{{ @value }}">
+			<select id="size" name="size">
+				<repeat group="{{ @atailles }}" key="{{ @key }}" value="{{ @value }}">
 				<option value="{{ @key }}" <check if="{{ @contrepartie.taille==@key }}">selected</check> >{{ @value }}</option>
 				</repeat>
 			</select>
 		</span>
 		<span id="quoi_pdf">
 			<label for="url">Pdf</label>
-			<select id="url" name="url" onchange="select_taille()">
+			<select id="url" name="url">
 				<repeat group="{{ @pdfs }}" value="{{ @pdf }}">
 				<option value="{{ @pdf.id }}" <check if="{{ @contrepartie.taille==@pdf.id }}">selected</check> >{{ @pdf.pdf }} / {{ @pdf.nom }}</option>
 				</repeat>
@@ -43,7 +43,11 @@
 		<br />
 
 		<label for="adresse">Adresse</label>
-		<textarea id="adresse" name="adresse" cols="30" rows="2">{{ @contrepartie.adresse }}</textarea>
+        <input type="text" id="adresse" name="adresse" size="60" value="{{ @contrepartie.adresse }}">
+		<br />
+
+		<label for="adresse">Complément d'adresse</label>
+        <input type="text" id="adresse2" name="adresse2" size="60" value="{{ @contrepartie.adresse2 }}">
 		<br />
 
 		<label for="codepostal">Code postal</label>
@@ -65,7 +69,7 @@
 		</select>
 		<br />
 
-		<label for=commentaire">Commentaire</label>
+		<label for="commentaire">Commentaire</label>
 		<textarea type="textarea" id="commentaire" name="commentaire" cols="30" rows="2">{{ @contrepartie.commentaire }}</textarea>
 		<br />
 
diff --git a/app/view/backend/contreparties.html b/app/view/backend/contreparties.html
index b82fbff3fcb10d71971fe0537dc811b8ec09c7d4..8f71fd0a135c033e4c6298644861d0b31befe959 100644
--- a/app/view/backend/contreparties.html
+++ b/app/view/backend/contreparties.html
@@ -71,14 +71,14 @@
             &nbsp;
             </true>
             <false>
-            {{ @TAILLES[@row.taille] }}
+            {{ @atailles[@row.taille] }}
             </false>
             </check>
         </false>
         </check>
         </td>
         <td>
-        {{ @row.nom }}<br />
+        {{ @row.pseudo }}<br />
         {{ @row.adresse }}<br />
         {{ @row.adresse2 }}<br />
         {{ @row.codepostal }} {{ @row.ville }}<br />
diff --git a/app/view/backend/dons.html b/app/view/backend/dons.html
index 742a767ac9668225c77e574914373adc7dd3bde3..418656652bf9bc268f79c5ccde2496c5b260031c 100644
--- a/app/view/backend/dons.html
+++ b/app/view/backend/dons.html
@@ -55,8 +55,8 @@
     <tr>
         <td>{{ @row.id }}</td>
         <td class="inline">{{ @row.datec }}</td>
-        <td>{{ @row.nom }}</td>
-	<td><a href="{{ 'user_info','id='.@row.user_id | alias }}">{{ @row.email }}</a></td>
+        <td>{{ @row.pseudo }}</td>
+        <td><a href="{{ 'user_info','id='.@row.user_id | alias }}">{{ @row.email }}</a></td>
         <td>{{ @row.somme }}</td>
         <td>
         {{ @row.adresse }}<br />
@@ -71,12 +71,12 @@
         -
         <check if="{{ @row.status==0 || @row.status==100 }}" >
         <true>
-            <span class="lien" onclick="valid({{ @row.id }})">Valider</span>
+        <a href="{{ 'validate_support', 'id='.@row.id | alias }}">Valider</a>
         </true>
         <false>
-            <span class="lien" onclick="invalid({{ @row.id }})">Invalider</span>
+            <a href="{{ 'invalidate_support', 'id='.@row.id | alias }}">Invalider</a>
             -
-            <span class="lien" onclick="pdf({{ @row.id }})">PDF</span>
+            <a href="{{ 'validate_support', 'id='.@row.id | alias }}">PDF</a>
         </false>
         </check>
         </td>
diff --git a/app/view/backend/user.html b/app/view/backend/user.html
index 9ce91220307e8b755ec03f2976d7f0a1467ca1c7..654759a317211bcdb8c9a7c16ceafbe052ff1eea 100644
--- a/app/view/backend/user.html
+++ b/app/view/backend/user.html
@@ -35,52 +35,50 @@
 	<br />
 </section>
 <section id="adresses">
-	<h2>Adresses associées à cet utilisateur</h2>
-	<repeat group="{{ @user.adresses }}" value="{{ @adresse }}" counter="{{ @i }}">
-		<h3>{{ @i }}&nbsp:{{ @adresse.alias }}</h3>
-		<form name="addr_{{@id }}" method="POST" action="{{ 'adresse' |alias }}">
-		        <input type="hidden" id="csrf" name="csrf" value="{{ @CSRF }}" />
-			<input type="hidden" name="id" id="id" value="{{ @adresse.id }}" />
-			<input type="hidden" name="action" id="action" value="modify" />
-
-			<label for="nom">Nom</label>
-			<input type="text" id="nom" name="nom" size="30" value="{{ @adresse.nom }}" />
-			<br />
-
-			<label for="adresse">Adresse</label>
-			<input type="text" id="adresse" name="adresse" size="100" value="{{ @adresse.adresse }}" />
-			<br />
-
-			<label for="adresse2">Adresse (compl.)</label>
-			<input type="text" id="adresse2" name="adresse2" size="100" value="{{ @adresse.adresse2 }}" />
-			<br />
-
-			<label for="codepostal">Code Postal</label>
-			<input type="text" id="codepostal" name="codepostal" size="10" value="{{ @adresse.codepostal }}" />
-			<br />
-
-			<label for="ville">Ville</label>
-			<input type="text" id="ville" name="ville" size="50" value="{{ @adresse.ville }}" />
-			<br />
-
-			<label for="etat">Etat / Province / Comté</label>
-			<input type="text" id="etat" name="etat" size="50" value="{{ @adresse.etat }}" />
-			<br />
-
-			<label for="pays">Pays</label>
-			<input type="text" id="pays" name="pays" size="30" value="{{ @adresse.pays }}" />
-			<br />
-
-			<input type="submit" value="Modifier l'adresse" />
-		</form>
-		<form name="del_addr_{{@id}}" method="POST" action="{{ 'adresse' | alias }}">
-		        <input type="hidden" id="csrf" name="csrf" value="{{ @CSRF }}" />
-			<input type="hidden" name="id" id="id" value="{{ @adresse.id }}" />
-			<input type="hidden" name="action" id="action" value="delete" />
-			<input type="submit" value="Effacer l'adresse" />
-		</form>
-
-	</repeat>
+	<h2>Adresse postale de cet utilisateur</h2>
+    <check if="@@user.adresse">
+    <form name="addr_{{@id }}" method="POST" action="{{ 'adresse' |alias }}">
+        <input type="hidden" id="csrf" name="csrf" value="{{ @CSRF }}" />
+        <input type="hidden" name="id" id="id" value="{{ @@user.adresse.id }}" />
+        <input type="hidden" name="action" id="action" value="modify" />
+
+        <label for="nom">Nom</label>
+        <input type="text" id="nom" name="nom" size="30" value="{{ @@user.adresse.nom }}" />
+        <br />
+
+        <label for="adresse">Adresse</label>
+        <input type="text" id="adresse" name="adresse" size="100" value="{{ @@user.adresse.adresse }}" />
+        <br />
+
+        <label for="adresse2">Adresse (compl.)</label>
+        <input type="text" id="adresse2" name="adresse2" size="100" value="{{ @@user.adresse.adresse2 }}" />
+        <br />
+
+        <label for="codepostal">Code Postal</label>
+        <input type="text" id="codepostal" name="codepostal" size="10" value="{{ @@user.adresse.codepostal }}" />
+        <br />
+
+        <label for="ville">Ville</label>
+        <input type="text" id="ville" name="ville" size="50" value="{{ @@user.adresse.ville }}" />
+        <br />
+
+        <label for="etat">Etat / Province / Comté</label>
+        <input type="text" id="etat" name="etat" size="50" value="{{ @@user.adresse.etat }}" />
+        <br />
+
+        <label for="pays">Pays</label>
+        <input type="text" id="pays" name="pays" size="30" value="{{ @@user.adresse.pays }}" />
+        <br />
+
+        <input type="submit" value="Modifier l'adresse" />
+    </form>
+    <form name="del_addr_{{@id}}" method="POST" action="{{ 'adresse' | alias }}">
+            <input type="hidden" id="csrf" name="csrf" value="{{ @CSRF }}" />
+        <input type="hidden" name="id" id="id" value="{{ @@user.adresse.id }}" />
+        <input type="hidden" name="action" id="action" value="delete" />
+        <input type="submit" value="Effacer l'adresse" />
+    </form>
+    </check>
 </section>
 <section id="contreparties">
 	<check if="{{ count(@user.contreparties) > 0}}">
@@ -123,7 +121,7 @@
 					<td>
 						<check if="{{ @row.adresse_id != null }}">
 						<true>
-							{{ @user.adresses[@row.adresse_id].alias }}
+							{{ @@user.adresses[@row.adresse_id].nom }}
 						</true>
 						<false>
 							-
@@ -174,7 +172,6 @@
 		    <th>ID</th>
 		    <th>Date</th>
 		    <th>Don</th>
-		    <th>Adresse</th>
 		    <th>PDF</th>
 		    <th>Statut</th>
 		    <th>Actions</th>
@@ -186,35 +183,26 @@
 			<td class="inline">{{ @row.datec }}</td>
 			<td>{{ @row.somme }}</td>
 			<td>
-				<check if="{{ array_key_exists(@row.adresse_id, @user.adresses)}}">
-				<true>
-					{{ @user.adresses[@row.adresse_id].alias }}
-				</true>
-				<false>
-					&nbsp;
-				</false>
-				</check>
-			</td>
-			<td>
-				<check if="{{ @row.pdf != '' }}">
-				<true><a href="{{ @PIPLOME_URL }}{{ @row.pdf }}.pdf">{{ @row.pdf }}</a>( {{@user.adresses[@row.adresse_id].nom }})</td>
-				</true>
-				<false>
-				&nbsp;
-				</false>
-				</check>
+                <check if="{{ @row.pdf == '' }}">
+                    <true>
+                        <a href="/cron/piplome/{{ @row.id }}">PDF</a>
+                    </true>
+                    <false>
+                        <a href="{{ PIPLOME_URL }}/{{ @row.pdf }}.pdf" target="_blank">PDF</a>
+                    </false>
+                </check>
+            </td>
 			<td class="inline">{{ @DONS_STATUTS[@row.status] }}</td>
 			<td>
 				<a href="{{ 'edit_support', 'id='.@row.id | alias }}">Editer</a>
 				-
 				<check if="{{ @row.status==0 || @row.status==100 }}" >
 					<true>
-					    <span class="lien" onclick="valid({{ @row.id }})">Valider</span>
+				        <a href="{{ 'validate_support', 'id='.@row.id | alias }}">Valider</a>
 					</true>
 					<false>
-					    <span class="lien" onclick="invalid({{ @row.id }})">Invalider</span>
+				        <a href="{{ 'invalidate_support', 'id='.@row.id | alias }}">Invalider</a>
 					    -
-					    <span class="lien" onclick="pdf({{ @row.id }})">PDF</span>
 					</false>
 				</check>
 			</td>
diff --git a/app/view/campaign/home.html b/app/view/campaign/home.html
index 9116230d9aded3cf4f1b6f5945ab62e29413c956..782278fc809b2dc006e75b86628d9d1fc8853553 100644
--- a/app/view/campaign/home.html
+++ b/app/view/campaign/home.html
@@ -7,7 +7,7 @@
 		</div>
 		<div class="modal-form-body">
 			<fieldset class="modal-form-only modal-form-body">
-				<legend>{{ _("3 Redirection vers le site de paiement") }}</legend>
+				<legend>{{ _("Redirection vers le site de paiement") }}</legend>
 				<div class="modal-row">
 					<p> {{ _("Vous allez effectuer un don de") }} <em>{{ @@amount }} €</em><check if="{{ @@monthly == 'true' }}">{{ _(" par mois.") }}</check></p>
 					<p> {{ _("En cliquant sur le bouton ci-dessous, vous allez être redirigé vers le système de paiement de notre banque.") }}</p>
@@ -16,7 +16,7 @@
 					</repeat>
 				</div>
 				<div class="modal-row">
-					<input class="btn btn-lg btn-modal" type="submit" name="submit_" id="submit_" value={{ _("Procéder au paiement") }}>
+					<input class="btn btn-lg btn-modal" type="submit" name="submit_" id="submit_" value={{ _("Valider") }}>
 				</div>
 			</fieldset>
 		</div>
@@ -41,7 +41,7 @@
 					</div>
 					<div class="modal-form-body">
 						<fieldset class="form-group">
-							<legend class="modal-form-only">{{ _("1 Récapitulatif de votre don") }}</legend>
+							<legend class="modal-form-only">{{ _("Récapitulatif de votre don") }}</legend>
 							<fieldset>
 								<div class="modal-row">
 									<div class="radio-row"> 
@@ -88,9 +88,9 @@
 					</div>
 					<div class="modal-form-body">
 						<fieldset class="modal-form-only">
-							<legend>{{ _("2 Détails personnels") }}</legend>
+							<legend>{{ _("Détails personnels") }}</legend>
 							<div class="modal-row">
-								<p>{{ _("Si vous avez déjà donné, vous pouvez réutiliser vos identifiants de connexion précédents, sinon un compte sera automatiquement créé afin que vous puissiez obtenir vos contreparties.") }}</p>
+								<p>{{ _("Si vous avez déjà donné, utilisez votre adresse email et votre mot de passe habituel.") }}</p>
 							</div>
 							<div class="modal-row form-group">
 								<label for="pseudo">{{ _("Pseudo") }}</label>
@@ -106,9 +106,9 @@
 							</div>
 							</false>
 							</check>
-							<div class="modal-row modal-form-only">
-								<a href="#password-reset">{{ _("Obtenir un nouveau mot de passe") }}</a>
-								<input class="btn btn-lg btn-modal" type="submit" name="submit" id="submit" value={{ _("Procéder au paiement") }}>
+							<div class="modal-row modal-form-only"><br>
+								<a href="#password-reset">{{ _("Mot de passe oublié ?") }}</a><br>
+								<input class="btn btn-lg btn-modal" type="submit" name="submit" id="submit" value={{ _("Valider") }}>
 							</div>
 						</fieldset>
 					</div>
diff --git a/app/view/user/perso.html b/app/view/user/perso.html
index 2941a27beaf458c36072ad0a4fd20c157436b6c2..2d44a4ce9b250818c476cdfb432b79ca06727782 100644
--- a/app/view/user/perso.html
+++ b/app/view/user/perso.html
@@ -237,7 +237,7 @@
         <div class="page-header">
             <h2 class="text-left">{{ _("Demander des contreparties")}}</h2>
         </div>
-        <p class="text-left">{{ _("Pour débloquer les objets associés à un bonus, cliquez sur l'icône de celui-ci. Le montant disponible pour les objets sera déduit du montant du palier et les objets seront disponibles sur la page <a href=\"#\">Mes contreparties</a> pour en demander la livraison.")}}</p>
+        <p class="text-left">{{ _("Pour demander vos contreparties, cliquez sur le pack de votre choix, indiquez une adresse postale et validez.")}}</p>
         <div id="" class="row">
             <form method="GET" action="{{ 'perso' | alias }}" name="contreparties">
                 <input type="hidden" name="validate" value="true">
diff --git a/src/LQDN/Command/CounterpartChangeStateCommand.php b/src/LQDN/Command/CounterpartChangeStateCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..a88171607c11c93ed419224f0a57dcafbf4048c2
--- /dev/null
+++ b/src/LQDN/Command/CounterpartChangeStateCommand.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LQDN\Command;
+
+class CounterpartChangeStateCommand
+{
+    private $counterpartId;
+    private $state;
+
+    public function __construct($counterpartId, $state)
+    {
+        $this->counterpartId = $counterpartId;
+        $this->state = $state;
+    }
+
+    public function getCounterpartId()
+    {
+        return $this->counterpartId;
+    }
+
+    public function getState()
+    {
+        return $this->state;
+    }
+}
diff --git a/src/LQDN/Command/CounterpartCreateCommand.php b/src/LQDN/Command/CounterpartCreateCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..1a0a7e3ba44884b09be4609b7926039532762751
--- /dev/null
+++ b/src/LQDN/Command/CounterpartCreateCommand.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace LQDN\Command;
+
+class CounterpartCreateCommand
+{
+    private $counterpartId;
+    private $adresseId;
+    private $userId;
+    private $quoi;
+    private $taille;
+    private $status;
+    private $date;
+
+    public function __construct($addressId, $userId, $quoi, $taille, $status, $date, $commentaire)
+    {
+        $this->userId = $userId;
+        $this->addressId = $addressId;
+        $this->quoi = $quoi;
+        $this->taille = $taille;
+        $this->status = $status;
+        $this->date = $date;
+        $this->commentaire = $commentaire;
+    }
+
+    public function getUserId()
+    {
+        return $this->userId;
+    }
+
+    public function getAddressId()
+    {
+        return $this->addressId;
+    }
+
+    public function getQuoi()
+    {
+        return $this->quoi;
+    }
+
+    public function getTaille()
+    {
+        return $this->taille;
+    }
+
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getDateCreation()
+    {
+        return $this->date;
+    }
+
+    public function getCommentaire()
+    {
+        return $this->commentaire;
+    }
+}
diff --git a/src/LQDN/Command/CounterpartDeleteCommand.php b/src/LQDN/Command/CounterpartDeleteCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..570a4b7236758cc17f41f30ac450f55252f8b098
--- /dev/null
+++ b/src/LQDN/Command/CounterpartDeleteCommand.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace LQDN\Command;
+
+class CounterpartDeleteCommand
+{
+    private $counterpartId;
+
+    public function __construct($counterpartId)
+    {
+        $this->counterpartId = $counterpartId;
+    }
+
+    public function getCounterpartId()
+    {
+        return $this->counterpartId;
+    }
+}
diff --git a/src/LQDN/Command/DonationCreateCommand.php b/src/LQDN/Command/DonationCreateCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..8e713c77d56ce603d58eae0a316160c1627d17e0
--- /dev/null
+++ b/src/LQDN/Command/DonationCreateCommand.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace LQDN\Command;
+
+class DonationCreateCommand
+{
+    private $status;
+    private $datec;
+    private $somme;
+    private $userId;
+    private $public;
+    private $cumul;
+
+    public function __construct($userId, $status, $datec, $somme, $public, $cumul)
+    {
+        $this->status = $status;
+        $this->userId = $userId;
+        $this->datec = $datec;
+        $this->somme = $somme;
+        $this->public = $public;
+        $this->cumul = $cumul;
+    }
+
+    public function getUserId()
+    {
+        return $this->userId;
+    }
+
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getDateC()
+    {
+        return $this->datec;
+    }
+
+    public function getSomme()
+    {
+        return $this->somme;
+    }
+
+    public function getPublic()
+    {
+        return $this->public;
+    }
+
+    public function getCumul()
+    {
+        return $this->cumul;
+    }
+}
diff --git a/src/LQDN/Command/UserCreateCommand.php b/src/LQDN/Command/UserCreateCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7af39467b53b3ad87b0e579a4c22f27d814af4c
--- /dev/null
+++ b/src/LQDN/Command/UserCreateCommand.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace LQDN\Command;
+
+class UserCreateCommand
+{
+    private $email;
+    private $hash;
+    private $pseudo;
+
+    public function __construct($email, $hash, $pseudo, $cumul, $total)
+    {
+        $this->hash = $hash;
+        $this->email = $email;
+        $this->pseudo = $pseudo;
+        $this->total = $total;
+        $this->cumul = $cumul;
+    }
+
+    public function getHash()
+    {
+        return $this->hash;
+    }
+
+    public function getEmail()
+    {
+        return $this->email;
+    }
+
+    public function getPseudo()
+    {
+        return $this->pseudo;
+    }
+
+    public function getTotal()
+    {
+        return $this->total;
+    }
+
+    public function getCumul()
+    {
+        return $this->cumul;
+    }
+}
diff --git a/src/LQDN/Command/UserUpdateCumulCommand.php b/src/LQDN/Command/UserUpdateCumulCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..ced725fa90ee7226867b51ed78b7f77461c4b988
--- /dev/null
+++ b/src/LQDN/Command/UserUpdateCumulCommand.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LQDN\Command;
+
+class UserUpdateCumulCommand
+{
+    private $id;
+    private $cumul;
+
+    public function __construct($id, $cumul)
+    {
+        $this->id = $id;
+        $this->cumul = $cumul;
+    }
+
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    public function getCumul()
+    {
+        return $this->cumul;
+    }
+}
diff --git a/src/LQDN/Command/UserUpdateTotalCommand.php b/src/LQDN/Command/UserUpdateTotalCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..dc098074edeec27f0fe372dc2959b20690aa9a94
--- /dev/null
+++ b/src/LQDN/Command/UserUpdateTotalCommand.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LQDN\Command;
+
+class UserUpdateTotalCommand
+{
+    private $id;
+    private $total;
+
+    public function __construct($id, $total)
+    {
+        $this->id = $id;
+        $this->total = $total;
+    }
+
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    public function getTotal()
+    {
+        return $this->total;
+    }
+}
diff --git a/src/LQDN/Container.php b/src/LQDN/Container.php
index 8a677111154a2aa7ef8ef7f440a86b08b9ecf43a..700a996f06849a2cd894a9a44d63f0070f47bbeb 100644
--- a/src/LQDN/Container.php
+++ b/src/LQDN/Container.php
@@ -56,6 +56,7 @@ class Container extends BaseContainer
                 return new CommandHandler([
                     new Handler\AddressHandler($c['db']),
                     new Handler\DonationHandler($c['db']),
+                    new Handler\CounterpartHandler($c['db']),
                     new Handler\AdminHandler($c['db']),
                     new Handler\UserHandler($c['db']),
                 ]);
diff --git a/src/LQDN/Finder/AddressFinder.php b/src/LQDN/Finder/AddressFinder.php
index eea114f7216688dfce24bf77ca4eca3b61344325..f3a395549a09031459f96d8e73db3b5e6a3d0cd1 100644
--- a/src/LQDN/Finder/AddressFinder.php
+++ b/src/LQDN/Finder/AddressFinder.php
@@ -27,4 +27,19 @@ class AddressFinder
         $addresse = $stmt->fetch();
         return $addresse;
     }
+
+    /**
+     * Return adresses linked to a counterpart
+     *
+     * @param mixed $counterpartId
+     *
+     * @return array
+     */
+    public function findByCounterpartId($counterpartId)
+    {
+        $counterpartId = (int) $counterpartId;
+        $stmt = $this->connection->executeQuery('SELECT * FROM adresses WHERE user_id = :user_id', ['user_id' => $counterpartId]);
+        $addresse = $stmt->fetch();
+        return $addresse;
+    }
 }
diff --git a/src/LQDN/Finder/CounterpartFinder.php b/src/LQDN/Finder/CounterpartFinder.php
index 19d3a814d5db718cc7350b0f81b3fda500682911..b566c55af7d5b1b250b2846a33d8388d0effdcf7 100644
--- a/src/LQDN/Finder/CounterpartFinder.php
+++ b/src/LQDN/Finder/CounterpartFinder.php
@@ -56,4 +56,91 @@ EOQ;
 
         return $counterparts;
     }
+
+    /**
+     * Return all counterparts in a specific status
+     *
+     * @param mixed $status
+     *
+     * @return array
+     */
+    public function findByStatus($status)
+    {
+        $status = (int) $status;
+        $counterparts = [];
+        $stmt = $this->connection->executeQuery('SELECT * FROM contreparties WHERE status = :status', ['status' => $status]);
+        while ($counterpart = $stmt->fetch()) {
+            $counterpart['pdf_id'] = '';
+            $counterpart['pdf_nom'] = '';
+            $counterpart['pdf_url'] = '';
+
+            // Of course, piplomes are messy
+            // @TODO: This part is probably not working.
+            if ('piplome' === $counterpart['quoi']) {
+                $query = <<<EOQ
+SELECT d.id as id, a.nom as pseudo, d.pdf as pdf
+FROM dons d
+JOIN adresses a ON a.id = d.adresse_id
+JOIN contreparties c ON c.id = d.taille
+WHERE d.taille = :size
+EOQ;
+
+                $pdf = $this->connection->fetchAssoc($query, [
+                    'size' => $counterpart['taille']
+                ]);
+                if (false !== $pdf) {
+                    $counterpart['pdf_id'] = $pdf['id'];
+                    $counterpart['pdf_nom'] = $pdf['pseudo'];
+                    $counterpart['pdf_url'] = $pdf['pdf'];
+                }
+            }
+
+            $counterparts[$counterpart['id']] = $counterpart;
+        }
+
+        return $counterparts;
+    }
+
+    /** Return all counterparts by quoi
+     *
+     * @param mixed $quoi
+     *
+     * @return array
+     */
+    public function findByQuoi($quoi)
+    {
+        $quoi = (string) $quoi;
+        $counterparts = [];
+        $stmt = $this->connection->executeQuery('SELECT * FROM contreparties WHERE quoi = :quoi', ['quoi' => $quoi]);
+        while ($counterpart = $stmt->fetch()) {
+            $counterpart['pdf_id'] = '';
+            $counterpart['pdf_nom'] = '';
+            $counterpart['pdf_url'] = '';
+
+            // Of course, piplomes are messy
+            // @TODO: This part is probably not working.
+            if ('piplome' === $counterpart['quoi']) {
+                $query = <<<EOQ
+SELECT d.id as id, a.nom as pseudo, d.pdf as pdf
+FROM dons d
+JOIN adresses a ON a.id = d.adresse_id
+JOIN contreparties c ON c.id = d.taille
+WHERE d.taille = :size
+EOQ;
+
+                $pdf = $this->connection->fetchAssoc($query, [
+                    'size' => $counterpart['taille']
+                ]);
+                if (false !== $pdf) {
+                    $counterpart['pdf_id'] = $pdf['id'];
+                    $counterpart['pdf_nom'] = $pdf['pseudo'];
+                    $counterpart['pdf_url'] = $pdf['pdf'];
+                }
+            }
+
+            $counterparts[$counterpart['id']] = $counterpart;
+        }
+
+        return $counterparts;
+    }
 }
diff --git a/src/LQDN/Finder/DonationFinder.php b/src/LQDN/Finder/DonationFinder.php
index d65f779c081a9d5546374dce4744f266c9ac3edf..b2ff9feb01ec19fd6203ece4cc90331eac579894 100644
--- a/src/LQDN/Finder/DonationFinder.php
+++ b/src/LQDN/Finder/DonationFinder.php
@@ -53,6 +53,7 @@ SELECT d.id as id,
     d.status AS status,
     d.user_id AS user_id,
     u.email AS email,
+    u.pseudo AS pseudo,
     a.nom AS nom,
     a.adresse AS adresse,
     a.adresse2 AS adresse2,
diff --git a/src/LQDN/Finder/UserFinder.php b/src/LQDN/Finder/UserFinder.php
index 443158955e3cafbc01bb49c07bb57dc9052717c7..646e2af707f12aa5954989cca8ef32f19f6a3ede 100644
--- a/src/LQDN/Finder/UserFinder.php
+++ b/src/LQDN/Finder/UserFinder.php
@@ -25,6 +25,18 @@ class UserFinder
         return $this->connection->fetchAssoc("SELECT * FROM users WHERE id = :id", ['id' => (int) $id]);
     }
 
+    /**
+     * findByEmail
+     *
+     * @param mixed $email
+     *
+     * @return []
+     */
+    public function findByEmail($email)
+    {
+        return $this->connection->fetchAssoc("SELECT * FROM users WHERE email = :email", ['email' => $email]);
+    }
+
     /**
      * The search from the admin.
      *
@@ -40,7 +52,7 @@ class UserFinder
         $params = [];
 
         if ('' !== $text) {
-            $query .= " AND (pseudo LIKE :text OR email LIKE :text)";
+            $query .= " AND (pseudo LIKE :text OR email LIKE :text OR id LIKE :text)";
             $params['text'] = "%$text%";
         }
 
diff --git a/src/LQDN/Handler/AddressHandler.php b/src/LQDN/Handler/AddressHandler.php
index efb393db8775c64faed0bcd9792a0b88d1267520..cbc247ffbdd087a00037f2b71e3508b3fa20af04 100644
--- a/src/LQDN/Handler/AddressHandler.php
+++ b/src/LQDN/Handler/AddressHandler.php
@@ -67,7 +67,6 @@ EOF;
      * Check if an address already exists.
      *
      * @param int $userId
-     * @param string $alias
      *
      * @return bool
      */
diff --git a/src/LQDN/Handler/CounterpartHandler.php b/src/LQDN/Handler/CounterpartHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef4b4af5812f3c83194bc22317880cda2d1a0009
--- /dev/null
+++ b/src/LQDN/Handler/CounterpartHandler.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace LQDN\Handler;
+
+use Doctrine\DBAL\Connection;
+use LQDN\Command\CounterpartCreateCommand;
+use LQDN\Command\CounterpartDeleteCommand;
+use LQDN\Command\CounterpartChangeStateCommand;
+use LQDN\Exception\CounterpartAlreadyExistsException;
+
+class CounterpartHandler
+{
+    private $connection;
+
+    public function __construct(Connection $connection)
+    {
+        $this->connection = $connection;
+    }
+
+    /**
+     * Delete a counterpart
+     *
+     * @param CounterpartDeleteCommand $command
+     */
+    public function handleCounterpartDeleteCommand(CounterpartDeleteCommand $command)
+    {
+        $counterpartId = $command->getCounterpartId();
+        // Let's check if the counterpart exist
+        $this->connection->executeUpdate(
+            "DELETE FROM contreparties WHERE id = :id",
+            ['id' => $counterpartId]
+        );
+    }
+
+    /**
+     * Create a counterpart
+     *
+     * @param CounterpartCreateCommand $command
+     */
+    public function handleCounterpartCreateCommand(CounterpartCreateCommand $command)
+    {
+        $userId = $command->getUserId();
+        $adresseId = $command->getAddressId();
+
+        $query =<<<EOF
+INSERT INTO contreparties(datec, user_id, adresse_id, quoi, taille, status, commentaire)
+VALUES (:datec, :user_id, :adresse_id, :quoi, :taille, :status, :commentaire)
+EOF;
+        $stmt = $this->connection->prepare($query);
+        $stmt->bindValue('datec', $command->getDateCreation());
+        $stmt->bindValue('user_id', $command->getUserId());
+        $stmt->bindValue('adresse_id', $command->getAddressId());
+        $stmt->bindValue('quoi', $command->getQuoi());
+        $stmt->bindValue('taille', $command->getTaille());
+        $stmt->bindValue('status', $command->getStatus());
+        $stmt->bindValue('commentaire', $command->getCommentaire());
+        $stmt->execute();
+    }
+
+    /**
+     * Chnge the state of a counterpart
+     *
+     * @param CounterpartChangeStateCommand $command
+     */
+    public function handleCounterpartChangeStateCommand(CounterpartChangeStateCommand $command)
+    {
+        $counterpartId = $command->getCounterpartId();
+        $status = $command->getState();
+
+        $this->connection->executeUpdate(
+            "UPDATE contreparties SET status = :status WHERE id=:id",
+            [
+                'status' => $status,
+                'id' => $counterpartId,
+            ]
+        );
+    }
+
+    /**
+     * Test if a counterpart exists
+     *
+     * @param int $counterpartId
+     *
+     * @return bool
+     */
+    private function counterpartExists($counterpartId)
+    {
+        return (bool) $this->connection->fetchColumn(
+            "SELECT 1 FROM contreparties WHERE id = :counterpart_id",
+            [
+                'counterpart_id' => $counterpartId,
+            ],
+            0
+        );
+    }
+
+    /**
+     * Test if the counterpart can be deleted
+     *
+     * @param int $countepartId
+     *
+     * @return bool
+     */
+    private function counterpartUsed($counterpartId)
+    {
+        $status = (int) $this->connection->fetchColumn(
+            "SELECT status FROM contreparties WHERE id = :id",
+            [
+                'id' => $counterpartId,
+            ],
+            0
+        );
+        return ($status == 2); // status 2 is delivered counterparts
+    }
+}
diff --git a/src/LQDN/Handler/DonationHandler.php b/src/LQDN/Handler/DonationHandler.php
index 94dad2e9972cf7e68ae46bbea63132fa712a839f..34b17e8e2d725c82622df4045487b0b7feea8843 100644
--- a/src/LQDN/Handler/DonationHandler.php
+++ b/src/LQDN/Handler/DonationHandler.php
@@ -3,6 +3,7 @@
 namespace LQDN\Handler;
 
 use Doctrine\DBAL\Connection;
+use LQDN\Command\DonationCreateCommand;
 use LQDN\Command\DonationInvalidateCommand;
 use LQDN\Command\DonationResetPdfCommand;
 use LQDN\Command\DonationValidateCommand;
@@ -16,6 +17,27 @@ class DonationHandler
         $this->connection = $connection;
     }
 
+    /**
+     * Create a donation
+     *
+     * @param DonationCreateCommand $command
+     */
+    public function handleDonationCreateCommand(DonationCreateCommand $command)
+    {
+        $query =<<<EOF
+INSERT INTO dons(status, datec, somme, user_id, public, cumul)
+VALUES(:status, :datec, :somme, :user_id, :public, :cumul)
+EOF;
+        $stmt = $this->connection->prepare($query);
+        $stmt->bindvalue('status', $command->getStatus());
+        $stmt->bindvalue('datec', $command->getDateC());
+        $stmt->bindvalue('somme', $command->getSomme());
+        $stmt->bindvalue('user_id', $command->getUserId());
+        $stmt->bindvalue('public', $command->getPublic());
+        $stmt->bindvalue('cumul', $command->getCumul());
+        $stmt->execute();
+    }
+
     /**
      * Validate a donation.
      *
diff --git a/src/LQDN/Handler/UserHandler.php b/src/LQDN/Handler/UserHandler.php
index 5f13a683f304c038fa0b8830198bf7407403c8d2..e88b958b19bdb564eb2ae6f8f1a09ba0f1203851 100644
--- a/src/LQDN/Handler/UserHandler.php
+++ b/src/LQDN/Handler/UserHandler.php
@@ -4,6 +4,9 @@ namespace LQDN\Handler;
 
 use Doctrine\DBAL\Connection;
 use LQDN\Command\UserUpdateByAdminCommand;
+use LQDN\Command\UserUpdateTotalCommand;
+use LQDN\Command\UserUpdateCumulCommand;
+use LQDN\Command\UserCreateCommand;
 
 class UserHandler
 {
@@ -28,4 +31,52 @@ class UserHandler
             'id' => $command->getId(),
         ]);
     }
+
+    /**
+     * Create a user in database
+     *
+     * @param UserCreateCommand $command
+     */
+    public function handleUserCreateCommand(UserCreateCommand $command)
+    {
+        $stmt = $this->connection->prepare('INSERT INTO users(email, hash, pseudo, total, cumul) VALUES (:email, :hash, :pseudo, :total, :cumul)');
+        $stmt->bindValue('email', $command->getEmail());
+        $stmt->bindValue('hash', $command->getHash());
+        $stmt->bindValue('pseudo', $command->getPseudo());
+        $stmt->bindValue('total', $command->getTotal());
+        $stmt->bindValue('cumul', $command->getCumul());
+        $stmt->execute();
+    }
+
+    /**
+     * Update the user total
+     *
+     * @param UserUpdateTotalCommand $command
+     */
+    public function handleUserUpdateTotalCommand(UserUpdateTotalCommand $command)
+    {
+        $this->connection->executeUpdate(
+            'UPDATE users SET total = :total WHERE id = :id',
+            [
+                'total' => $command->getTotal(),
+                'id'=> $command->getId()
+            ]
+        );
+    }
+
+    /**
+     * Update the user cumul
+     *
+     * @param UserUpdateCumulCommand $command
+     */
+    public function handleUserUpdateCumulCommand(UserUpdateCumulCommand $command)
+    {
+        $this->connection->executeUpdate(
+            'UPDATE users SET cumul = :cumul WHERE id = :id',
+            [
+                'cumul' => $command->getCumul(),
+                'id' => $command->getId(),
+            ]
+        );
+    }
 }
diff --git a/tests/functional/Finder/AddressFinderTest.php b/tests/functional/Finder/AddressFinderTest.php
index e9a1b2f163fcb50309092ff386da1ea549f69154..117706e1a8a8e0f06648322478da3d50116e9e01 100644
--- a/tests/functional/Finder/AddressFinderTest.php
+++ b/tests/functional/Finder/AddressFinderTest.php
@@ -25,4 +25,24 @@ class AddressFinderTest extends FunctionalTest
         ];
         $this->assertEquals($expectedAddress, $addresse);
     }
+
+    public function testFindByCounterpartId()
+    {
+        $addresse = $this->container['address_finder']->findByCounterpartId(1);
+        $this->assertCount(9, $addresse);
+
+        // Check the address have an ID of 1
+        $expectedAddress = [
+            'id' => '1',
+            'nom' => 'Main',
+            'adresse' => '1 rue Ménars',
+            'adresse2' => null,
+            'codepostal' => '75001',
+            'ville' => 'Paris',
+            'etat' => null,
+            'pays' => 'France',
+            'user_id' => '1',
+        ];
+        $this->assertEquals($expectedAddress, $addresse);
+     }
 }
diff --git a/tests/functional/Finder/CounterpartFinderTest.php b/tests/functional/Finder/CounterpartFinderTest.php
index 8f2a15cb6303ef300fe417530857973457258fdf..2eec470acfccbb66d06a9bfef9d6c73c4877af21 100644
--- a/tests/functional/Finder/CounterpartFinderTest.php
+++ b/tests/functional/Finder/CounterpartFinderTest.php
@@ -29,4 +29,50 @@ class CounterpartFinderTest extends FunctionalTest
         ];
         $this->assertEquals($expectedCounterpart, $firstCounterpart);
     }
+
+    public function testFindByQuoi()
+    {
+        $counterparts = $this->container['counterpart_finder']->findByQuoi('piplome');
+        $this->assertCount(1, $counterparts);
+        $firstCounterpart = reset($counterparts);
+
+        // Check the first counterpart
+        $expectedCounterpart = [
+            'id' => '2',
+            'user_id' => '2',
+            'datec' => '2016-06-22 12:34:00',
+            'quoi' => 'piplome',
+            'taille' => '2',
+            'status' => '2',
+            'adresse_id' => null,
+            'pdf_id' => '1',
+            'pdf_nom' => 'Main',
+            'pdf_url' => 'pdf',
+            'commentaire' => '',
+        ];
+        $this->assertEquals($expectedCounterpart, $firstCounterpart);
+
+    }
+
+    public function testFindById()
+    {
+        $counterparts = $this->container['counterpart_finder']->findByStatus(1);
+        $this->assertCount(1, $counterparts);
+
+        $firstCounterpart = reset($counterparts);
+        $expectedCounterpart = [
+            'id' => '1',
+            'datec' => '2016-06-22 12:34:00',
+            'user_id' => '1',
+            'quoi' => 'pishirt', // [piplome|pibag|pishirt|hoodie]
+            'taille' => '8',
+            'status' => '1',
+            'adresse_id' => '1',
+            'pdf_id' => '',
+            'pdf_nom' => '',
+            'pdf_url' => '',
+            'commentaire' => '',
+        ];
+        $this->assertEquals($expectedCounterpart, $firstCounterpart);
+    }
 }
diff --git a/tests/functional/Finder/UserFinderTest.php b/tests/functional/Finder/UserFinderTest.php
index 3c9a2414fd6d1e69bc2cdc373eae2e2eec823a0a..923a3a954537e5207db02d5e8212de08a8941622 100644
--- a/tests/functional/Finder/UserFinderTest.php
+++ b/tests/functional/Finder/UserFinderTest.php
@@ -24,6 +24,24 @@ class UserFinderTest extends FunctionalTest
         $this->assertEquals($expectedUser, $user);
     }
 
+    public function testFindByEmail()
+    {
+        $user = $this->container['user_finder']->findByEmail('alice@example.org');
+
+        $expectedUser = [
+            'id' => '1',
+            'status' => '1',
+            'hash' => '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8',
+            'cumul' => '2000',
+            'email' => 'alice@example.org',
+            'total' => '5000',
+            'pseudo' => 'Alice',
+            'expiration' => null,
+            'commentaire' => 'RAS',
+        ];
+        $this->assertEquals($expectedUser, $user);
+    }
+
     public function testAdminSearch()
     {
         $this->assertCount(1, $this->container['user_finder']->adminSearch($text='alice@example.org', $status=''));
diff --git a/tests/functional/Handler/CounterpartHandlerTest.php b/tests/functional/Handler/CounterpartHandlerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecce1a68266e9bba61bcb9f6719752f8a9d25324
--- /dev/null
+++ b/tests/functional/Handler/CounterpartHandlerTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace LQDN\Tests\Functional\Handler;
+
+use LQDN\Command\CounterpartCreateCommand;
+use LQDN\Command\CounterpartDeleteCommand;
+use LQDN\Command\CounterpartChangeStateCommand;
+use LQDN\Handler\CounterpartHandler;
+use LQDN\Tests\Functional\FunctionalTest;
+
+class CounterpartHandlerTest extends FunctionalTest
+{
+    public function testCounterpartDelete()
+    {
+        $this->assertTrue($this->counterpartExists(1));
+
+        $this->container['command_handler']->handle(new CounterpartDeleteCommand(1));
+    }
+
+    public function testCounterpartCreate()
+    {
+        $this->assertFalse($this->counterpartExists(3));
+
+        $this->container['command_handler']->handle(new CounterpartCreateCommand(1, 1, 'pishirt', 4, 1, date("Y-m-d H:i:s"), ''));
+    }
+
+    public function testCounterpartChangeState()
+    {
+        $this->assertTrue($this->counterpartExists(1));
+
+        $this->container['command_handler']->handle(new CounterpartChangeStateCommand(1, 2));
+    }
+
+    /**
+     * Check if a counterpart exists in BDD
+     *
+     * @param int $id
+     *
+     * @return bool
+     */
+    private function counterpartExists($id)
+    {
+        return (bool) $this->container['db']->fetchColumn("SELECT 1 FROM contreparties WHERE id = $id");
+    }
+}
diff --git a/tests/functional/Handler/DonationHandlerTest.php b/tests/functional/Handler/DonationHandlerTest.php
index e54a4867683a093981a72471e6f6da259ab04392..dec818a9d3ff73107e850673408901a0d0d3712e 100644
--- a/tests/functional/Handler/DonationHandlerTest.php
+++ b/tests/functional/Handler/DonationHandlerTest.php
@@ -5,6 +5,7 @@ namespace LQDN\Tests\Functional\Handler;
 use LQDN\Command\DonationInvalidateCommand;
 use LQDN\Command\DonationResetPdfCommand;
 use LQDN\Command\DonationValidateCommand;
+use LQDN\Command\DonationCreateCommand;
 use LQDN\Tests\Functional\FunctionalTest;
 
 class DonationHandlerTest extends FunctionalTest
@@ -32,6 +33,13 @@ class DonationHandlerTest extends FunctionalTest
         $this->assertEquals(2, $this->getDonationByUser(2)[0]['user_id']);
     }
 
+    public function testDonationCreateCommand()
+    {
+        $this->container['command_handler']->handle(new DonationCreateCommand(1, 1, date("Y-m-d H:M:s"), 50, 0, 0));
+
+    }
+
+
     /**
      * Retrieve a donation
      *
diff --git a/tests/functional/Handler/UserHandlerTest.php b/tests/functional/Handler/UserHandlerTest.php
index 3e0f652ffea00b1470016cd19eca9cb0e80a1466..5162d26af5eb1b8ce3f649875ebb7240cf61499d 100644
--- a/tests/functional/Handler/UserHandlerTest.php
+++ b/tests/functional/Handler/UserHandlerTest.php
@@ -3,6 +3,9 @@
 namespace LQDN\Tests\Functional\Handler;
 
 use LQDN\Command\UserUpdateByAdminCommand;
+use LQDN\Command\UserUpdateTotalCommand;
+use LQDN\Command\UserUpdateCumulCommand;
+use LQDN\Command\UserCreateCommand;
 use LQDN\Tests\Functional\FunctionalTest;
 
 class UserHandlerTest extends FunctionalTest
@@ -22,6 +25,27 @@ class UserHandlerTest extends FunctionalTest
         $this->assertSame('This is foobar avé dé accênts !', $user['commentaire']);
     }
 
+    public function testUserCreateCommand()
+    {
+        $this->container['command_handler']->handle(new UserCreateCommand('eve@example.org', 'not a hash', 'Eve', 0, 0));
+    }
+
+    public function testUserUpdateTotal()
+    {
+        $this->container['command_handler']->handle(new UserUpdateTotalCommand(1, 600));
+        $user = $this->getUser(1);
+
+        $this->assertSame(600, (int) $user['total']);
+    }
+
+    public function testUserUpdateCumul()
+    {
+        $this->container['command_handler']->handle(new UserUpdateCumulCommand(1, 600));
+        $user = $this->getUser(1);
+
+        $this->assertSame(600, (int) $user['cumul']);
+    }
+
     /**
      * Retrieve a given user.
      *
diff --git a/www/static/css/custom.css b/www/static/css/custom.css
index 67c89a56dfaaedb20ee7f1b884b730d30c7d8728..928c8b820a975653a3eacf66703312ae334a828c 100644
--- a/www/static/css/custom.css
+++ b/www/static/css/custom.css
@@ -243,6 +243,11 @@ transform: rotate(-90deg);
 .addressmodal {
     padding-left:15px;
 }
+#messages {
+width: 77%;
+margin: auto;
+z-index: 99999;
+}
 
 /* Problèmes de css à répercuter plus tard */
 .col-md- { /* marge gauche arbitraire qui semblait destinée à centrer : .col-md-offset-1 { margin-left: 8.33333333%;} dans bootstrap.css ligne 2086 */