diff --git a/studs.php b/studs.php
index 7311efa8fc952c86496cfbe9fdea2da3f2e06b1b..6070557dafebe5f67ecc648aade6b68cb81a360c 100644
--- a/studs.php
+++ b/studs.php
@@ -16,6 +16,8 @@
  * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
  * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
  */
+use Framadate\Exception\AlreadyExistsException;
+use Framadate\Exception\ConcurrentEditionException;
 use Framadate\Services\LogService;
 use Framadate\Services\PollService;
 use Framadate\Services\InputService;
@@ -121,6 +123,7 @@ if ($accessGranted) {
         $name = $inputService->filterName($_POST['name']);
         $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
         $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
+        $slots_hash = $inputService->filterMD5($_POST['control']);
 
         if (empty($editedVote)) {
             $message = new Message('danger', __('Error', 'Something is going wrong...'));
@@ -131,24 +134,29 @@ if ($accessGranted) {
 
         if ($message == null) {
             // Update vote
-            $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices);
-            if ($result) {
-                if ($poll->editable == Editable::EDITABLE_BY_OWN) {
-                    $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
-                    $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
-                    $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
-                    $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
+            try {
+                $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
+                if ($result) {
+                    if ($poll->editable == Editable::EDITABLE_BY_OWN) {
+                        $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
+                        $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
+                        $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
+                        $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
+                    } else {
+                        $message = new Message('success', __('studs', 'Update vote succeeded'));
+                    }
+                    $notificationService->sendUpdateNotification($poll, NotificationService::UPDATE_VOTE, $name);
                 } else {
-                    $message = new Message('success', __('studs', 'Update vote succeeded'));
+                    $message = new Message('danger', __('Error', 'Update vote failed'));
                 }
-                $notificationService->sendUpdateNotification($poll, NotificationService::UPDATE_VOTE, $name);
-            } else {
-                $message = new Message('danger', __('Error', 'Update vote failed'));
+            } catch (ConcurrentEditionException $cee) {
+                $message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
             }
         }
     } elseif (isset($_POST['save'])) { // Add a new vote
         $name = $inputService->filterName($_POST['name']);
         $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
+        $slots_hash = $inputService->filterMD5($_POST['control']);
 
         if ($name == null) {
             $message = new Message('danger', __('Error', 'The name is invalid.'));
@@ -159,19 +167,25 @@ if ($accessGranted) {
 
         if ($message == null) {
             // Add vote
-            $result = $pollService->addVote($poll_id, $name, $choices);
-            if ($result) {
-                if ($poll->editable == Editable::EDITABLE_BY_OWN) {
-                    $editedVoteUniqueId = $result->uniqId;
-                    $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
-                    $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
-                    $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
+            try {
+                $result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
+                if ($result) {
+                    if ($poll->editable == Editable::EDITABLE_BY_OWN) {
+                        $editedVoteUniqueId = $result->uniqId;
+                        $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId);
+                        $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
+                        $message = new Message('success', __('studs', 'Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:'), $urlEditVote);
+                    } else {
+                        $message = new Message('success', __('studs', 'Adding the vote succeeded'));
+                    }
+                    $notificationService->sendUpdateNotification($poll, NotificationService::ADD_VOTE, $name);
                 } else {
-                    $message = new Message('success', __('studs', 'Adding the vote succeeded'));
+                    $message = new Message('danger', __('Error', 'Adding vote failed'));
                 }
-                $notificationService->sendUpdateNotification($poll, NotificationService::ADD_VOTE, $name);
-            } else {
-                $message = new Message('danger', __('Error', 'Adding vote failed'));
+            } catch (AlreadyExistsException $aee) {
+                $message = new Message('danger', __('Error', 'You already voted'));
+            } catch (ConcurrentEditionException $cee) {
+                $message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
             }
         }
     }
@@ -191,6 +205,7 @@ $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
 $smarty->assign('expired', strtotime($poll->end_date) < time());
 $smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400);
 $smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots);
+$smarty->assign('slots_hash',  $pollService->hashSlots($slots));
 $smarty->assign('votes', $pollService->splitVotes($votes));
 $smarty->assign('best_choices', $pollService->computeBestChoices($votes));
 $smarty->assign('comments', $comments);