--
This commit is contained in:
parent
7e6e7e95cf
commit
ec5ccc6d11
483
1
Normal file
483
1
Normal file
@ -0,0 +1,483 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"fmt"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"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"
|
||||
"go.mongodb.org/mongo-driver/mongo/readconcern"
|
||||
"go.mongodb.org/mongo-driver/mongo/writeconcern"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/expression"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/expression/discount"
|
||||
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/mongo"
|
||||
)
|
||||
|
||||
type DiscountRepository struct {
|
||||
mongoDB *mongo.Collection
|
||||
logger *logrus.Logger
|
||||
}
|
||||
|
||||
func NewDiscountRepository(mongoDB *mongo.Collection, logger *logrus.Logger) *DiscountRepository {
|
||||
return &DiscountRepository{
|
||||
mongoDB: mongoDB,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) getLayer(ctx context.Context, keyGroup, keyParam string, layer uint64, groupPrices, privilegeAmounts map[string]uint64, conditions *core.DiscountConditions) ([]models.Discount, error) {
|
||||
conditionFilter := discount.ConditionFilter(conditions, groupPrices, privilegeAmounts, layer)
|
||||
|
||||
if conditionFilter == nil {
|
||||
return []models.Discount{}, ErrEmptyArgs
|
||||
}
|
||||
|
||||
filter := bson.M{
|
||||
"$and": []bson.M{
|
||||
*conditionFilter,
|
||||
{"$or": []bson.M{{fields.Discount.Deprecated: false}, {fields.Discount.Deprecated: nil}}},
|
||||
{"$or": []bson.M{{fields.Audit.Deleted: false}, {fields.Audit.Deleted: nil}}},
|
||||
},
|
||||
}
|
||||
|
||||
receiver.logger.Info("DR cf", conditionFilter)
|
||||
|
||||
cursor, err := receiver.mongoDB.Aggregate(ctx, mongo.Pipeline{
|
||||
bson.D{
|
||||
{Key: "$match", Value: filter},
|
||||
},
|
||||
bson.D{
|
||||
{Key: "$sort", Value: bson.M{
|
||||
keyGroup: 1,
|
||||
keyParam: -1,
|
||||
}},
|
||||
},
|
||||
bson.D{
|
||||
{Key: "$group", Value: bson.M{
|
||||
"_id": "$" + keyGroup,
|
||||
"doc": bson.M{"$first": "$$ROOT"},
|
||||
}},
|
||||
},
|
||||
bson.D{
|
||||
{Key: "$replaceRoot", Value: bson.M{
|
||||
"newRoot": "$doc",
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return []models.Discount{}, err
|
||||
}
|
||||
|
||||
discounts := []models.Discount{}
|
||||
|
||||
err = cursor.All(ctx, &discounts)
|
||||
|
||||
fmt.Println("DISCOOOO", discounts)
|
||||
return discounts, err
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *core.DiscountConditions) ([]models.Discount, uint64, error) {
|
||||
if conditions == nil {
|
||||
receiver.logger.Errorln("empty condition on <Determine> of <DiscountRepository>")
|
||||
return []models.Discount{}, uint64(0), ErrEmptyArgs
|
||||
}
|
||||
|
||||
var (
|
||||
applyed = []models.Discount{}
|
||||
keyGroup = "condition.product"
|
||||
keyParam = "condition.term"
|
||||
//rawPrice = uint64(0)
|
||||
groupPrices = map[string]uint64{}
|
||||
privilegeAmounts = map[string]uint64{}
|
||||
privilegePrices = map[string]uint64{}
|
||||
privilegeGroups = map[string]string{}
|
||||
priority = make(map[string]struct{})
|
||||
noAccept = make(map[string]struct{})
|
||||
)
|
||||
|
||||
for layer := uint64(1); layer < 5; layer++ {
|
||||
switch layer {
|
||||
case 1:
|
||||
for _, condition := range conditions.Optionals {
|
||||
if condition.Product == nil || condition.Term == nil {
|
||||
continue
|
||||
}
|
||||
// вычисляем количество привилегий во всей корзине
|
||||
fmt.Println("GRP", *condition.Group)
|
||||
privilegeAmounts[*condition.Product] += *condition.Term
|
||||
privilegePrices[*condition.Product] += *condition.PriceFrom
|
||||
if _, ok := privilegeAmounts[*condition.Product]; !ok {
|
||||
privilegeGroups[*condition.Product] = *condition.Group
|
||||
}
|
||||
}
|
||||
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
if err != nil {
|
||||
return []models.Discount{}, uint64(0), err
|
||||
}
|
||||
// проверяем юзера, если его тип nko, то нужно просто применить скидку на nko к сумму сумм привилегий
|
||||
// в getLayer возвращаются все подходящие скидыки для юзера но нужно только nko
|
||||
if conditions.Common.UserType == "nko" {
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.UserType != nil && *discount.Condition.UserType == "nko" {
|
||||
var nkoPrice uint64
|
||||
for _, privilegePrice := range privilegePrices {
|
||||
nkoPrice += privilegePrice
|
||||
}
|
||||
return []models.Discount{discount}, uint64(float64(nkoPrice) * discount.Target.Factor), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
// если юзер не nko, то выбираем все скидки за первый слой
|
||||
|
||||
// сначала делаем все нужные проверки записываем запреты
|
||||
for privilege, privilegePrice := range privilegePrices {
|
||||
fmt.Println("PREPPRIV", privilege, privilegePrice)
|
||||
|
||||
// проверки существования скидки за 2 слой noAccept не применям скидки к этой группе если есть такие
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.User != nil && *discount.Condition.User == conditions.Common.User && privilegeGroups[privilege] == *discount.Condition.Group && discount.Layer == 2 {
|
||||
noAccept[privilegeGroups[privilege]] = struct{}{}
|
||||
}
|
||||
}
|
||||
// если к этой привилегии не было запрета в виде слоя 2, и это скидка для этого юзера и слой 1
|
||||
// то применям к этой привилегии скидку только раз, но никак не ограничиваем скидку на группу,
|
||||
// только конкретно на привилегию
|
||||
for _, discount := range discounts {
|
||||
fmt.Println("PREPPRIV1", groupPrices, *discount.Condition.User, conditions.Common.User, privilege, *discount.Condition.Product, discount.Layer )
|
||||
if _, ok := noAccept[privilegeGroups[privilege]]; !ok {
|
||||
fmt.Println("PREPPRIV3", priority, privilegeGroups)
|
||||
if discount.Condition.User != nil && discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 {
|
||||
fmt.Println("PREPPRIV4", priority, float64(privilegePrice), discount.Target.Products[0].Factor)
|
||||
groupPrices[privilegeGroups[privilege]] += uint64(float64(privilegePrice) * discount.Target.Products[0].Factor)
|
||||
applyed = append(applyed, discount)
|
||||
priority[privilege] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for privilege, privilegePrice := range privilegePrices {
|
||||
found := false
|
||||
// приминеям оставшиеся просто где слой 1 и дозаполняем полностью groupPrices
|
||||
for _, discount := range discounts {
|
||||
if _, ok := noAccept[privilegeGroups[privilege]]; !ok {
|
||||
if _, ok := priority[privilege]; !ok {
|
||||
if discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 && discount.Condition.User == nil {
|
||||
fmt.Println("PREPPRIV5", groupPrices)
|
||||
groupPrices[privilegeGroups[privilege]] += uint64(float64(privilegePrice) * discount.Target.Factor)
|
||||
applyed = append(applyed, discount)
|
||||
found = true
|
||||
// сли у нас в ревесте есть такая привилегия но ее нет в пришедших скидках, просто добавляем ее в groupPrices с ключем группы
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("PREPPRIV2", groupPrices)
|
||||
if !found {
|
||||
groupPrices[privilegeGroups[privilege]] += privilegePrice
|
||||
}
|
||||
}
|
||||
|
||||
keyGroup = "condition.group"
|
||||
keyParam = "condition.priceFrom"
|
||||
|
||||
case 2:
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
if err != nil {
|
||||
return []models.Discount{}, uint64(0), err
|
||||
}
|
||||
var price uint64
|
||||
// проходимся по мапе где ключ группа и значение прайс за группу с учетом скидки за привилегии
|
||||
// ищем в скидках скидку за эту группу, для этого юзера, за 2 слой, если найдена то применяем
|
||||
// и добавляем группу в мапу для предотвращения повторного применения скидки за группу
|
||||
noAccept := make(map[string]struct{})
|
||||
for group, nowPrice := range groupPrices {
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.Group != nil && *discount.Condition.Group == group && discount.Layer == 2 && discount.Condition.User != nil && *discount.Condition.User == conditions.Common.User {
|
||||
groupPrices[group] += uint64(float64(nowPrice) * discount.Target.Factor)
|
||||
noAccept[group] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
// вычисляем оставшиеся скидки за сервис с ограничениями noAccept
|
||||
for group, nowPrice := range groupPrices {
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.Group != nil && *discount.Condition.Group == group && discount.Layer == 2 {
|
||||
if _, ok := noAccept[*discount.Condition.Group]; !ok {
|
||||
groupPrices[group] += uint64(float64(nowPrice) * discount.Target.Factor)
|
||||
applyed = append(applyed, discount)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// вычислям сумму корзины за 1 и 2 слой для 3 слоя
|
||||
for _, val := range groupPrices {
|
||||
price += val
|
||||
}
|
||||
|
||||
fmt.Println("GPP", conditions.Common.CartPurchasesAmount)
|
||||
conditions.Common.CartPurchasesAmount += price
|
||||
// если сумма корзины на этом этапе равна 0, то лен(groupPrices) =0 следовательно 3,4 слои тоже будут без скидок
|
||||
// заполним groupPrices и почитаем conditions.Common.CartPurchasesAmount
|
||||
if conditions.Common.CartPurchasesAmount == 0 {
|
||||
for pr, p := range privilegePrices {
|
||||
conditions.Common.CartPurchasesAmount += p
|
||||
groupPrices[privilegeGroups[pr]] += p
|
||||
}
|
||||
}
|
||||
|
||||
//restrictions = noAccept
|
||||
|
||||
keyGroup = "condition.user"
|
||||
keyParam = "condition.cartPurchasesAmount"
|
||||
|
||||
case 3:
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
if err != nil {
|
||||
return []models.Discount{}, uint64(0), err
|
||||
}
|
||||
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.User != nil && *discount.Condition.User == "" && discount.Layer == 3 {
|
||||
for gr, pr := range groupPrices {
|
||||
if _, ok := noAccept[gr]; !ok {
|
||||
groupPrices[gr] = uint64(float64(pr) * discount.Target.Factor)
|
||||
}
|
||||
}
|
||||
applyed = append(applyed, discount)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
keyGroup = "condition.userType"
|
||||
keyParam = "condition.purchasesAmount"
|
||||
|
||||
case 4:
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
if err != nil {
|
||||
return []models.Discount{}, uint64(0), err
|
||||
}
|
||||
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.User != nil && *discount.Condition.User == "" && discount.Layer == 4 {
|
||||
for gr, pr := range groupPrices {
|
||||
if _, ok := noAccept[gr]; !ok {
|
||||
groupPrices[gr] = uint64(float64(pr) * discount.Target.Factor)
|
||||
}
|
||||
}
|
||||
applyed = append(applyed, discount)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var finishPrice uint64
|
||||
for _, p := range groupPrices {
|
||||
finishPrice += p
|
||||
}
|
||||
|
||||
return applyed, finishPrice, nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) FindByID(ctx context.Context, id string) (*models.Discount, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to parse ObjectID <%s> on <FindByID> of <DiscountRepository>: %v", id, err)
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
|
||||
filter := bson.M{
|
||||
fields.Discount.ID: objectID,
|
||||
fields.Discount.Deprecated: false,
|
||||
fields.Audit.Deleted: false,
|
||||
}
|
||||
|
||||
discount, err := mongoWrapper.FindOne[models.Discount](ctx, &mongoWrapper.RequestSettings{
|
||||
Driver: receiver.mongoDB,
|
||||
Filter: filter,
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to find discount <%s> on <FindByID> of <DiscountRepository>: %v", id, err)
|
||||
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil, ErrNoRecord
|
||||
}
|
||||
|
||||
return nil, ErrFindRecord
|
||||
}
|
||||
|
||||
return discount, nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) FindByUserID(ctx context.Context, userID string) ([]models.Discount, error) {
|
||||
filter := bson.M{
|
||||
"$or": expression.GetValueConditionBSON(fields.DiscountCondition.User, userID),
|
||||
fields.Discount.Deprecated: false,
|
||||
fields.Audit.Deleted: false,
|
||||
}
|
||||
|
||||
discounts, err := mongoWrapper.Find[models.Discount](ctx, &mongoWrapper.RequestSettings{
|
||||
Driver: receiver.mongoDB,
|
||||
Filter: filter,
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to find user <%s> discount on <FindByUserID> of <DiscountRepository>: %v", userID, err)
|
||||
return nil, ErrFindRecord
|
||||
}
|
||||
|
||||
return discounts, nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) FindAll(ctx context.Context) ([]models.Discount, error) {
|
||||
filter := bson.M{
|
||||
fields.Audit.Deleted: false,
|
||||
fields.Discount.Deprecated: false,
|
||||
}
|
||||
|
||||
discounts, err := mongoWrapper.Find[models.Discount](ctx, &mongoWrapper.RequestSettings{
|
||||
Driver: receiver.mongoDB,
|
||||
Filter: filter,
|
||||
})
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to find all discount on <FindAll> of <DiscountRepository>: %v", err)
|
||||
return nil, ErrFindRecord
|
||||
}
|
||||
|
||||
return discounts, nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) UpdateOne(ctx context.Context, request *core.UpdateDiscountSettings) (*models.Discount, error) {
|
||||
if request == nil {
|
||||
receiver.logger.Errorln("empy update on <UpdateOne> of <DiscountRepository>")
|
||||
return nil, ErrEmptyArgs
|
||||
}
|
||||
|
||||
update := discount.GetUpdateDiscountExpression(request)
|
||||
|
||||
objectID, err := primitive.ObjectIDFromHex(update.ID)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to parse ObjectID <%s> on <UpdateOne> of <DiscountRepository>: %v", update.ID, err)
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
|
||||
updatedDiscount := models.Discount{}
|
||||
options := options.FindOneAndUpdate().SetUpsert(false).SetReturnDocument(options.After)
|
||||
|
||||
filter := bson.M{
|
||||
fields.Discount.ID: objectID,
|
||||
}
|
||||
|
||||
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update.Expression, options).Decode(&updatedDiscount); err != nil {
|
||||
receiver.logger.Errorf("failed to update discount with id <%s> on <UpdateOne> of <DiscountRepository>: %v", update.ID, err)
|
||||
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil, ErrNoRecord
|
||||
}
|
||||
|
||||
return nil, ErrUpdateRecord
|
||||
}
|
||||
|
||||
return &updatedDiscount, nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) UpdateMany(ctx context.Context, updates []core.UpdateDiscountSettings) error {
|
||||
if len(updates) < 1 {
|
||||
receiver.logger.Errorln("empy updates on <UpdateMany>")
|
||||
return ErrEmptyArgs
|
||||
}
|
||||
|
||||
transactionOptions := options.Transaction().
|
||||
SetReadConcern(readconcern.Snapshot()).
|
||||
SetWriteConcern(writeconcern.New(writeconcern.WMajority()))
|
||||
|
||||
session, err := receiver.mongoDB.Database().Client().StartSession()
|
||||
if err != nil {
|
||||
receiver.logger.Errorln("failed to start session on <UpdateMany> of <DiscountRepository>")
|
||||
return ErrTransactionSessionStart
|
||||
}
|
||||
|
||||
defer session.EndSession(ctx)
|
||||
|
||||
if _, transactionError := session.WithTransaction(ctx, func(sessionContext mongo.SessionContext) (interface{}, error) {
|
||||
for _, update := range updates {
|
||||
updateCopy := update
|
||||
|
||||
if _, err := receiver.UpdateOne(sessionContext, &updateCopy); err != nil {
|
||||
receiver.logger.Errorf("failed to update <%s> in transaction on <UpdateMany> of <DiscountRepository>: %v", update.ID, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}, transactionOptions); transactionError != nil {
|
||||
receiver.logger.Errorf("failed to transaction on <UpdateMany> of <DiscountRepository>: %v", transactionError)
|
||||
return ErrTransaction
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) Insert(ctx context.Context, discount *models.Discount) (string, error) {
|
||||
if discount.Condition.User != nil && *discount.Condition.User != "" {
|
||||
filter := bson.M{"condition.user": *discount.Condition.User, "audit.deleted": false}
|
||||
update := bson.M{
|
||||
"$set": bson.M{"audit.deleted": true},
|
||||
}
|
||||
_, err := receiver.mongoDB.UpdateMany(ctx, filter, update)
|
||||
if err != nil && err != mongo.ErrNoDocuments {
|
||||
return "", ErrAlreadyExistDiscount
|
||||
}
|
||||
}
|
||||
|
||||
res, err := receiver.mongoDB.InsertOne(ctx, discount.Sanitize())
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to insert record on <Insert> of <DiscountRepository>: %v", err)
|
||||
return "", ErrInsertRecord
|
||||
}
|
||||
|
||||
return res.InsertedID.(primitive.ObjectID).Hex(), nil
|
||||
}
|
||||
|
||||
func (receiver *DiscountRepository) DeleteByID(ctx context.Context, id string) (*models.Discount, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
receiver.logger.Errorf("failed to parse ObjectID <%s> on <DeleteByID> of <DiscountRepository>: %v", id, err)
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
|
||||
discount := models.Discount{}
|
||||
now := time.Now()
|
||||
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
||||
|
||||
update := bson.M{"$set": bson.M{
|
||||
fields.Audit.Deleted: true,
|
||||
fields.Audit.DeletedAt: now,
|
||||
fields.Audit.UpdatedAt: now,
|
||||
}}
|
||||
|
||||
filter := bson.M{
|
||||
fields.Discount.ID: objectID,
|
||||
}
|
||||
|
||||
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&discount); err != nil {
|
||||
receiver.logger.Errorf("failed to set 'deleted=true' with id <%s> on <DeleteByID> of <DiscountRepository>: %v", id, err)
|
||||
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil, ErrNoRecord
|
||||
}
|
||||
|
||||
return nil, ErrUpdateRecord
|
||||
}
|
||||
|
||||
return &discount, nil
|
||||
}
|
@ -47,8 +47,6 @@ func (receiver *DiscountRepository) getLayer(ctx context.Context, keyGroup, keyP
|
||||
},
|
||||
}
|
||||
|
||||
receiver.logger.Info("DR cf", conditionFilter)
|
||||
|
||||
cursor, err := receiver.mongoDB.Aggregate(ctx, mongo.Pipeline{
|
||||
bson.D{
|
||||
{Key: "$match", Value: filter},
|
||||
@ -56,6 +54,7 @@ func (receiver *DiscountRepository) getLayer(ctx context.Context, keyGroup, keyP
|
||||
bson.D{
|
||||
{Key: "$sort", Value: bson.M{
|
||||
keyGroup: 1,
|
||||
"target.overhelm": -1,
|
||||
keyParam: -1,
|
||||
}},
|
||||
},
|
||||
@ -111,11 +110,10 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
continue
|
||||
}
|
||||
// вычисляем количество привилегий во всей корзине
|
||||
fmt.Println("GRP", *condition.Group)
|
||||
privilegeAmounts[*condition.Product] += *condition.Term
|
||||
privilegePrices[*condition.Product] += *condition.PriceFrom
|
||||
if _, ok := privilegeAmounts[*condition.Product]; !ok {
|
||||
privilegeGroups[*condition.Product] = *condition.Group
|
||||
}
|
||||
privilegeGroups[*condition.Product] = *condition.Group
|
||||
}
|
||||
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
@ -139,6 +137,7 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
|
||||
// сначала делаем все нужные проверки записываем запреты
|
||||
for privilege, privilegePrice := range privilegePrices {
|
||||
fmt.Println("PREPPRIV", privilege, privilegePrice)
|
||||
|
||||
// проверки существования скидки за 2 слой noAccept не применям скидки к этой группе если есть такие
|
||||
for _, discount := range discounts {
|
||||
@ -151,14 +150,16 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
// только конкретно на привилегию
|
||||
for _, discount := range discounts {
|
||||
if _, ok := noAccept[privilegeGroups[privilege]]; !ok {
|
||||
if discount.Condition.User != nil && *discount.Condition.User == conditions.Common.User && discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 {
|
||||
groupPrices[privilegeGroups[privilege]] += uint64(float64(privilegePrice) * discount.Target.Factor)
|
||||
if discount.Target.Overhelm && discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 {
|
||||
fmt.Println("PREPPRIV1", groupPrices, *discount.Condition.User, conditions.Common.User, privilege, *discount.Condition.Product, discount.Layer )
|
||||
groupPrices[privilegeGroups[privilege]] += uint64(float64(privilegePrice) * discount.Target.Products[0].Factor)
|
||||
applyed = append(applyed, discount)
|
||||
priority[privilege] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("PREPPRIV3", groupPrices)
|
||||
|
||||
for privilege, privilegePrice := range privilegePrices {
|
||||
found := false
|
||||
@ -166,37 +167,43 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
for _, discount := range discounts {
|
||||
if _, ok := noAccept[privilegeGroups[privilege]]; !ok {
|
||||
if _, ok := priority[privilege]; !ok {
|
||||
if discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 {
|
||||
if discount.Condition.Product != nil && privilege == *discount.Condition.Product && discount.Layer == 1 && *discount.Condition.User == "" {
|
||||
fmt.Println("PREPPRIV4", groupPrices, privilege)
|
||||
groupPrices[privilegeGroups[privilege]] += uint64(float64(privilegePrice) * discount.Target.Factor)
|
||||
applyed = append(applyed, discount)
|
||||
found = true
|
||||
// сли у нас в ревесте есть такая привилегия но ее нет в пришедших скидках, просто добавляем ее в groupPrices с ключем группы
|
||||
}
|
||||
} else {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
fmt.Println("PREPPRIV5", groupPrices, privilege,privilegePrice)
|
||||
groupPrices[privilegeGroups[privilege]] += privilegePrice
|
||||
}
|
||||
fmt.Println("PREPPRIV2", groupPrices, privilege, privilegePrice)
|
||||
}
|
||||
|
||||
keyGroup = "condition.group"
|
||||
keyParam = "condition.priceFrom"
|
||||
|
||||
case 2:
|
||||
fmt.Println("PV4", groupPrices)
|
||||
discounts, err := receiver.getLayer(ctx, keyGroup, keyParam, layer, privilegeAmounts, groupPrices, conditions)
|
||||
if err != nil {
|
||||
return []models.Discount{}, uint64(0), err
|
||||
}
|
||||
}
|
||||
var price uint64
|
||||
|
||||
// проходимся по мапе где ключ группа и значение прайс за группу с учетом скидки за привилегии
|
||||
// ищем в скидках скидку за эту группу, для этого юзера, за 2 слой, если найдена то применяем
|
||||
// и добавляем группу в мапу для предотвращения повторного применения скидки за группу
|
||||
noAccept := make(map[string]struct{})
|
||||
for group, nowPrice := range groupPrices {
|
||||
for _, discount := range discounts {
|
||||
if discount.Condition.Group != nil && *discount.Condition.Group == group && discount.Layer == 2 && discount.Condition.User != nil && *discount.Condition.User == conditions.Common.User {
|
||||
fmt.Println("PV3", group, nowPrice, conditions.Common.User, *discount.Condition.User)
|
||||
if discount.Condition.Group != nil && *discount.Condition.Group == group && discount.Layer == 2 && *discount.Condition.User == conditions.Common.User {
|
||||
groupPrices[group] += uint64(float64(nowPrice) * discount.Target.Factor)
|
||||
noAccept[group] = struct{}{}
|
||||
}
|
||||
@ -205,6 +212,7 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
// вычисляем оставшиеся скидки за сервис с ограничениями noAccept
|
||||
for group, nowPrice := range groupPrices {
|
||||
for _, discount := range discounts {
|
||||
fmt.Println("PV2", group, nowPrice, discount)
|
||||
if discount.Condition.Group != nil && *discount.Condition.Group == group && discount.Layer == 2 {
|
||||
if _, ok := noAccept[*discount.Condition.Group]; !ok {
|
||||
groupPrices[group] += uint64(float64(nowPrice) * discount.Target.Factor)
|
||||
@ -213,13 +221,14 @@ func (receiver *DiscountRepository) Determine(ctx context.Context, conditions *c
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("PV2", groupPrices)
|
||||
|
||||
// вычислям сумму корзины за 1 и 2 слой для 3 слоя
|
||||
for _, val := range groupPrices {
|
||||
price += val
|
||||
}
|
||||
|
||||
fmt.Println("GPP", conditions.Common.CartPurchasesAmount)
|
||||
fmt.Println("GPP", price, groupPrices, conditions.Common.CartPurchasesAmount)
|
||||
conditions.Common.CartPurchasesAmount += price
|
||||
// если сумма корзины на этом этапе равна 0, то лен(groupPrices) =0 следовательно 3,4 слои тоже будут без скидок
|
||||
// заполним groupPrices и почитаем conditions.Common.CartPurchasesAmount
|
||||
|
@ -30,6 +30,7 @@ func ConditionFilter(conditions *core.DiscountConditions, privilegeAmounts, grou
|
||||
"$and": []bson.M{
|
||||
{fields.DiscountCondition.Product: product},
|
||||
{fields.DiscountCondition.Term: bson.M{"$lte": amount}},
|
||||
{fields.DiscountCondition.User: ""},
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -48,6 +49,7 @@ func ConditionFilter(conditions *core.DiscountConditions, privilegeAmounts, grou
|
||||
"$and": []bson.M{
|
||||
{fields.DiscountCondition.Group: group},
|
||||
{fields.DiscountCondition.PriceFrom: bson.M{"$lte": price}},
|
||||
{fields.DiscountCondition.User: ""},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user