package service import ( "bytes" "github.com/gofiber/fiber/v2" "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.git/tools" "strconv" "time" ) 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 (s *Service) 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 := s.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 := s.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 (s *Service) 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 := s.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 := s.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 (s *Service) 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 := s.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 := s.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 (s *Service) 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 := s.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") } } questions, err := s.dal.ResultRepo.GetQuestions(ctx.Context(), quizID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get questions") } answers, err := s.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); 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 (s *Service) 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 := s.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 := s.dal.ResultRepo.GetResultAnswers(ctx.Context(), resultID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString("failed to get result answers") } return ctx.JSON(answers) }