diff --git a/database/db_helper/vote_helper.go b/database/db_helper/vote_helper.go index 2a74321..893af97 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 @@ -51,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 @@ -72,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 @@ -106,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/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_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 506e5b2..d989b25 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"}) }