From 81caf39ae2abdb81db8f26d6423f8d1b7811802f Mon Sep 17 00:00:00 2001 From: Sep Date: Wed, 9 Apr 2025 13:51:39 +0330 Subject: [PATCH 1/2] logging vote history --- database/db_helper/vote_helper.go | 1 - database/helper.go | 8 +++++++ .../answer_handler/answer_vote_handler.go | 21 +++++++++++++++++++ .../question_handler/question_vote_handler.go | 21 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/database/db_helper/vote_helper.go b/database/db_helper/vote_helper.go index 2a74321..2fd3a54 100644 --- a/database/db_helper/vote_helper.go +++ b/database/db_helper/vote_helper.go @@ -30,7 +30,6 @@ func VoteDownQuestion(question *models.Question) error { if err := tx.Model(&question).Update("votes", gorm.Expr("votes - ?", 1)).Error; err != nil { return fmt.Errorf("failed to downvote: %w", err) } - return nil }) return err diff --git a/database/helper.go b/database/helper.go index f6b899e..7fa4170 100644 --- a/database/helper.go +++ b/database/helper.go @@ -2,6 +2,7 @@ package database import ( "Learning/models" + "fmt" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" "strconv" @@ -62,3 +63,10 @@ func CreateUser(user models.UserRegister) *string { } return nil } + +func SaveLog(log *models.Log) { + loggingResult := DB.Create(log) + if loggingResult.Error != nil { + fmt.Printf("failed to save log %s\n", loggingResult.Error.Error()) + } +} diff --git a/handlers/answer_handler/answer_vote_handler.go b/handlers/answer_handler/answer_vote_handler.go index 506e5b2..be713da 100644 --- a/handlers/answer_handler/answer_vote_handler.go +++ b/handlers/answer_handler/answer_vote_handler.go @@ -5,6 +5,7 @@ import ( "Learning/database/db_helper" "Learning/helper" "Learning/models" + "fmt" "github.com/gin-gonic/gin" "net/http" "strconv" @@ -42,6 +43,15 @@ func VoteUpAnswer(c *gin.Context) { c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Transaction failed", "error": err.Error()}) return } + log := models.Log{ + UserID: uint(user.UserId), + Action: "vote_up", + EntityType: "answer", + EntityID: uint(answer.AnswerId), + ReputationChange: -10, + Description: fmt.Sprintf("User gained 10 reputation for vote up on answer %d", answer.AnswerId), + } + database.SaveLog(&log) c.IndentedJSON(http.StatusOK, gin.H{"message": "answer voted up"}) } @@ -77,5 +87,16 @@ func VoteDownAnswer(c *gin.Context) { c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Transaction failed", "error": err.Error()}) return } + + log := models.Log{ + UserID: uint(user.UserId), + Action: "vote_down", + EntityType: "answer", + EntityID: uint(answer.AnswerId), + ReputationChange: -10, + Description: fmt.Sprintf("User lost 10 reputation for vote down on answer %d", answer.AnswerId), + } + database.SaveLog(&log) + c.IndentedJSON(http.StatusOK, gin.H{"message": "answer voted down"}) } diff --git a/handlers/question_handler/question_vote_handler.go b/handlers/question_handler/question_vote_handler.go index 3379a73..e3d9eec 100644 --- a/handlers/question_handler/question_vote_handler.go +++ b/handlers/question_handler/question_vote_handler.go @@ -5,6 +5,7 @@ import ( "Learning/database/db_helper" "Learning/helper" "Learning/models" + "fmt" "github.com/gin-gonic/gin" "net/http" "strconv" @@ -43,6 +44,16 @@ func VoteUpQuestion(c *gin.Context) { c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Transaction failed", "error": err.Error()}) return } + + log := models.Log{ + UserID: uint(user.UserId), + Action: "vote_up", + EntityType: "question", + EntityID: uint(question.QuestionId), + ReputationChange: 10, + Description: fmt.Sprintf("User gained 10 reputation for vote up on question %d", question.QuestionId), + } + database.SaveLog(&log) c.IndentedJSON(http.StatusOK, gin.H{"message": "question voted up"}) } @@ -76,6 +87,16 @@ func VoteDownQuestion(c *gin.Context) { if err != nil { c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Transaction failed", "error": err.Error()}) } + log := models.Log{ + UserID: uint(user.UserId), + Action: "vote_down", + EntityType: "question", + EntityID: uint(question.QuestionId), + ReputationChange: -10, + Description: fmt.Sprintf("User lost 10 reputation for vote down on question %d", question.QuestionId), + } + database.SaveLog(&log) + c.IndentedJSON(http.StatusOK, gin.H{"message": "question voted down"}) } From a1ce0e65b5845e87a4ce497b5a73c3cfdf0061e8 Mon Sep 17 00:00:00 2001 From: Sep Date: Wed, 9 Apr 2025 14:00:18 +0330 Subject: [PATCH 2/2] history for marking answer as correct --- database/db_helper/vote_helper.go | 22 +++++++++++++-- handlers/answer_handler/answer_handler.go | 28 +++++++++++++------ .../answer_handler/answer_vote_handler.go | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/database/db_helper/vote_helper.go b/database/db_helper/vote_helper.go index 2fd3a54..893af97 100644 --- a/database/db_helper/vote_helper.go +++ b/database/db_helper/vote_helper.go @@ -50,7 +50,6 @@ func VoteUpQuestion(question *models.Question) error { return fmt.Errorf("failed to vote up: %w", err) } - //todo log the action later return nil }) return err @@ -71,7 +70,6 @@ func VoteUpAnswerWithOwner(answer *models.Answer) error { return fmt.Errorf("failed to vote up: %w", err) } - //todo log the action later return nil }) return err @@ -105,3 +103,23 @@ func VoteDownAnswerWithOwner(answer *models.Answer) error { }) return err } + +func MarkAnswerAsCorrect(answer *models.Answer) error { + err := database.DB.Transaction(func(tx *gorm.DB) error { + var answerOwner models.User + if err := tx.First(&answer, answer.UserId).Error; err != nil { + return fmt.Errorf("failed to fetch answer owner: %w", err) + } + + if err := tx.Model(&answerOwner).Update("reputation", gorm.Expr("reputation + ?", 10)).Error; err != nil { + return fmt.Errorf("failed to update reputation: %w", err) + } + + if err := tx.Model(&answer).Update("is_correct_answer", gorm.Expr("is_correct_answer = ?", true)).Error; err != nil { + return fmt.Errorf("failed to mark as correct answer : %w", err) + } + + return nil + }) + return err +} diff --git a/handlers/answer_handler/answer_handler.go b/handlers/answer_handler/answer_handler.go index fa5895a..8da88e3 100644 --- a/handlers/answer_handler/answer_handler.go +++ b/handlers/answer_handler/answer_handler.go @@ -2,8 +2,10 @@ package answer_handler import ( "Learning/database" + "Learning/database/db_helper" "Learning/helper" "Learning/models" + "fmt" "github.com/gin-gonic/gin" "net/http" "regexp" @@ -69,16 +71,26 @@ func CorrectAnswer(c *gin.Context) { return } - if user.UserId == question.UserId { - answer.IsCorrectAnswer = true - if updateError := database.DB.Save(&answer).Error; updateError != nil { - c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "failed to update the answer"}) - return - } - c.IndentedJSON(http.StatusOK, answer) - } else { + if user.UserId != question.UserId { c.IndentedJSON(http.StatusUnauthorized, gin.H{"message": "only the user asked the question, may mark it as correct"}) + return + } + + err := db_helper.MarkAnswerAsCorrect(&answer) + if err != nil { + c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": "Transaction failed", "error": err.Error()}) + return + } + log := models.Log{ + UserID: uint(user.UserId), + Action: "mark_answer_as_correct", + EntityType: "answer", + EntityID: uint(answer.AnswerId), + ReputationChange: 10, + Description: fmt.Sprintf("User gained 10 reputation for vote up on answer %d", answer.AnswerId), } + database.SaveLog(&log) + c.IndentedJSON(http.StatusOK, &answer) } diff --git a/handlers/answer_handler/answer_vote_handler.go b/handlers/answer_handler/answer_vote_handler.go index be713da..d989b25 100644 --- a/handlers/answer_handler/answer_vote_handler.go +++ b/handlers/answer_handler/answer_vote_handler.go @@ -48,7 +48,7 @@ func VoteUpAnswer(c *gin.Context) { Action: "vote_up", EntityType: "answer", EntityID: uint(answer.AnswerId), - ReputationChange: -10, + ReputationChange: 10, Description: fmt.Sprintf("User gained 10 reputation for vote up on answer %d", answer.AnswerId), } database.SaveLog(&log)