add stats route
This commit is contained in:
parent
bfc332fd77
commit
c282b8151b
@ -312,7 +312,25 @@ paths:
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
|
||||
/promocode/stats:
|
||||
get:
|
||||
summary: Получить статистику промокода
|
||||
responses:
|
||||
'200':
|
||||
description: Статистика промокода успешно получена
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PromoCodeStats'
|
||||
'500':
|
||||
description: Внутренняя ошибка сервера
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
|
||||
components:
|
||||
schemas:
|
||||
@ -505,4 +523,17 @@ components:
|
||||
properties:
|
||||
greetings:
|
||||
type: string
|
||||
description: Поле из активированного промокода
|
||||
description: Поле из активированного промокода
|
||||
|
||||
PromoCodeStats:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: ID промокода
|
||||
usageCount:
|
||||
type: object
|
||||
description: Количество использований промокода для каждого пользователя
|
||||
usageHistory:
|
||||
type: object
|
||||
description: История использования промокода для каждого пользователя
|
||||
|
@ -67,6 +67,7 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
|
||||
encrypt := initialize.Encrypt(cfg)
|
||||
|
||||
promoCodeRepo := repository.NewPromoCodeRepository(mdb.Collection("promoCodes"))
|
||||
statsRepo := repository.NewStatsRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("promoStats")})
|
||||
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
|
||||
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
|
||||
|
||||
@ -84,6 +85,7 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
|
||||
promoService := services.NewPromoCodeService(services.PromoDeps{
|
||||
Logger: logger,
|
||||
PromoCodeRepo: promoCodeRepo,
|
||||
StatsRepo: statsRepo,
|
||||
Kafka: brokers.TariffProducer,
|
||||
DiscountClient: discountRpcClient,
|
||||
})
|
||||
|
@ -165,3 +165,12 @@ func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"fastlink": fastLink})
|
||||
}
|
||||
|
||||
func (p *PromoCodeController) GetAllStats(c *fiber.Ctx) error {
|
||||
promoStats, err := p.promoCodeService.GetAllStats(c.Context())
|
||||
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)
|
||||
}
|
||||
|
@ -67,3 +67,9 @@ type ActivateReq struct {
|
||||
type ActivateResp struct {
|
||||
Greetings string `json:"greetings"` // поле из активированного промокода
|
||||
}
|
||||
|
||||
type PromoCodeStats struct {
|
||||
ID string `bson:"_id,omitempty" json:"id,omitempty"`
|
||||
UsageCount map[string]int `bson:"usageCount" json:"usageCount"`
|
||||
UsageHistory map[string][]time.Time `bson:"usageHistory" json:"usageHistory"`
|
||||
}
|
||||
|
59
internal/repository/promocode_stats.go
Normal file
59
internal/repository/promocode_stats.go
Normal file
@ -0,0 +1,59 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"codeword/internal/models"
|
||||
"context"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StatsRepository struct {
|
||||
mdb *mongo.Collection
|
||||
}
|
||||
|
||||
func NewStatsRepository(deps Deps) *StatsRepository {
|
||||
|
||||
return &StatsRepository{mdb: deps.Mdb}
|
||||
}
|
||||
|
||||
func (r *StatsRepository) UpdateStatistics(ctx context.Context, key, userID string) error {
|
||||
update := bson.M{
|
||||
"$inc": bson.M{"usageCount." + userID: 1},
|
||||
"$push": bson.M{"usageHistory." + userID: time.Now()},
|
||||
}
|
||||
|
||||
opts := options.Update().SetUpsert(true)
|
||||
filter := bson.M{"_id": key}
|
||||
|
||||
_, err := r.mdb.UpdateOne(ctx, filter, update, opts)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *StatsRepository) GetAllStatistics(ctx context.Context) ([]models.PromoCodeStats, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
opts := options.Find()
|
||||
|
||||
cursor, err := r.mdb.Find(ctx, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var promoCodeStatsList []models.PromoCodeStats
|
||||
for cursor.Next(ctx) {
|
||||
var promoCodeStats models.PromoCodeStats
|
||||
if err := cursor.Decode(&promoCodeStats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
promoCodeStatsList = append(promoCodeStatsList, promoCodeStats)
|
||||
}
|
||||
|
||||
if err := cursor.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return promoCodeStatsList, nil
|
||||
}
|
@ -61,6 +61,7 @@ func (s *Server) registerRoutes() {
|
||||
s.app.Post("/promocode/activate", s.PromoCodeController.Activate)
|
||||
s.app.Delete("/promocode/:promocodeID", s.PromoCodeController.Delete)
|
||||
s.app.Post("/promocode/fastlink", s.PromoCodeController.CreateFastLink)
|
||||
s.app.Get("/promocode/stats", s.PromoCodeController.GetAllStats)
|
||||
//... other
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,15 @@ type PromoCodeRepository interface {
|
||||
AddFastLink(ctx context.Context, promoCodeID primitive.ObjectID, xid string) error
|
||||
}
|
||||
|
||||
type PromoStatsRepository interface {
|
||||
UpdateStatistics(ctx context.Context, key, userID string) error
|
||||
GetAllStatistics(ctx context.Context) ([]models.PromoCodeStats, error)
|
||||
}
|
||||
|
||||
type PromoDeps struct {
|
||||
Logger *zap.Logger
|
||||
PromoCodeRepo PromoCodeRepository
|
||||
StatsRepo PromoStatsRepository
|
||||
Kafka *tariff.Producer
|
||||
DiscountClient discount.DiscountServiceClient
|
||||
}
|
||||
@ -31,6 +37,7 @@ type PromoDeps struct {
|
||||
type PromoCodeService struct {
|
||||
logger *zap.Logger
|
||||
promoCodeRepo PromoCodeRepository
|
||||
statsRepo PromoStatsRepository
|
||||
kafka *tariff.Producer
|
||||
discountClient discount.DiscountServiceClient
|
||||
}
|
||||
@ -39,6 +46,7 @@ func NewPromoCodeService(deps PromoDeps) *PromoCodeService {
|
||||
return &PromoCodeService{
|
||||
logger: deps.Logger,
|
||||
promoCodeRepo: deps.PromoCodeRepo,
|
||||
statsRepo: deps.StatsRepo,
|
||||
kafka: deps.Kafka,
|
||||
discountClient: deps.DiscountClient,
|
||||
}
|
||||
@ -76,7 +84,7 @@ func (s *PromoCodeService) GetPromoCodesList(ctx context.Context, req *models.Ge
|
||||
|
||||
// todo одумать еще реализацию этого дела, надо уточнить как разделяется ответственность в бонусе между привилегией и скидкой
|
||||
// разделяется ли она или они всегда вместе, если разделяются то что-то из этого может быть пустым либо все заполеннное,
|
||||
//соответсвенно надо сделать соответствующие проверки до записи в кафку и до отправки в дискаунт сервис
|
||||
// соответсвенно надо сделать соответствующие проверки до записи в кафку и до отправки в дискаунт сервис
|
||||
|
||||
func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error) {
|
||||
promoCode, err := s.promoCodeRepo.ActivatePromo(ctx, req)
|
||||
@ -85,6 +93,12 @@ func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.Activa
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = s.statsRepo.UpdateStatistics(ctx, promoCode.ID.Hex(), req.UserID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed add in stats", zap.Error(err))
|
||||
return "", err
|
||||
}
|
||||
|
||||
var postfix string
|
||||
|
||||
if req.FastLink != "" {
|
||||
@ -159,3 +173,12 @@ func (s *PromoCodeService) CreateFastLink(ctx context.Context, promoCodeID strin
|
||||
|
||||
return xid, nil
|
||||
}
|
||||
|
||||
func (s *PromoCodeService) GetAllStats(ctx context.Context) ([]models.PromoCodeStats, error) {
|
||||
promoStats, err := s.statsRepo.GetAllStatistics(ctx)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed getting promo stats", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return promoStats, nil
|
||||
}
|
||||
|
@ -533,6 +533,26 @@ func TestActivatePromoCode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetPromoStats
|
||||
func TestGetPromoStats(t *testing.T) {
|
||||
client := fiber.AcquireClient()
|
||||
|
||||
t.Run("GetAllStats", func(t *testing.T) {
|
||||
req := client.Get(BaseUrl + "/promocode/stats")
|
||||
|
||||
statusCode, resBody, errs := req.Bytes()
|
||||
if len(errs) != 0 {
|
||||
assert.NoError(t, errs[0])
|
||||
}
|
||||
assert.Equal(t, fiber.StatusOK, statusCode)
|
||||
|
||||
var response []models.PromoCodeStats
|
||||
err := json.Unmarshal(resBody, &response)
|
||||
assert.NoError(t, err)
|
||||
fmt.Println(response)
|
||||
})
|
||||
}
|
||||
|
||||
// DeletePromoCode
|
||||
func TestDeletePromoCode(t *testing.T) {
|
||||
client := fiber.AcquireClient()
|
||||
|
Loading…
Reference in New Issue
Block a user