2024-10-25 15:26:03 +00:00
|
|
|
package result
|
2024-02-19 17:48:04 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2025-02-24 17:06:12 +00:00
|
|
|
"gitea.pena/SQuiz/common/dal"
|
|
|
|
"gitea.pena/SQuiz/common/middleware"
|
|
|
|
"gitea.pena/SQuiz/common/model"
|
|
|
|
"gitea.pena/SQuiz/common/repository/result"
|
2024-02-19 17:48:04 +00:00
|
|
|
"github.com/gofiber/fiber/v2"
|
2025-02-24 17:06:12 +00:00
|
|
|
"gitea.pena/SQuiz/core/internal/tools"
|
2024-02-19 17:48:04 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
type Deps struct {
|
|
|
|
DAL *dal.DAL
|
|
|
|
S3Prefix string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Result struct {
|
|
|
|
dal *dal.DAL
|
|
|
|
s3Prefix string
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewResultController(deps Deps) *Result {
|
|
|
|
return &Result{
|
|
|
|
dal: deps.DAL,
|
|
|
|
s3Prefix: deps.S3Prefix,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 17:48:04 +00:00
|
|
|
type ReqExport struct {
|
|
|
|
To, From time.Time
|
|
|
|
New bool
|
|
|
|
Page uint64
|
|
|
|
Limit uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
type ReqExportResponse struct {
|
|
|
|
TotalCount uint64 `json:"total_count"`
|
|
|
|
Results []model.AnswerExport `json:"results"`
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
func (r *Result) GetResultsByQuizID(ctx *fiber.Ctx) error {
|
2024-02-19 17:48:04 +00:00
|
|
|
payment := true // параметр для определения существования текущих привилегий юзера
|
|
|
|
|
|
|
|
accountID, ok := middleware.GetAccountId(ctx)
|
|
|
|
if !ok {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
|
|
|
|
}
|
|
|
|
|
|
|
|
var req ReqExport
|
|
|
|
if err := ctx.BodyParser(&req); err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
|
|
|
|
}
|
|
|
|
|
|
|
|
quizIDStr := ctx.Params("quizId")
|
|
|
|
quizID, err := strconv.ParseUint(quizIDStr, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid quiz ID format")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
2024-03-13 16:57:12 +00:00
|
|
|
if _, cnt := account.Privileges["quizCnt"]; !cnt {
|
|
|
|
if _, unlim := account.Privileges["quizUnlimTime"]; !unlim {
|
|
|
|
payment = false
|
|
|
|
}
|
2024-02-19 17:48:04 +00:00
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
results, totalCount, err := r.dal.ResultRepo.GetQuizResults(ctx.Context(), quizID, result.GetQuizResDeps{
|
2024-02-19 17:48:04 +00:00
|
|
|
To: req.To,
|
|
|
|
From: req.From,
|
|
|
|
New: req.New,
|
|
|
|
Page: req.Page,
|
|
|
|
Limit: req.Limit,
|
|
|
|
}, payment)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &ReqExportResponse{
|
|
|
|
TotalCount: totalCount,
|
|
|
|
Results: results,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctx.Status(fiber.StatusOK).JSON(resp)
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
func (r *Result) DelResultByID(ctx *fiber.Ctx) error {
|
2024-02-19 17:48:04 +00:00
|
|
|
accountID, ok := middleware.GetAccountId(ctx)
|
|
|
|
if !ok {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("could not get account ID from token")
|
|
|
|
}
|
|
|
|
|
|
|
|
resultIDStr := ctx.Params("resultId")
|
|
|
|
resultID, err := strconv.ParseUint(resultIDStr, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid result ID format")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
isOwner, err := r.dal.ResultRepo.CheckResultOwner(ctx.Context(), resultID, accountID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if !isOwner {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("not the owner of the result")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
if err := r.dal.ResultRepo.SoftDeleteResultByID(ctx.Context(), resultID); err != nil {
|
2024-02-19 17:48:04 +00:00
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.Status(fiber.StatusOK)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type ReqSeen struct {
|
|
|
|
Answers []int64
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
func (r *Result) SetStatus(ctx *fiber.Ctx) error {
|
2024-02-19 17:48:04 +00:00
|
|
|
var req ReqSeen
|
|
|
|
if err := ctx.BodyParser(&req); err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data")
|
|
|
|
}
|
|
|
|
|
|
|
|
accountID, ok := middleware.GetAccountId(ctx)
|
|
|
|
if !ok {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("could not get account ID from token")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
answers, err := r.dal.ResultRepo.CheckResultsOwner(ctx.Context(), req.Answers, accountID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(answers) != len(req.Answers) {
|
|
|
|
return ctx.Status(fiber.StatusNotAcceptable).SendString("could not update some answers because you don't have rights")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
if err := r.dal.ResultRepo.UpdateAnswersStatus(ctx.Context(), accountID, answers); err != nil {
|
2024-02-19 17:48:04 +00:00
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctx.Status(fiber.StatusOK).JSON(nil)
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
func (r *Result) ExportResultsToCSV(ctx *fiber.Ctx) error {
|
2024-02-19 17:48:04 +00:00
|
|
|
accountID, ok := middleware.GetAccountId(ctx)
|
|
|
|
if !ok {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
|
|
|
|
}
|
|
|
|
|
|
|
|
quizIDStr := ctx.Params("quizID")
|
|
|
|
quizID, err := strconv.ParseUint(quizIDStr, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("invalid quiz ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
req := ReqExport{}
|
|
|
|
if err := ctx.BodyParser(&req); err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("invalid request body")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
2024-03-13 16:57:12 +00:00
|
|
|
if _, cnt := account.Privileges["quizCnt"]; !cnt {
|
|
|
|
if _, unlim := account.Privileges["quizUnlimTime"]; !unlim {
|
|
|
|
return ctx.Status(fiber.StatusPaymentRequired).SendString("payment required")
|
|
|
|
}
|
2024-02-19 17:48:04 +00:00
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
quiz, err := r.dal.QuizRepo.GetQuizById(ctx.Context(), accountID, quizID)
|
2024-07-19 12:46:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get quiz")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
questions, err := r.dal.ResultRepo.GetQuestions(ctx.Context(), quizID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get questions")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
answers, err := r.dal.ResultRepo.GetQuizResultsCSV(ctx.Context(), quizID, result.GetQuizResDeps{
|
2024-02-19 17:48:04 +00:00
|
|
|
To: req.To,
|
|
|
|
From: req.From,
|
|
|
|
New: req.New,
|
|
|
|
Page: req.Page,
|
|
|
|
Limit: req.Limit,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get quiz results")
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer := new(bytes.Buffer)
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
if err := tools.WriteDataToExcel(buffer, questions, answers, r.s3Prefix+quiz.Qid+"/"); err != nil {
|
2024-02-19 17:48:04 +00:00
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to write data to Excel")
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.Set(fiber.HeaderContentType, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
|
|
ctx.Set(fiber.HeaderContentDisposition, `attachment; filename="results.xlsx"`)
|
|
|
|
|
|
|
|
return ctx.Send(buffer.Bytes())
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
func (r *Result) GetResultAnswers(ctx *fiber.Ctx) error {
|
2024-02-19 17:48:04 +00:00
|
|
|
accountID, ok := middleware.GetAccountId(ctx)
|
|
|
|
if !ok {
|
|
|
|
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
|
|
|
|
}
|
|
|
|
|
|
|
|
resultID, err := strconv.ParseUint(ctx.Params("resultID"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString("invalid quiz ID")
|
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
|
|
|
}
|
|
|
|
|
2024-03-13 16:57:12 +00:00
|
|
|
if _, cnt := account.Privileges["quizCnt"]; !cnt {
|
|
|
|
if _, unlim := account.Privileges["quizUnlimTime"]; !unlim {
|
|
|
|
return ctx.Status(fiber.StatusPaymentRequired).SendString("payment required")
|
|
|
|
}
|
2024-02-19 17:48:04 +00:00
|
|
|
}
|
|
|
|
|
2024-10-25 15:26:03 +00:00
|
|
|
answers, err := r.dal.ResultRepo.GetResultAnswers(ctx.Context(), resultID)
|
2024-02-19 17:48:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get result answers")
|
|
|
|
}
|
2024-10-25 15:26:03 +00:00
|
|
|
sortedAnswers, err := r.dal.QuestionRepo.ForSortingResults(ctx.Context(), answers)
|
2024-04-16 14:29:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString("failed sort result answers")
|
|
|
|
}
|
2024-02-19 17:48:04 +00:00
|
|
|
|
2024-04-16 14:29:15 +00:00
|
|
|
return ctx.JSON(sortedAnswers)
|
2024-02-19 17:48:04 +00:00
|
|
|
}
|