185 lines
6.0 KiB
Go
185 lines
6.0 KiB
Go
package services
|
|
|
|
import (
|
|
"codeword/internal/kafka/tariff"
|
|
"codeword/internal/models"
|
|
"codeword/internal/proto/discount"
|
|
"codeword/internal/utils/genID"
|
|
"context"
|
|
"fmt"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type PromoCodeRepository interface {
|
|
CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error)
|
|
EditPromoCode(ctx context.Context, req *models.ReqEditPromoCode) (*models.PromoCode, error)
|
|
GetPromoCodesList(ctx context.Context, req *models.GetPromoCodesListReq) ([]models.PromoCode, int64, error)
|
|
ActivatePromo(ctx context.Context, req *models.ActivateReq) (*models.PromoCode, error)
|
|
DeletePromoCode(ctx context.Context, promoCodeID string) error
|
|
GetPromoCodeByID(ctx context.Context, promoCodeID primitive.ObjectID) (*models.PromoCode, error)
|
|
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
|
|
}
|
|
|
|
type PromoCodeService struct {
|
|
logger *zap.Logger
|
|
promoCodeRepo PromoCodeRepository
|
|
statsRepo PromoStatsRepository
|
|
kafka *tariff.Producer
|
|
discountClient discount.DiscountServiceClient
|
|
}
|
|
|
|
func NewPromoCodeService(deps PromoDeps) *PromoCodeService {
|
|
return &PromoCodeService{
|
|
logger: deps.Logger,
|
|
promoCodeRepo: deps.PromoCodeRepo,
|
|
statsRepo: deps.StatsRepo,
|
|
kafka: deps.Kafka,
|
|
discountClient: deps.DiscountClient,
|
|
}
|
|
}
|
|
|
|
func (s *PromoCodeService) CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error) {
|
|
promoCode, err := s.promoCodeRepo.CreatePromoCode(ctx, req)
|
|
if err != nil {
|
|
s.logger.Error("Failed to add promocode in database", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return promoCode, nil
|
|
}
|
|
|
|
func (s *PromoCodeService) EditPromoCode(ctx context.Context, req *models.ReqEditPromoCode) (*models.PromoCode, error) {
|
|
editedPromoCode, err := s.promoCodeRepo.EditPromoCode(ctx, req)
|
|
if err != nil {
|
|
s.logger.Error("Failed to edit promocode in database", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return editedPromoCode, nil
|
|
}
|
|
|
|
func (s *PromoCodeService) GetPromoCodesList(ctx context.Context, req *models.GetPromoCodesListReq) ([]models.PromoCode, int64, error) {
|
|
promoCodes, count, err := s.promoCodeRepo.GetPromoCodesList(ctx, req)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get list promocodes from database", zap.Error(err))
|
|
return nil, 0, err
|
|
}
|
|
|
|
return promoCodes, count, nil
|
|
}
|
|
|
|
// todo одумать еще реализацию этого дела, надо уточнить как разделяется ответственность в бонусе между привилегией и скидкой
|
|
// разделяется ли она или они всегда вместе, если разделяются то что-то из этого может быть пустым либо все заполеннное,
|
|
// соответсвенно надо сделать соответствующие проверки до записи в кафку и до отправки в дискаунт сервис
|
|
|
|
func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error) {
|
|
promoCode, err := s.promoCodeRepo.ActivatePromo(ctx, req)
|
|
if err != nil {
|
|
s.logger.Error("Failed to activate promocode", zap.Error(err))
|
|
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 != "" {
|
|
postfix = fmt.Sprintf(":(%s)", req.FastLink)
|
|
}
|
|
|
|
var privileges []models.Privilege
|
|
privilege := models.Privilege{
|
|
PrivilegeID: promoCode.Bonus.Privilege.PrivilegeID,
|
|
Amount: promoCode.Bonus.Privilege.Amount,
|
|
}
|
|
privileges = append(privileges, privilege)
|
|
|
|
fakeTariff := &models.Tariff{
|
|
Name: promoCode.Codeword + postfix,
|
|
Privileges: privileges,
|
|
Deleted: promoCode.Delete,
|
|
CreatedAt: promoCode.CreatedAt,
|
|
}
|
|
if err := s.kafka.Send(ctx, req.UserID, fakeTariff); err != nil {
|
|
s.logger.Error("Failed to send fake tariff to Kafka", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
disOverHelm := true
|
|
discountRequest := &discount.CreateDiscountRequest{
|
|
Name: promoCode.Codeword + postfix,
|
|
Layer: promoCode.Bonus.Discount.Layer,
|
|
Description: "",
|
|
Condition: &discount.DiscountCondition{
|
|
Coupon: &promoCode.Codeword,
|
|
User: &req.UserID,
|
|
},
|
|
Target: &discount.DiscountCalculationTarget{
|
|
Factor: promoCode.Bonus.Discount.Factor,
|
|
Overhelm: &disOverHelm,
|
|
},
|
|
}
|
|
|
|
_, err = s.discountClient.CreateDiscount(ctx, discountRequest)
|
|
if err != nil {
|
|
s.logger.Error("Failed to create discount", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return promoCode.Greetings, nil
|
|
}
|
|
|
|
func (s *PromoCodeService) DeletePromoCode(ctx context.Context, promoCodeID string) error {
|
|
err := s.promoCodeRepo.DeletePromoCode(ctx, promoCodeID)
|
|
if err != nil {
|
|
s.logger.Error("Failed simple delete promocode from database", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *PromoCodeService) CreateFastLink(ctx context.Context, promoCodeID string) (string, error) {
|
|
xid := genID.GenerateXID()
|
|
promoID, err := primitive.ObjectIDFromHex(promoCodeID)
|
|
if err != nil {
|
|
s.logger.Error("Failed conversion promoCodeID to ObjectID", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
err = s.promoCodeRepo.AddFastLink(ctx, promoID, xid)
|
|
if err != nil {
|
|
s.logger.Error("Failed to add fastlink for promocode by promocode id", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
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
|
|
}
|