package result import ( "bytes" "github.com/gofiber/fiber/v2" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/middleware" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model" "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/repository/result" "penahub.gitlab.yandexcloud.net/backend/quiz/core/internal/tools" "strconv" "time" ) 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, } } 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"` } func (r *Result) GetResultsByQuizID(ctx *fiber.Ctx) error { 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") } account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if _, cnt := account.Privileges["quizCnt"]; !cnt { if _, unlim := account.Privileges["quizUnlimTime"]; !unlim { payment = false } } results, totalCount, err := r.dal.ResultRepo.GetQuizResults(ctx.Context(), quizID, result.GetQuizResDeps{ 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) } func (r *Result) DelResultByID(ctx *fiber.Ctx) error { 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") } isOwner, err := r.dal.ResultRepo.CheckResultOwner(ctx.Context(), resultID, accountID) 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") } if err := r.dal.ResultRepo.SoftDeleteResultByID(ctx.Context(), resultID); err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } ctx.Status(fiber.StatusOK) return nil } type ReqSeen struct { Answers []int64 } func (r *Result) SetStatus(ctx *fiber.Ctx) error { 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") } answers, err := r.dal.ResultRepo.CheckResultsOwner(ctx.Context(), req.Answers, accountID) 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") } if err := r.dal.ResultRepo.UpdateAnswersStatus(ctx.Context(), accountID, answers); err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.Status(fiber.StatusOK).JSON(nil) } func (r *Result) ExportResultsToCSV(ctx *fiber.Ctx) error { 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") } account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if _, cnt := account.Privileges["quizCnt"]; !cnt { if _, unlim := account.Privileges["quizUnlimTime"]; !unlim { return ctx.Status(fiber.StatusPaymentRequired).SendString("payment required") } } quiz, err := r.dal.QuizRepo.GetQuizById(ctx.Context(), accountID, quizID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get quiz") } questions, err := r.dal.ResultRepo.GetQuestions(ctx.Context(), quizID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get questions") } answers, err := r.dal.ResultRepo.GetQuizResultsCSV(ctx.Context(), quizID, result.GetQuizResDeps{ 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) if err := tools.WriteDataToExcel(buffer, questions, answers, r.s3Prefix+quiz.Qid+"/"); err != nil { 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()) } func (r *Result) GetResultAnswers(ctx *fiber.Ctx) error { 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") } account, err := r.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if _, cnt := account.Privileges["quizCnt"]; !cnt { if _, unlim := account.Privileges["quizUnlimTime"]; !unlim { return ctx.Status(fiber.StatusPaymentRequired).SendString("payment required") } } answers, err := r.dal.ResultRepo.GetResultAnswers(ctx.Context(), resultID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get result answers") } sortedAnswers, err := r.dal.QuestionRepo.ForSortingResults(ctx.Context(), answers) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed sort result answers") } return ctx.JSON(sortedAnswers) }