refactor with new ag query

This commit is contained in:
Pavel 2024-04-24 15:20:21 +03:00
parent eea77bf2e9
commit 7d3bb7c675
4 changed files with 122 additions and 103 deletions

@ -975,29 +975,33 @@ components:
type: string
example: user not found
QuizLogoStat:
type: object
type: array
properties:
count:
# count:
# type: integer
# description: Общее количество
_id:
type: string
description: user id
money:
type: integer
description: Общее количество
items:
type: object
additionalProperties:
type: object
properties:
money:
type: integer
description: Количество денег
regs:
type: integer
description: Количество регистраций
quizes:
type: object
additionalProperties:
type: array
items:
type: integer
description: Массив значений для каждого квиза 1 элемент регистрации по квизу, второй количество денег по квизу
description: Количество денег
regs:
type: integer
description: Количество регистраций
quizes:
type: array
properties:
quiz:
type: string
description: qid quiz
regs:
type: integer
description: Количество регистраций
money:
type: integer
description: Количество денег
securitySchemes:
Bearer: # arbitrary name for the security scheme

@ -410,47 +410,106 @@ type QuizLogoStatDeps struct {
To *int
}
func (receiver *AccountRepository) QuizLogoStat(ctx context.Context, req QuizLogoStatDeps) ([]models.Account, int64, error) {
filter := bson.M{
"from": bson.M{"$ne":"","$exists":true},
"partner": bson.M{"$ne":"","$exists":true},
}
filter2 := bson.M{
"from": bson.M{"$ne":"","$exists":true},
"partner": bson.M{"$ne":"","$exists":true},
}
if req.From != nil || req.To != nil {
timeRange := bson.M{}
if *req.From != 0 {
timeRange["$gte"] = time.Unix(int64(*req.From), 0)
type QuizLogoStats struct {
ID string `bson:"_id"`
Regs int `bson:"regs"`
Money int64 `bson:"money"`
Quizes []Quiz `bson:"quizes"`
}
type Quiz struct {
QuizID string `bson:"quiz"`
Regs int `bson:"regs"`
Money int64 `bson:"money"`
}
func (receiver *AccountRepository) QuizLogoStat(ctx context.Context, req QuizLogoStatDeps) ([]QuizLogoStats, error) {
var pipeline mongo.Pipeline
if req.From != nil && req.To != nil {
match := bson.D{
{"$match", bson.D{
{"createdAt", bson.D{{"$gte", time.Unix(int64(*req.From), 0)}}},
{"createdAt", bson.D{{"$lte", time.Unix(int64(*req.To), 0)}}},
{"from", bson.D{{"$exists", true}}},
{"partner", bson.D{{"$exists", true}}},
}},
}
if *req.To != 0 {
timeRange["$lte"] = time.Unix(int64(*req.To), 0)
pipeline = append(pipeline, match)
} else {
match := bson.D{
{"$match", bson.D{
{"from", bson.D{{"$exists", true}}},
{"partner", bson.D{{"$exists", true}}},
}},
}
filter["createdAt"] = timeRange
pipeline = append(pipeline, match)
}
options := options.Find()
if req.Page != nil && req.Limit != nil {
options.SetSkip(int64(*req.Page * *req.Limit))
options.SetLimit(int64(*req.Limit))
}
pipeline = append(pipeline, mongo.Pipeline{
{
{"$lookup", bson.D{
{"from", "histories"},
{"localField", "userId"},
{"foreignField", "userId"},
{"as", "history"},
}},
},
{
{"$unwind", bson.D{
{"path", "$history"},
{"preserveNullAndEmptyArrays", true},
}},
},
{
{"$match", bson.D{
{"$or", bson.A{
bson.D{{"history", bson.D{{"$exists", false}}}},
bson.D{{"history.key", "payment.succeeded"}},
}},
}},
},
{
{"$group", bson.D{
{"_id", "$userId"},
{"partner", bson.D{{"$first", "$partner"}}},
{"from", bson.D{{"$first", "$from"}}},
{"sum", bson.D{{"$sum", "$history.rawDetails.price"}}},
}},
},
{
{"$group", bson.D{
{"_id", "$from"},
{"partner", bson.D{{"$first", "$partner"}}},
{"regs", bson.D{{"$count", bson.D{}}}},
{"money", bson.D{{"$sum", "$sum"}}},
}},
},
{
{"$group", bson.D{
{"_id", "$partner"},
{"regs", bson.D{{"$sum", "$regs"}}},
{"money", bson.D{{"$sum", "$money"}}},
{"quizes", bson.D{{"$push", bson.D{
{"quiz", "$_id"},
{"regs", "$regs"},
{"money", "$money"},
}}}}},
},
},
}...)
count, err := receiver.mongoDB.CountDocuments(ctx, filter2)
var results []QuizLogoStats
cursor, err := receiver.mongoDB.Aggregate(ctx, pipeline)
if err != nil {
return nil, 0, err
}
fmt.Println("ACCCCCCCCCCCC", filter,options, *req.Limit)
cursor, err := receiver.mongoDB.Find(ctx, filter)
if err != nil {
return nil, 0, err
return nil, err
}
defer cursor.Close(ctx)
var accounts []models.Account
if err := cursor.All(ctx, &accounts); err != nil {
return nil, 0, err
if err := cursor.All(ctx, &results); err != nil {
return nil, err
}
return accounts, count, nil
return results, nil
}

@ -63,7 +63,7 @@ func NewAPI2(logger *zap.Logger, db *mongo.Database, config *models.Config, cons
account: repository.NewAccountRepository2(logger, db.Collection("accounts")),
consumer: consumer,
producer: producer,
encrypt: encrypt,
encrypt: encrypt,
grpc: config.GRPC,
clients: clients{
auth: client.NewAuthClient(client.AuthClientDeps{Logger: logger, URLs: &config.Service.AuthMicroservice.URL}),
@ -874,59 +874,15 @@ func (api *API2) QuizLogoStat(ctx echo.Context) error {
return api.error(ctx, http.StatusBadRequest, "failed to bind request")
}
//получаем аккаунты с непустыми quizfrom и partner, с пагинацией за заданный период
accounts, count, err := api.account.QuizLogoStat(ctx.Request().Context(), repository.QuizLogoStatDeps{
result, err := api.account.QuizLogoStat(ctx.Request().Context(), repository.QuizLogoStatDeps{
Page: req.Page,
Limit: req.Limit,
From: req.From,
To: req.To,
})
if err != nil {
return api.error(ctx, http.StatusInternalServerError, "failed getting accounts in period with pagination")
return api.error(ctx, http.StatusInternalServerError, fmt.Sprint("failed getting quiz logo stat", err.Error()))
}
historyMap, err := api.history.GetHistoryByListUsers(ctx.Request().Context(), accounts)
// partner тот кто позвал quizfrom qid квиза нужно посчитать первое количество регистраций и денег у это партнера и тоже самое по квизу этого партнера
resp := QuizLogoStat2{
Count: count,
Items: make(map[string]Item),
}
fmt.Println("AC", accounts)
for _, account := range accounts {
partner := account.Partner
quizFrom := account.From
fmt.Println("ACC", account)
// проверка на то что существует ли такой партнер в мапе
if _, exists := resp.Items[partner]; !exists {
resp.Items[partner] = Item{
Money: 0,
Quizes: make(map[string][2]int),
Regs: 0,
}
}
// тут аналогичная проверка на Quizes
if _, exists := resp.Items[partner].Quizes[quizFrom]; !exists {
resp.Items[partner].Quizes[quizFrom] = [2]int{0, 0}
}
// если все ок то начинаем получать историю
historys := historyMap[account.UserID]
// ренжим историю заполняем resp прайс из RawDetails также инкрементируем значения регистраций
currentItem := resp.Items[partner]
currentItem.Regs++
fmt.Println("ACCC", currentItem, resp)
for _, history := range historys {
currentItem.Money += history.RawDetails.Price
currentQuizes := currentItem.Quizes[quizFrom]
// первый элемент это регистрации по квизу
currentQuizes[0] = currentQuizes[0] + 1
// второй элемент прайс по квизу
currentQuizes[1] = currentQuizes[1] + int(history.RawDetails.Price)
currentItem.Quizes[quizFrom] = currentQuizes
}
resp.Items[partner] = currentItem
}
return ctx.JSON(http.StatusOK, resp)
return ctx.JSON(http.StatusOK, result)
}

@ -26,7 +26,7 @@ func TestLogostat(t *testing.T) {
mongoDB, err := mongo.Connect(ctx, &mongo.ConnectDeps{
Configuration: &mongo.Configuration{
Host: "localhost",
Port: "27024",
Port: "27020",
User: "test",
Password: "test",
Auth: "admin",