package service import ( "database/sql" "errors" "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/pj_errors" "penahub.gitlab.yandexcloud.net/backend/quiz/core.git/brokers" "strconv" "time" ) type CreateAccountReq struct { UserID string `json:"userId"` } type CreateAccountResp struct { CreatedAccount model.Account `json:"created_account"` } type DeleteAccountResp struct { DeletedAccountID string `json:"account_Id"` } type GetPrivilegeByUserIDReq struct { UserID string `json:"userId"` } type DeleteAccountByUserIDReq struct { UserID string `json:"userId"` } type DeleteAccountByUserIDResp struct { DeletedAccountUserID string `json:"userId"` } type GetAccountsReq struct { Limit uint64 `json:"limit"` Page uint64 `json:"page"` } type GetAccountsResp struct { Count uint64 `json:"count"` Items []model.Account `json:"items"` } // getCurrentAccount обработчик для получения текущего аккаунта func (s *Service) getCurrentAccount(ctx *fiber.Ctx) error { accountID, ok := middleware.GetAccountId(ctx) if !ok { return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required") } account, err := s.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil && err != sql.ErrNoRows { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } //TODO: fix this later if account.ID == "" { return ctx.Status(fiber.StatusNotFound).SendString("no account") } return ctx.Status(fiber.StatusOK).JSON(account) } // createAccount обработчик для создания нового аккаунта func (s *Service) createAccount(ctx *fiber.Ctx) error { accountID, ok := middleware.GetAccountId(ctx) if !ok { return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required") } existingAccount, err := s.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil && err != sql.ErrNoRows { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if existingAccount.ID != "" { return ctx.Status(fiber.StatusConflict).SendString("user with this ID already exists") } email, err := s.authClient.GetUserEmail(accountID) if err != nil { return err } newAccount := model.Account{ UserID: accountID, CreatedAt: time.Now(), Deleted: false, Privileges: map[string]model.ShortPrivilege{ "quizUnlimTime": { PrivilegeID: "quizUnlimTime", PrivilegeName: "Безлимит Опросов", Amount: 14, CreatedAt: time.Now(), }, }, } _, err = s.dal.AccountRepo.CreateAccount(ctx.Context(), &newAccount) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } err = s.producer.ToMailNotify(ctx.Context(), brokers.Message{ AccountID: accountID, Email: email, ServiceKey: s.serviceName, SendAt: time.Now(), }) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.JSON(CreateAccountResp{ CreatedAccount: newAccount, }) } // deleteAccount обработчик для удаления текущего аккаунта func (s *Service) deleteAccount(ctx *fiber.Ctx) error { accountID, ok := middleware.GetAccountId(ctx) if !ok { return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required") } account, err := s.dal.AccountRepo.GetAccountByID(ctx.Context(), accountID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if err := s.dal.AccountRepo.DeleteAccount(ctx.Context(), account.ID); err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.JSON(DeleteAccountResp{ DeletedAccountID: accountID, }) } // getPrivilegeByUserID обработчик для получения привилегий аккаунта по ID пользователя func (s *Service) getPrivilegeByUserID(ctx *fiber.Ctx) error { var req GetPrivilegeByUserIDReq if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } privilege, err := s.dal.AccountRepo.GetPrivilegesByAccountID(ctx.Context(), req.UserID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.Status(fiber.StatusOK).JSON(privilege) } // deleteAccountByUserID обработчик для удаления аккаунта по ID пользователя func (s *Service) deleteAccountByUserID(ctx *fiber.Ctx) error { var req DeleteAccountByUserIDReq if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } existingAccount, err := s.dal.AccountRepo.GetAccountByID(ctx.Context(), req.UserID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } if existingAccount.ID == "" { return ctx.Status(fiber.StatusInternalServerError).SendString("user with this ID not found") } if err := s.dal.AccountRepo.DeleteAccount(ctx.Context(), existingAccount.ID); err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.JSON(DeleteAccountByUserIDResp{ DeletedAccountUserID: req.UserID, }) } // getAccounts обработчик для получения списка аккаунтов с пагинацией func (s *Service) getAccounts(ctx *fiber.Ctx) error { var req GetAccountsReq if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } _, ok := middleware.GetAccountId(ctx) if !ok { return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required") } accounts, totalCount, err := s.dal.AccountRepo.GetAccounts(ctx.Context(), req.Limit, req.Page) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } response := GetAccountsResp{ Count: totalCount, Items: accounts, } return ctx.Status(fiber.StatusOK).JSON(response) } func (s *Service) ManualDone(ctx *fiber.Ctx) error { var req struct { Id string `json:"id"` } if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } if req.Id == "" { return ctx.Status(fiber.StatusBadRequest).SendString("User id is required") } err := s.dal.AccountRepo.ManualDone(ctx.Context(), req.Id) if err != nil { if errors.Is(err, pj_errors.ErrNotFound) { return ctx.Status(fiber.StatusNotFound).SendString("user don't have this privilege") } return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") } return ctx.SendStatus(fiber.StatusOK) } func (s *Service) PostLeadTarget(ctx *fiber.Ctx) error { var req struct { Type string `json:"type"` QuizID int32 `json:"quizID"` Target string `json:"target"` } 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("account id is required") } if req.Type == "" || req.Target == "" { return ctx.Status(fiber.StatusBadRequest).SendString("Type and Target don't be nil") } result, err := s.dal.AccountRepo.PostLeadTarget(ctx.Context(), model.LeadTarget{ AccountID: accountID, Target: req.Target, Type: req.Type, QuizID: req.QuizID, }) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.Status(fiber.StatusOK).JSON(result) } func (s *Service) DeleteLeadTarget(ctx *fiber.Ctx) error { leadIDStr := ctx.Params("id") leadID, err := strconv.ParseInt(leadIDStr, 10, 64) if err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid lead ID format") } err = s.dal.AccountRepo.DeleteLeadTarget(ctx.Context(), leadID) if err != nil { return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } return ctx.SendStatus(fiber.StatusOK) } func (s *Service) GetLeadTarget(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.ParseInt(quizIDStr, 10, 64) if err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid quiz ID format") } result, err := s.dal.AccountRepo.GetLeadTarget(ctx.Context(), accountID, int32(quizID)) if err != nil { switch { case errors.Is(err, pj_errors.ErrNotFound): return ctx.Status(fiber.StatusNotFound).SendString("this lead target not found") default: return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } } return ctx.Status(fiber.StatusOK).JSON(result) } func (s *Service) UpdateLeadTarget(ctx *fiber.Ctx) error { var req struct { ID int64 `json:"id"` Target string `json:"target"` } if err := ctx.BodyParser(&req); err != nil { return ctx.Status(fiber.StatusBadRequest).SendString("Invalid request data") } if req.ID == 0 || req.Target == "" { return ctx.Status(fiber.StatusBadRequest).SendString("ID and Target don't be nil") } result, err := s.dal.AccountRepo.UpdateLeadTarget(ctx.Context(), model.LeadTarget{ ID: req.ID, Target: req.Target, }) if err != nil { switch { case errors.Is(err, pj_errors.ErrNotFound): return ctx.Status(fiber.StatusNotFound).SendString("this lead target not found") default: return ctx.Status(fiber.StatusInternalServerError).SendString(err.Error()) } } return ctx.Status(fiber.StatusOK).JSON(result) }