2023-05-17 20:27:09 +00:00
|
|
|
package repository
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-05-19 04:50:40 +00:00
|
|
|
"log"
|
2023-05-17 20:27:09 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"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.uber.org/zap"
|
2024-02-02 12:15:03 +00:00
|
|
|
mongoWrapper "penahub.gitlab.yandexcloud.net/backend/penahub_common/mongo"
|
2023-05-17 20:27:09 +00:00
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
|
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AccountRepositoryDeps struct {
|
|
|
|
Logger *zap.Logger
|
2023-05-19 04:50:40 +00:00
|
|
|
MongoDB *mongo.Collection
|
2023-05-17 20:27:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type AccountRepository struct {
|
|
|
|
logger *zap.Logger
|
2023-05-19 04:50:40 +00:00
|
|
|
mongoDB *mongo.Collection
|
2023-05-17 20:27:09 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 22:51:34 +00:00
|
|
|
func NewAccountRepository(deps AccountRepositoryDeps) *AccountRepository {
|
2023-05-19 04:50:40 +00:00
|
|
|
if deps.Logger == nil {
|
|
|
|
log.Panicln("logger is nil on <NewAccountRepository>")
|
|
|
|
}
|
|
|
|
|
|
|
|
if deps.MongoDB == nil {
|
2023-05-19 07:18:33 +00:00
|
|
|
log.Panicln("mongodb is nil on <NewAccountRepository>")
|
2023-05-19 04:50:40 +00:00
|
|
|
}
|
|
|
|
|
2023-05-17 20:27:09 +00:00
|
|
|
return &AccountRepository{
|
|
|
|
logger: deps.Logger,
|
2023-05-19 04:50:40 +00:00
|
|
|
mongoDB: deps.MongoDB,
|
2023-05-17 20:27:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error) {
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: id,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-17 20:27:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
account, err := mongoWrapper.FindOne[models.Account](ctx, &mongoWrapper.RequestSettings{
|
|
|
|
Driver: receiver.mongoDB,
|
|
|
|
Filter: filter,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to find account by userID on <FindByUserID> of <AccountRepository>",
|
|
|
|
zap.String("id", id),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
findError := errors.New(
|
|
|
|
fmt.Errorf("failed to find account with <%s> on <FindByUserID> of <AccountRepository>: %w", id, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
findError.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, findError
|
|
|
|
}
|
|
|
|
|
|
|
|
return account, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) FindMany(ctx context.Context, page, limit int64) ([]models.Account, errors.Error) {
|
2023-06-16 09:47:11 +00:00
|
|
|
filter := bson.M{fields.Account.IsDeleted: false}
|
2023-05-17 20:27:09 +00:00
|
|
|
findOptions := options.Find()
|
|
|
|
|
|
|
|
skip := (page - 1) * limit
|
|
|
|
|
|
|
|
findOptions.SetSkip(skip)
|
|
|
|
findOptions.SetLimit(limit)
|
|
|
|
|
|
|
|
accounts, err := mongoWrapper.Find[models.Account](ctx, &mongoWrapper.RequestSettings{
|
|
|
|
Driver: receiver.mongoDB,
|
|
|
|
Options: findOptions,
|
|
|
|
Filter: filter,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to find many accounts on <FindMany> of <AccountRepository>",
|
|
|
|
zap.Int64("page", page),
|
|
|
|
zap.Int64("limit", limit),
|
|
|
|
zap.Int64("skip", skip),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to find many accounts on <FindMany> of <AccountRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return accounts, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) Insert(ctx context.Context, account *models.Account) (*models.Account, errors.Error) {
|
2023-06-15 12:45:38 +00:00
|
|
|
result, err := receiver.mongoDB.InsertOne(ctx, account.Sanitize())
|
2023-05-17 20:27:09 +00:00
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to insert account on <Insert> of <AccountRepository>",
|
|
|
|
zap.Any("account", account),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to insert account on <Insert> of <AccountRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
|
|
|
|
account.ID = insertedID
|
|
|
|
|
|
|
|
return account, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) Remove(ctx context.Context, id string) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
2023-06-15 15:44:53 +00:00
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
2023-05-17 20:27:09 +00:00
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: id,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-17 20:27:09 +00:00
|
|
|
}
|
|
|
|
|
2023-05-19 07:18:33 +00:00
|
|
|
update := bson.M{"$set": bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.IsDeleted: true,
|
2023-05-19 07:18:33 +00:00
|
|
|
fields.Account.DeletedAt: time.Now(),
|
|
|
|
}}
|
|
|
|
|
2023-06-15 15:44:53 +00:00
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-05-17 20:27:09 +00:00
|
|
|
receiver.logger.Error("failed to set 'deleted=true' on <Delete> of <AccountRepository>",
|
|
|
|
zap.String("id", id),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to remove account with <%s> on <Remove> of <AccountRepository>: %w", id, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
|
|
|
|
2023-05-18 12:26:37 +00:00
|
|
|
func (receiver *AccountRepository) CountAll(ctx context.Context) (int64, errors.Error) {
|
2023-06-16 09:47:11 +00:00
|
|
|
count, err := receiver.mongoDB.CountDocuments(ctx, bson.M{fields.Account.IsDeleted: false})
|
2023-05-18 12:26:37 +00:00
|
|
|
if err != nil {
|
2023-06-15 15:44:53 +00:00
|
|
|
receiver.logger.Error("failed to count all documents on <CountAll> of <AccountRepository>", zap.Error(err))
|
2023-05-18 12:26:37 +00:00
|
|
|
|
|
|
|
return 0, errors.New(
|
|
|
|
fmt.Errorf("failed to count all documents on <CountAll> of <AccountRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return count, nil
|
|
|
|
}
|
2023-05-19 07:18:33 +00:00
|
|
|
|
|
|
|
func (receiver *AccountRepository) AddItemToCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
2023-06-15 15:44:53 +00:00
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
2023-05-19 07:18:33 +00:00
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-19 07:18:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{
|
2023-06-15 15:44:53 +00:00
|
|
|
"$addToSet": bson.M{fields.Account.Cart: itemID},
|
|
|
|
"$set": bson.M{fields.Account.UpdatedAt: time.Now()},
|
2023-05-19 07:18:33 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 15:44:53 +00:00
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-05-19 07:18:33 +00:00
|
|
|
receiver.logger.Error("failed to add item on <AddItemToCart> of <AccountRepository>",
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.String("itemID", itemID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to add item <%s> account with <%s> on <AddItemToCart> of <AccountRepository>: %w", itemID, userID, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) RemoveItemFromCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
2023-06-15 15:44:53 +00:00
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
2023-05-19 07:18:33 +00:00
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-19 07:18:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{
|
2023-06-15 15:44:53 +00:00
|
|
|
"$pull": bson.M{fields.Account.Cart: itemID},
|
|
|
|
"$set": bson.M{fields.Account.UpdatedAt: time.Now()},
|
2023-05-19 07:18:33 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 15:44:53 +00:00
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-05-19 07:18:33 +00:00
|
|
|
receiver.logger.Error("failed to add item on <AddItemToCart> of <AccountRepository>",
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.String("itemID", itemID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to add item <%s> account with <%s> on <AddItemToCart> of <AccountRepository>: %w", itemID, userID, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
2023-05-22 12:43:15 +00:00
|
|
|
|
|
|
|
func (receiver *AccountRepository) ChangeWallet(ctx context.Context, userID string, wallet *models.Wallet) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
2023-06-15 15:44:53 +00:00
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
2023-05-22 12:43:15 +00:00
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-22 12:43:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{"$set": bson.M{
|
|
|
|
fields.Account.Wallet: wallet,
|
|
|
|
fields.Account.UpdatedAt: time.Now(),
|
|
|
|
}}
|
|
|
|
|
2023-06-15 15:44:53 +00:00
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-05-22 12:43:15 +00:00
|
|
|
receiver.logger.Error("failed to change wallet on <ChangeWallet> of <AccountRepository>",
|
|
|
|
zap.Error(err),
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.Any("wallet", wallet),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to change wallet of account <%s> on <ChangeWallet> of <AccountRepository>: %w", userID, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
2023-05-30 11:33:57 +00:00
|
|
|
|
|
|
|
func (receiver *AccountRepository) ClearCart(ctx context.Context, userID string) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
2023-06-15 15:44:53 +00:00
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
2023-05-30 11:33:57 +00:00
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-05-30 11:33:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{"$set": bson.M{
|
|
|
|
fields.Account.Cart: []string{},
|
|
|
|
fields.Account.UpdatedAt: time.Now(),
|
|
|
|
}}
|
|
|
|
|
2023-06-15 15:44:53 +00:00
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-05-30 11:33:57 +00:00
|
|
|
receiver.logger.Error("failed to clear cart on <ClearCart> of <AccountRepository>",
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to clear cart of account <%s> on <ClearCart> of <AccountRepository>: %w", userID, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
2023-06-15 15:44:53 +00:00
|
|
|
|
|
|
|
func (receiver *AccountRepository) SetStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-06-15 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{"$set": bson.M{
|
|
|
|
fields.Account.Status: status,
|
|
|
|
fields.Account.UpdatedAt: time.Now(),
|
|
|
|
}}
|
|
|
|
|
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
2023-06-15 16:00:01 +00:00
|
|
|
receiver.logger.Error("failed to set status on <SetStatus> of <AccountRepository>",
|
2023-06-15 15:44:53 +00:00
|
|
|
zap.Error(err),
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.String("status", string(status)),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
2023-06-15 16:00:01 +00:00
|
|
|
fmt.Errorf("failed to set status <%s> to account <%s> on <SetStatus> of <AccountRepository>: %w", status, userID, err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *AccountRepository) UpdateName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error) {
|
|
|
|
account := models.Account{}
|
|
|
|
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
|
|
|
|
|
|
|
filter := bson.M{
|
2023-06-16 09:47:11 +00:00
|
|
|
fields.Account.UserID: userID,
|
|
|
|
fields.Account.IsDeleted: false,
|
2023-06-15 16:00:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update := bson.M{"$set": bson.M{
|
|
|
|
fields.Account.Name: name,
|
|
|
|
fields.Account.UpdatedAt: time.Now(),
|
|
|
|
}}
|
|
|
|
|
|
|
|
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
|
|
|
|
receiver.logger.Error("failed to change name on <UpdateName> of <AccountRepository>",
|
|
|
|
zap.Error(err),
|
|
|
|
zap.String("userID", userID),
|
|
|
|
zap.Any("name", name),
|
|
|
|
)
|
|
|
|
|
|
|
|
removeErr := errors.New(
|
|
|
|
fmt.Errorf("failed to change name of account <%s> on <UpdateName> of <AccountRepository>: %w", userID, err),
|
2023-06-15 15:44:53 +00:00
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
removeErr.SetType(errors.ErrNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, removeErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return &account, nil
|
|
|
|
}
|
2024-04-15 09:27:00 +00:00
|
|
|
|
|
|
|
type QuizLogoStatDeps struct {
|
|
|
|
From *int
|
|
|
|
Limit *int
|
|
|
|
Page *int
|
|
|
|
To *int
|
|
|
|
}
|
|
|
|
|
2024-04-24 12:20:21 +00:00
|
|
|
type QuizLogoStats struct {
|
|
|
|
ID string `bson:"_id"`
|
|
|
|
Regs int `bson:"regs"`
|
|
|
|
Money int64 `bson:"money"`
|
|
|
|
Quizes []Quiz `bson:"quizes"`
|
|
|
|
}
|
2024-04-15 09:27:00 +00:00
|
|
|
|
2024-04-24 12:20:21 +00:00
|
|
|
type Quiz struct {
|
|
|
|
QuizID string `bson:"quiz"`
|
|
|
|
Regs int `bson:"regs"`
|
|
|
|
Money int64 `bson:"money"`
|
|
|
|
}
|
2024-04-15 09:27:00 +00:00
|
|
|
|
2024-04-24 12:20:21 +00:00
|
|
|
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)}}},
|
2024-04-24 12:35:55 +00:00
|
|
|
{"from", bson.D{{"$exists", true}, {"$ne", ""}}},
|
|
|
|
{"partner", bson.D{{"$exists", true}, {"$ne", ""}}},
|
2024-04-24 12:20:21 +00:00
|
|
|
}},
|
|
|
|
}
|
|
|
|
pipeline = append(pipeline, match)
|
|
|
|
} else {
|
|
|
|
match := bson.D{
|
|
|
|
{"$match", bson.D{
|
2024-04-24 12:35:55 +00:00
|
|
|
{"from", bson.D{{"$exists", true}, {"$ne", ""}}},
|
|
|
|
{"partner", bson.D{{"$exists", true}, {"$ne", ""}}},
|
2024-04-24 12:20:21 +00:00
|
|
|
}},
|
|
|
|
}
|
|
|
|
pipeline = append(pipeline, match)
|
|
|
|
}
|
|
|
|
|
|
|
|
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"},
|
|
|
|
}}}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}...)
|
|
|
|
|
|
|
|
var results []QuizLogoStats
|
|
|
|
|
|
|
|
cursor, err := receiver.mongoDB.Aggregate(ctx, pipeline)
|
2024-04-15 09:27:00 +00:00
|
|
|
if err != nil {
|
2024-04-24 12:20:21 +00:00
|
|
|
return nil, err
|
2024-04-15 09:27:00 +00:00
|
|
|
}
|
|
|
|
defer cursor.Close(ctx)
|
2024-04-24 12:20:21 +00:00
|
|
|
|
|
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
|
|
return nil, err
|
2024-04-15 09:27:00 +00:00
|
|
|
}
|
|
|
|
|
2024-04-24 12:20:21 +00:00
|
|
|
return results, nil
|
2024-04-15 09:27:00 +00:00
|
|
|
}
|