add base logic for promo created

This commit is contained in:
Pavel 2024-01-11 21:20:33 +03:00
parent 95559a0fda
commit f3df811c9b
7 changed files with 85 additions and 39 deletions

@ -1,8 +1,8 @@
package app
import (
promocontroller "codeword/internal/controller/promocode"
reccontroller "codeword/internal/controller/recovery"
"codeword/internal/controller/promocode"
"codeword/internal/controller/recovery"
"codeword/internal/initialize"
"codeword/internal/repository"
httpserver "codeword/internal/server/http"
@ -26,9 +26,9 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
rdb, err := initialize.Redis(ctx, cfg)
encrypt := initialize.Encrypt(cfg)
promoCodeRepo := repository.NewPromoCodeRepository(mdb.Collection("promoCodes"))
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
promoCodeRepo := repository.NewPromoCodeRepository(mdb.Collection("promocodes"))
recoveryEmailSender := initialize.RecoveryEmailSender(cfg, logger)
authClient := initialize.AuthClient(cfg, logger)
@ -46,8 +46,8 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
PromoCodeRepo: promoCodeRepo,
})
recoveryController := reccontroller.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL)
promoCodeController := promocontroller.NewPromoCodeController(logger, promoService)
recoveryController := recovery.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL)
promoCodeController := promocode.NewPromoCodeController(logger, promoService)
recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{
Logger: logger,

@ -1,8 +1,10 @@
package controller
package promocode
import (
"codeword/internal/models"
"codeword/internal/repository"
"codeword/internal/services"
"errors"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
@ -28,6 +30,11 @@ func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
createdPromoCode, err := p.promoCodeService.CreatePromoCode(c.Context(), &reqCreatePromoCode)
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"})
}

@ -1,4 +1,4 @@
package controller
package recovery
import (
"codeword/internal/models"

@ -1,28 +1,31 @@
package models
import "time"
import (
"go.mongodb.org/mongo-driver/bson/primitive"
"time"
)
type PromoCode struct {
ID string `json:"id"`
Codeword string `json:"codeword"` // то, что будет вводить пользователь, чтобы получить плюшки
Description string `json:"description"` // описание, необходимое менеджеру в админке
Greetings string `json:"greetings"` // текст, выдаваемый пользователю в ответ на активацию промокода
DueTo int64 `json:"dueTo"` // таймштамп времени окончания работы активации промокода
ActivationCount int64 `json:"activationCount"` // предел количества активаций промокода
ID primitive.ObjectID `json:"id" bson:"_id"`
Codeword string `json:"codeword" bson:"codeword"` // то, что будет вводить пользователь, чтобы получить плюшки
Description string `json:"description" bson:"description"` // описание, необходимое менеджеру в админке
Greetings string `json:"greetings" bson:"greetings"` // текст, выдаваемый пользователю в ответ на активацию промокода
DueTo int64 `json:"dueTo" bson:"dueTo"` // таймштамп времени окончания работы активации промокода
ActivationCount int64 `json:"activationCount" bson:"activationCount"` // предел количества активаций промокода
Bonus struct {
Privilege struct {
PrivilegeID string `json:"privilegeID"` // айдишник привилегии, которая будет выдаваться
Amount uint64 `json:"amount"` // количество
} `json:"privilege"`
PrivilegeID string `json:"privilegeID" bson:"privilegeID"` // айдишник привилегии, которая будет выдаваться
Amount uint64 `json:"amount" bson:"amount"` // количество
} `json:"privilege" bson:"privilege"`
Discount struct {
Layer int `json:"layer"` // 1|2
Factor float64 `json:"factor"` // процент скидки, вернее множитель, при котором достигается этот процент скидки
Target string `json:"target"` // PrivilegeID или ServiceKey в зависимости от слоя
Threshold int64 `json:"threshold"` // граничное значение, при пересечении которого применяется эта скидка
} `json:"discount"`
} `json:"bonus"`
Outdated bool `json:"outdated"`
OffLimit bool `json:"offLimit"`
Delete bool `json:"delete"`
CreatedAt time.Time `json:"createdAt"`
Layer int `json:"layer" bson:"layer"` // 1|2
Factor float64 `json:"factor" bson:"factor"` // процент скидки, вернее множитель, при котором достигается этот процент скидки
Target string `json:"target" bson:"target"` // PrivilegeID или ServiceKey в зависимости от слоя
Threshold int64 `json:"threshold" bson:"threshold"` // граничное значение, при пересечении которого применяется эта скидка
} `json:"discount" bson:"discount"`
} `json:"bonus" bson:"bonus"`
Outdated bool `json:"outdated" bson:"outdated"`
OffLimit bool `json:"offLimit" bson:"offLimit"`
Delete bool `json:"delete" bson:"delete"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}

@ -3,23 +3,52 @@ package repository
import (
"codeword/internal/models"
"context"
"errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
var ErrDuplicateCodeword = errors.New("duplicate codeword")
type PromoCodeRepository struct {
mdb *mongo.Collection
}
func NewPromoCodeRepository(mdb *mongo.Collection) *PromoCodeRepository {
indexModel := mongo.IndexModel{
Keys: bson.D{
{"codeword", 1},
{"delete", 1},
},
Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"delete": false}),
}
_, err := mdb.Indexes().CreateOne(context.Background(), indexModel)
if err != nil {
panic(err)
}
return &PromoCodeRepository{mdb: mdb}
}
func (r *PromoCodeRepository) CreatePromoCode(ctx context.Context, promoCode *models.PromoCode) (*models.PromoCode, error) {
func (r *PromoCodeRepository) CreatePromo(ctx context.Context, promoCode *models.PromoCode) (*models.PromoCode, error) {
promoCode.CreatedAt = time.Now()
promoCode.ID = primitive.NewObjectID()
_, err := r.mdb.InsertOne(ctx, promoCode)
if err != nil {
if writeErr, ok := err.(mongo.WriteException); ok {
for _, writeError := range writeErr.WriteErrors {
if writeError.Code == 11000 {
return nil, ErrDuplicateCodeword
}
}
}
return nil, err
}
return promoCode, nil
}

@ -1,8 +1,8 @@
package http
import (
promocontroller "codeword/internal/controller/promocode"
reccontroller "codeword/internal/controller/recovery"
"codeword/internal/controller/promocode"
"codeword/internal/controller/recovery"
"context"
"fmt"
"github.com/gofiber/fiber/v2"
@ -12,14 +12,14 @@ import (
type ServerConfig struct {
Logger *zap.Logger
RecoveryController *reccontroller.RecoveryController
PromoCodeController *promocontroller.PromoCodeController
RecoveryController *recovery.RecoveryController
PromoCodeController *promocode.PromoCodeController
}
type Server struct {
Logger *zap.Logger
RecoveryController *reccontroller.RecoveryController
PromoCodeController *promocontroller.PromoCodeController
RecoveryController *recovery.RecoveryController
PromoCodeController *promocode.PromoCodeController
app *fiber.App
}
@ -27,9 +27,10 @@ func NewServer(config ServerConfig) *Server {
app := fiber.New()
s := &Server{
Logger: config.Logger,
RecoveryController: config.RecoveryController,
app: app,
Logger: config.Logger,
RecoveryController: config.RecoveryController,
PromoCodeController: config.PromoCodeController,
app: app,
}
s.registerRoutes()

@ -7,7 +7,7 @@ import (
)
type PromoCodeRepository interface {
CreatePromoCode(ctx context.Context, promoCode *models.PromoCode) (*models.PromoCode, error)
CreatePromo(ctx context.Context, promoCode *models.PromoCode) (*models.PromoCode, error)
}
type PromoDeps struct {
@ -28,5 +28,11 @@ func NewPromoCodeService(deps PromoDeps) *PromoCodeService {
}
func (s *PromoCodeService) CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error) {
return nil, nil
promoCode, err := s.promoCodeRepo.CreatePromo(ctx, req)
if err != nil {
s.logger.Error("Failed to add promocode in database", zap.Error(err))
return nil, err
}
return promoCode, nil
}