From 780291f864c4dca01a800fdbb80435630d567701 Mon Sep 17 00:00:00 2001
From: Alexis POYEN <apoyen@grandlyon.com>
Date: Mon, 17 Aug 2020 09:56:30 +0200
Subject: [PATCH] Fix : when posting a vote that already exist: update it

PUT API is no more needed
---
 internal/models/vote.go           | 139 ++++++++----------------------
 internal/rootmux/admin_test.go    |   2 +-
 internal/rootmux/capturer_test.go |   2 +-
 internal/rootmux/rootmux_test.go  |  16 +---
 web/components/vote/votes.js      |   8 +-
 5 files changed, 44 insertions(+), 123 deletions(-)

diff --git a/internal/models/vote.go b/internal/models/vote.go
index f4caf7a..72d07f5 100644
--- a/internal/models/vote.go
+++ b/internal/models/vote.go
@@ -36,11 +36,7 @@ func (d *DataHandler) handleVote(w http.ResponseWriter, r *http.Request) {
 
 	case "PUT":
 		switch auth.GetLoggedUserTechnical(w, r).Role {
-		case "ADMIN":
-			d.putVote(w, r)
-		case "CAPTURER":
-			d.putVoteCapturer(w, r)
-		case "VISUALIZER":
+		case "ADMIN", "CAPTURER", "VISUALIZER":
 			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
 		default:
 			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
@@ -104,36 +100,6 @@ func (d *DataHandler) postVoteCapturer(w http.ResponseWriter, r *http.Request) {
 }
 
 func (d *DataHandler) addVote(w http.ResponseWriter, r *http.Request, o Vote) {
-	var voteFound Vote
-	if o.Blank {
-		d.db.First(&voteFound, "desk_round_id = ? AND blank = ?", o.DeskRoundID, o.Blank)
-		if voteFound.ID != 0 {
-			http.Error(w, ErrorVoteExist, http.StatusInternalServerError)
-			return
-		}
-	} else if o.NullVote {
-		d.db.First(&voteFound, "desk_round_id = ? AND null_vote = ?", o.DeskRoundID, o.NullVote)
-		if voteFound.ID != 0 {
-			http.Error(w, ErrorVoteExist, http.StatusInternalServerError)
-			return
-		}
-	} else {
-		d.db.First(&voteFound, "desk_round_id = ? AND candidate_list_id = ?", o.DeskRoundID, o.CandidateListID)
-		if voteFound.ID != 0 {
-			http.Error(w, ErrorVoteExist, http.StatusInternalServerError)
-			return
-		}
-	}
-
-	if !o.Blank && !o.NullVote {
-		// Check that CandidateListID exist
-		var candidateList CandidateList
-		if err := d.db.First(&candidateList, o.CandidateListID).Error; err != nil {
-			http.Error(w, ErrorParentNotFound, http.StatusInternalServerError)
-			return
-		}
-	}
-
 	// Check that deskRound exist
 	var deskRound DeskRound
 	if err := d.db.Preload("Votes").First(&deskRound, o.DeskRoundID).Error; err != nil {
@@ -145,79 +111,46 @@ func (d *DataHandler) addVote(w http.ResponseWriter, r *http.Request, o Vote) {
 		return
 	}
 
-	d.db.Create(&o)
-	d.db.Last(&o)
-	json.NewEncoder(w).Encode(o)
-}
-
-func (d *DataHandler) putVote(w http.ResponseWriter, r *http.Request) {
-	var vote Vote
-	err := json.NewDecoder(r.Body).Decode(&vote)
-	if err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
-		return
-	}
-	d.updateVote(w, r, vote)
-
-}
-
-func (d *DataHandler) putVoteCapturer(w http.ResponseWriter, r *http.Request) {
-	var o Vote
-	err := json.NewDecoder(r.Body).Decode(&o)
-	if err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
-		return
-	}
-
-	var flag = false
-	var capturer = d.getLoggedUser(w, r).(Capturer)
-	for _, deskRound := range capturer.DeskRounds {
-		if deskRound.ID == o.DeskRoundID {
-			flag = true
-		}
-	}
-	if flag {
-		d.updateVote(w, r, o)
-	} else {
-		http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
-		return
-	}
-}
-
-func (d *DataHandler) updateVote(w http.ResponseWriter, r *http.Request, vote Vote) {
-
-	var deskRound DeskRound
-	if err := d.db.First(&deskRound, vote.DeskRoundID).Error; err != nil {
-		http.Error(w, ErrorParentNotFound, http.StatusNotFound)
-		return
-	}
-	if deskRound.Validated {
-		http.Error(w, ErrorValidatedVote, http.StatusInternalServerError)
-		return
-	}
-
-	var o Vote
-	if vote.Blank {
-		if err := d.db.Where("blank = true  and desk_round_id = ?", vote.DeskRoundID).Find(&o).Error; err != nil {
-			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
-			return
+	var voteFound Vote
+	if o.Blank {
+		d.db.First(&voteFound, "desk_round_id = ? AND blank = ?", o.DeskRoundID, o.Blank)
+		if voteFound.ID != 0 {
+			voteFound.VoiceNumber = o.VoiceNumber
+			d.db.Save(&voteFound)
+			json.NewEncoder(w).Encode(voteFound)
+		} else {
+			d.db.Create(&o)
+			d.db.Last(&o)
+			json.NewEncoder(w).Encode(o)
 		}
-	} else if vote.NullVote {
-		if err := d.db.Where("null_vote = true  and desk_round_id = ?", vote.DeskRoundID).Find(&o).Error; err != nil {
-			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
-			return
+	} else if o.NullVote {
+		d.db.First(&voteFound, "desk_round_id = ? AND null_vote = ?", o.DeskRoundID, o.NullVote)
+		if voteFound.ID != 0 {
+			voteFound.VoiceNumber = o.VoiceNumber
+			d.db.Save(&voteFound)
+			json.NewEncoder(w).Encode(voteFound)
+		} else {
+			d.db.Create(&o)
+			d.db.Last(&o)
+			json.NewEncoder(w).Encode(o)
 		}
 	} else {
-		if err := d.db.Where("candidate_list_id = ?  and desk_round_id = ?", vote.CandidateListID, vote.DeskRoundID).Find(&o).Error; err != nil {
-			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
-			return
+		d.db.First(&voteFound, "desk_round_id = ? AND candidate_list_id = ?", o.DeskRoundID, o.CandidateListID)
+		if voteFound.ID != 0 {
+			voteFound.VoiceNumber = o.VoiceNumber
+			d.db.Save(&voteFound)
+			json.NewEncoder(w).Encode(voteFound)
+		} else {
+			var candidateList CandidateList
+			if err := d.db.First(&candidateList, o.CandidateListID).Error; err != nil {
+				http.Error(w, ErrorParentNotFound, http.StatusInternalServerError)
+				return
+			}
+			d.db.Create(&o)
+			d.db.Last(&o)
+			json.NewEncoder(w).Encode(o)
 		}
 	}
-
-	o.VoiceNumber = vote.VoiceNumber
-	d.db.Save(&o)
-	json.NewEncoder(w).Encode(o)
-
 }
 
 func (d *DataHandler) deleteVote(w http.ResponseWriter, r *http.Request, id int) {
diff --git a/internal/rootmux/admin_test.go b/internal/rootmux/admin_test.go
index 9e2ae85..554015f 100644
--- a/internal/rootmux/admin_test.go
+++ b/internal/rootmux/admin_test.go
@@ -124,7 +124,7 @@ func AdminTests(t *testing.T) {
 		// Get Votes
 		do("GET", "/api/Vote/", xsrfHeader, ``, 200, `[{"ID":1,"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":158,"Blank":false,"NullVote":false}]`)
 		// Update a Vote
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":258,"Blank":false,"NullVote":false}`, 200, `{"ID":1,"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":258,"Blank":false,"NullVote":false}`)
+		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":258,"Blank":false,"NullVote":false}`, 405, `You're not authorize to execute this method on this ressource.`)
 
 		// Delete a Vote
 		do("DELETE", "/api/Vote/1", xsrfHeader, ``, 200, ``)
diff --git a/internal/rootmux/capturer_test.go b/internal/rootmux/capturer_test.go
index 335d887..8e0e864 100644
--- a/internal/rootmux/capturer_test.go
+++ b/internal/rootmux/capturer_test.go
@@ -139,7 +139,7 @@ func CapturerTests(t *testing.T) {
 		// Get Votes
 		do("GET", "/api/Vote/", xsrfHeader, ``, 200, `[{"ID":1,"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":158,"Blank":false,"NullVote":false},{"ID":2,"DeskRoundID":2,"CandidateListID":1,"VoiceNumber":103,"Blank":false,"NullVote":false},{"ID":3,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":3,"Blank":true,"NullVote":false}]`)
 		// Update a Vote
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"ID":1,"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":13,"Blank":true}`, 200, `{"ID":3,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":13,"Blank":true,"NullVote":false}`)
+		do("PUT", "/api/Vote/1", xsrfHeader, `{"ID":1,"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":13,"Blank":true}`, 405, `You're not authorize to execute this method on this ressource`)
 		// Delete a Vote
 		do("DELETE", "/api/Vote/1", xsrfHeader, ``, 200, ``)
 		// Can't add, update or delete a vote to a deskRound not affected
diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go
index 19e36dd..6a8fb30 100644
--- a/internal/rootmux/rootmux_test.go
+++ b/internal/rootmux/rootmux_test.go
@@ -111,27 +111,17 @@ func appTests(t *testing.T) {
 		do("POST", "/api/Vote", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":5,"NullVote":true}`, 200, `{"ID":4,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":5,"Blank":false,"NullVote":true}`)
 		do("GET", "/api/DeskRound/1", xsrfHeader, ``, 200, `{"ID":1,"RoundID":1,"DeskID":1,"Capturers":[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}],"Completed":true,"DateCompletion":"20`)
 
-		// Check to update the good vote
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":258,"Blank":false,"NullVote":false}`, 200, `{"ID":1,"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":258,"Blank":false,"NullVote":false}`)
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":158,"Blank":true,"NullVote":false}`, 200, `{"ID":3,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":158,"Blank":true,"NullVote":false}`)
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":158,"Blank":false,"NullVote":true}`, 200, `{"ID":4,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":158,"Blank":false,"NullVote":true}`)
-
-		// Can't add the same vote several time
-		do("POST", "/api/Vote", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":158}`, 500, `Error the vote have already been captured`)
-		do("POST", "/api/Vote", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":3,"Blank":true}`, 500, `Error the vote have already been captured`)
-		do("POST", "/api/Vote", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":null,"VoiceNumber":5,"NullVote":true}`, 500, `Error the vote have already been captured`)
-
 		// Update a DeskRound to Validated=true can only be done when votes are captured
 		do("PUT", "/api/DeskRound/1", xsrfHeader, `{"ID":1,"Validated":true}`, 200, `{"ID":1,"RoundID":1,"DeskID":1,"Capturers":[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}],"Completed":true,"DateCompletion":"20`)
 
 		// If DeskRound is validated, votes can't be updated or deleted
-		do("PUT", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":358,"Blank":false,"NullVote":false}`, 500, `Error the vote have already been validated and can't be updated`)
+		do("POST", "/api/Vote/1", xsrfHeader, `{"DeskRoundID":1,"CandidateListID":1,"VoiceNumber":358,"Blank":false,"NullVote":false}`, 500, `Error the vote have already been validated and can't be updated`)
 		do("DELETE", "/api/Vote/1", xsrfHeader, ``, 500, `Error the vote have already been validated and can't be updated`)
 
-		// //Check that on Vote deletion, deskRound is updated
+		// Check that on Vote deletion, deskRound is updated
 		do("PUT", "/api/DeskRound/1", xsrfHeader, `{"ID":1,"Validated":false}`, 200, `{"ID":1,"RoundID":1,"DeskID":1,"Capturers":[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}],"Completed":true,"DateCompletion":"20`)
 		do("DELETE", "/api/Vote/1", xsrfHeader, ``, 200, ``)
-		do("GET", "/api/DeskRound/1", xsrfHeader, ``, 200, `{"ID":1,"RoundID":1,"DeskID":1,"Capturers":[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}],"Completed":false,"DateCompletion":"0001-01-01T00:00:00Z","Validated":false,"Votes":[{"ID":3,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":158,"Blank":true,"NullVote":false},{"ID":4,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":158,"Blank":false,"NullVote":true}]}`)
+		do("GET", "/api/DeskRound/1", xsrfHeader, ``, 200, `{"ID":1,"RoundID":1,"DeskID":1,"Capturers":[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}],"Completed":false,"DateCompletion":"0001-01-01T00:00:00Z","Validated":false,"Votes":[{"ID":3,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":3,"Blank":true,"NullVote":false},{"ID":4,"DeskRoundID":1,"CandidateListID":0,"VoiceNumber":5,"Blank":false,"NullVote":true}]}`)
 
 		// Verify that on Desk deletion deskRounds are deleted
 		do("GET", "/api/Desk/1", xsrfHeader, ``, 200, `{"ID":1,"SectionID":1,"Name":"Desk 1","WitnessDesk":true,"Subscribed":9587,"DeskRounds":[{"ID":1,"RoundID":1,"DeskID":1,"Capturers":null,"Completed":false,"DateCompletion":"0001-01-01T00:00:00Z","Validated":false,"Votes":null}]}`)
diff --git a/web/components/vote/votes.js b/web/components/vote/votes.js
index 892607b..5a7d898 100644
--- a/web/components/vote/votes.js
+++ b/web/components/vote/votes.js
@@ -239,9 +239,7 @@ class Vote {
     let candidateLists = await this.updateCandidateLists();
     let votes = await this.updatesVotes();
 
-    let method;
-    if (votes.length == 0) method = "POST";
-    else method = "PUT";
+    let method = "POST";
 
     let flag = true;
     for (let candidateList of candidateLists) {
@@ -302,8 +300,8 @@ class Vote {
         this.DeskRoundID,
         null,
         parseInt(document.getElementById("null-vote-voice").value),
-        true,
-        false
+        false,
+        true
       );
     }
     this.refreshParent();
-- 
GitLab