codeword/internal/controller/promocode/promocode_controller.go
2024-03-03 22:31:40 +03:00

207 lines
6.7 KiB
Go

package promocode
import (
"codeword/internal/models"
"codeword/internal/repository"
"codeword/internal/services"
"errors"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type Deps struct {
Logger *zap.Logger
PromoCodeService *services.PromoCodeService
AuthMiddleware func(*fiber.Ctx) error
}
type PromoCodeController struct {
logger *zap.Logger
promoCodeService *services.PromoCodeService
authMiddleware func(*fiber.Ctx) error
}
func NewPromoCodeController(deps Deps) *PromoCodeController {
return &PromoCodeController{
logger: deps.Logger,
promoCodeService: deps.PromoCodeService,
authMiddleware: deps.AuthMiddleware,
}
}
func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
var req models.PromoCode
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
if req.Codeword == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "codeword is required"})
}
createdPromoCode, err := p.promoCodeService.CreatePromoCode(c.Context(), &req)
if err != nil {
p.logger.Error("Failed to create promocode", zap.Error(err))
if errors.Is(err, repository.ErrDuplicateCodeword) {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Duplicate Codeword"})
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
return c.Status(fiber.StatusOK).JSON(createdPromoCode)
}
func (p *PromoCodeController) EditPromoCode(c *fiber.Ctx) error {
var req models.ReqEditPromoCode
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
if req.ID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "promocode ID is required"})
}
editedPromoCode, err := p.promoCodeService.EditPromoCode(c.Context(), &req)
if err != nil {
p.logger.Error("Failed to edit promocode", zap.Error(err))
if errors.Is(err, repository.ErrPromoCodeNotFound) {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "PromoCode not found"})
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
return c.Status(fiber.StatusOK).JSON(editedPromoCode)
}
func (p *PromoCodeController) GetList(c *fiber.Ctx) error {
var req models.GetPromoCodesListReq
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
promoCodes, count, err := p.promoCodeService.GetPromoCodesList(c.Context(), &req)
if err != nil {
p.logger.Error("Failed to retrieve promocode list", zap.Error(err))
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
resp := models.GetPromoCodesListResp{
Count: count,
Items: promoCodes,
}
return c.Status(fiber.StatusOK).JSON(resp)
}
func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
err := p.authMiddleware(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err})
}
userID := c.Locals(models.AuthJWTDecodedUserIDKey).(string)
if userID == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "failed to get jwt payload"})
}
var req models.ActivateReq
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
if req.Codeword == "" && req.FastLink == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "codeword or fastlink is required"})
}
greetings, err := p.promoCodeService.ActivatePromo(c.Context(), &req, userID)
if err != nil {
p.logger.Error("Failed to activate promocode", zap.Error(err))
switch {
case errors.Is(err, repository.ErrPromoCodeNotFound):
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "PromoCode not found"})
case errors.Is(err, repository.ErrPromoCodeAlreadyActivated):
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "PromoCode already activated"})
case errors.Is(err, repository.ErrPromoCodeExpired):
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
case errors.Is(err, repository.ErrPromoCodeExhausted):
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode exhausted"})
default:
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
}
return c.Status(fiber.StatusOK).JSON(models.ActivateResp{Greetings: greetings})
}
func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
promoCodeID := c.Params("promocodeID")
if promoCodeID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
}
err := p.promoCodeService.DeletePromoCode(c.Context(), promoCodeID)
if err != nil {
p.logger.Error("Failed to delete promocode", zap.Error(err))
if errors.Is(err, repository.ErrPromoCodeNotFound) {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "PromoCode not found"})
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
return c.SendStatus(fiber.StatusOK)
}
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
var req struct {
PromoCodeID string `json:"id"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
if req.PromoCodeID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
}
fastLink, err := p.promoCodeService.CreateFastLink(c.Context(), req.PromoCodeID)
if err != nil {
p.logger.Error("Failed to create fastlink", zap.Error(err))
if errors.Is(err, repository.ErrPromoCodeNotFound) {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "PromoCode not found"})
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"fastlink": fastLink})
}
func (p *PromoCodeController) GetStats(c *fiber.Ctx) error {
var req struct {
PromoCodeID string `json:"id"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
}
if req.PromoCodeID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
}
promoStats, err := p.promoCodeService.GetStats(c.Context(), req.PromoCodeID)
if err != nil {
p.logger.Error("Failed getting promo stats", zap.Error(err))
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
}
return c.Status(fiber.StatusOK).JSON(promoStats)
}