319 lines
10 KiB
Go
319 lines
10 KiB
Go
package promocode
|
|
|
|
import (
|
|
"codeword/internal/models"
|
|
"codeword/internal/repository"
|
|
"codeword/internal/services"
|
|
"codeword/internal/utils/middleware"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/gofiber/fiber/v2"
|
|
"go.uber.org/zap"
|
|
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
|
|
)
|
|
|
|
type Deps struct {
|
|
Logger *zap.Logger
|
|
PromoCodeService *services.PromoCodeService
|
|
}
|
|
|
|
type PromoCodeController struct {
|
|
logger *zap.Logger
|
|
promoCodeService *services.PromoCodeService
|
|
}
|
|
|
|
func NewPromoCodeController(deps Deps) *PromoCodeController {
|
|
return &PromoCodeController{
|
|
logger: deps.Logger,
|
|
promoCodeService: deps.PromoCodeService,
|
|
}
|
|
}
|
|
|
|
func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
|
|
userID := middleware.ExtractUserID(c)
|
|
hlogger := log_mw.ExtractLogger(c)
|
|
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"})
|
|
}
|
|
|
|
req.ActivationLimit = req.ActivationCount
|
|
|
|
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"})
|
|
}
|
|
|
|
var keyType string
|
|
var ctxFactor float64
|
|
var keyTargetType string
|
|
var ctxTarget string
|
|
var ctxAmount int64
|
|
|
|
if createdPromoCode.Bonus.Privilege.PrivilegeID != "" && createdPromoCode.Bonus.Discount.Factor != 0 && createdPromoCode.Bonus.Discount.Factor != 1 {
|
|
keyType = "privilege,discount"
|
|
keyTargetType = "privilege,service"
|
|
ctxTarget = fmt.Sprintf("%s,%s", createdPromoCode.Bonus.Privilege.PrivilegeID, createdPromoCode.Bonus.Discount.Target)
|
|
ctxAmount = int64(createdPromoCode.Bonus.Privilege.Amount)
|
|
ctxFactor = createdPromoCode.Bonus.Discount.Factor
|
|
} else if createdPromoCode.Bonus.Privilege.PrivilegeID != "" {
|
|
keyType = "privilege"
|
|
keyTargetType = "privilege"
|
|
ctxTarget = createdPromoCode.Bonus.Privilege.PrivilegeID
|
|
ctxAmount = int64(createdPromoCode.Bonus.Privilege.Amount)
|
|
} else if createdPromoCode.Bonus.Discount.Factor != 0 && createdPromoCode.Bonus.Discount.Factor != 1 {
|
|
keyType = "discount"
|
|
keyTargetType = "service"
|
|
ctxFactor = createdPromoCode.Bonus.Discount.Factor
|
|
ctxTarget = createdPromoCode.Bonus.Discount.Target
|
|
}
|
|
|
|
hlogger.Emit(models.InfoPromocodeCreated{
|
|
CtxID: createdPromoCode.ID.String(),
|
|
CtxUserID: userID,
|
|
KeyType: keyType,
|
|
CtxFactor: ctxFactor,
|
|
KeyTargetType: keyTargetType,
|
|
CtxTarget: ctxTarget,
|
|
CtxAmount: ctxAmount,
|
|
CtxCode: createdPromoCode.Codeword,
|
|
})
|
|
|
|
return c.Status(fiber.StatusOK).JSON(createdPromoCode)
|
|
}
|
|
|
|
func (p *PromoCodeController) EditPromoCode(c *fiber.Ctx) error {
|
|
userID := middleware.ExtractUserID(c)
|
|
hlogger := log_mw.ExtractLogger(c)
|
|
|
|
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"})
|
|
}
|
|
|
|
req.ActivationLimit = req.ActivationCount
|
|
|
|
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"})
|
|
}
|
|
|
|
var keyType string
|
|
var ctxFactor float64
|
|
var keyTargetType string
|
|
var ctxTarget string
|
|
var ctxAmount int64
|
|
|
|
if editedPromoCode.Bonus.Privilege.PrivilegeID != "" && editedPromoCode.Bonus.Discount.Factor != 0 && editedPromoCode.Bonus.Discount.Factor != 1 {
|
|
keyType = "privilege,discount"
|
|
keyTargetType = "privilege,service"
|
|
ctxTarget = fmt.Sprintf("%s,%s", editedPromoCode.Bonus.Privilege.PrivilegeID, editedPromoCode.Bonus.Discount.Target)
|
|
ctxAmount = int64(editedPromoCode.Bonus.Privilege.Amount)
|
|
ctxFactor = editedPromoCode.Bonus.Discount.Factor
|
|
} else if editedPromoCode.Bonus.Privilege.PrivilegeID != "" {
|
|
keyType = "privilege"
|
|
keyTargetType = "privilege"
|
|
ctxTarget = editedPromoCode.Bonus.Privilege.PrivilegeID
|
|
ctxAmount = int64(editedPromoCode.Bonus.Privilege.Amount)
|
|
} else if editedPromoCode.Bonus.Discount.Factor != 0 && editedPromoCode.Bonus.Discount.Factor != 1 {
|
|
keyType = "discount"
|
|
keyTargetType = "service"
|
|
ctxFactor = editedPromoCode.Bonus.Discount.Factor
|
|
ctxTarget = editedPromoCode.Bonus.Discount.Target
|
|
}
|
|
|
|
hlogger.Emit(models.InfoPromocodeUpdated{
|
|
CtxID: editedPromoCode.ID.String(),
|
|
CtxUserID: userID,
|
|
KeyType: keyType,
|
|
CtxFactor: ctxFactor,
|
|
KeyTargetType: keyTargetType,
|
|
CtxTarget: ctxTarget,
|
|
CtxAmount: ctxAmount,
|
|
CtxCode: editedPromoCode.Codeword,
|
|
})
|
|
|
|
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"})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(models.GetPromoCodesListResp{
|
|
Count: count,
|
|
Items: promoCodes,
|
|
})
|
|
}
|
|
|
|
func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
|
|
userID := middleware.ExtractUserID(c)
|
|
hlogger := log_mw.ExtractLogger(c)
|
|
fmt.Println("SKER1", userID)
|
|
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"})
|
|
}
|
|
fmt.Println("SKER2", req)
|
|
|
|
promocode, err := p.promoCodeService.ActivatePromo(c.Context(), &req, userID)
|
|
fmt.Println("SKER3", err)
|
|
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):
|
|
hlogger.Emit(models.InfoPromocodeDeadlined{
|
|
|
|
CtxID: promocode.ID.String(),
|
|
})
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
|
|
case errors.Is(err, repository.ErrPromoCodeExhausted):
|
|
hlogger.Emit(models.InfoPromocodeExhausted{
|
|
CtxID: promocode.ID.String(),
|
|
})
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode exhausted"})
|
|
default:
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
|
}
|
|
}
|
|
|
|
if req.Codeword != "" {
|
|
hlogger.Emit(models.InfoPromocodeActivated{
|
|
CtxID: promocode.ID.String(),
|
|
CtxUserID: userID,
|
|
CtxCode: req.Codeword,
|
|
})
|
|
} else if req.FastLink != "" {
|
|
hlogger.Emit(models.InfoFastlinkActivated{
|
|
CtxID: promocode.ID.String(),
|
|
CtxUserID: userID,
|
|
CtxPromocodeID: req.FastLink,
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(models.ActivateResp{Greetings: promocode.Greetings})
|
|
}
|
|
|
|
func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
|
userID := middleware.ExtractUserID(c)
|
|
hlogger := log_mw.ExtractLogger(c)
|
|
|
|
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"})
|
|
}
|
|
|
|
hlogger.Emit(models.InfoPromocodeDeleted{
|
|
CtxID: promoCodeID,
|
|
CtxUserID: userID,
|
|
})
|
|
|
|
return c.SendStatus(fiber.StatusOK)
|
|
}
|
|
|
|
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
|
userID := middleware.ExtractUserID(c)
|
|
hlogger := log_mw.ExtractLogger(c)
|
|
|
|
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"})
|
|
}
|
|
|
|
hlogger.Emit(models.InfoFastlinkCreated{
|
|
CtxID: fastLink,
|
|
CtxPromocodeID: req.PromoCodeID,
|
|
CtxUserID: userID,
|
|
})
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"fastlink": fastLink})
|
|
}
|
|
|
|
func (p *PromoCodeController) GetStats(c *fiber.Ctx) error {
|
|
var req models.PromoStatReq
|
|
|
|
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)
|
|
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: " + err.Error()})
|
|
}
|
|
return c.Status(fiber.StatusOK).JSON(promoStats)
|
|
}
|