2023-05-23 10:52:27 +00:00
|
|
|
package repository
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
2023-10-16 12:12:12 +00:00
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
2023-05-23 10:52:27 +00:00
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
|
"go.mongodb.org/mongo-driver/mongo"
|
2023-05-23 15:24:52 +00:00
|
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
2023-05-23 10:52:27 +00:00
|
|
|
"go.uber.org/zap"
|
2023-09-14 10:02:32 +00:00
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/dto"
|
2023-05-23 10:52:27 +00:00
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
2023-11-25 11:23:19 +00:00
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
|
2023-05-23 10:52:27 +00:00
|
|
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
2023-05-23 15:24:52 +00:00
|
|
|
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
2023-05-23 10:52:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type HistoryRepositoryDeps struct {
|
|
|
|
Logger *zap.Logger
|
|
|
|
MongoDB *mongo.Collection
|
|
|
|
}
|
|
|
|
|
|
|
|
type HistoryRepository struct {
|
|
|
|
logger *zap.Logger
|
|
|
|
mongoDB *mongo.Collection
|
|
|
|
}
|
|
|
|
|
2023-06-13 22:51:34 +00:00
|
|
|
func NewHistoryRepository(deps HistoryRepositoryDeps) *HistoryRepository {
|
2023-05-23 10:52:27 +00:00
|
|
|
if deps.Logger == nil {
|
|
|
|
log.Panicln("logger is nil on <NewHistoryRepository>")
|
|
|
|
}
|
|
|
|
|
|
|
|
if deps.MongoDB == nil {
|
|
|
|
log.Panicln("mongodb is nil on <NewHistoryRepository>")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &HistoryRepository{
|
|
|
|
logger: deps.Logger,
|
|
|
|
mongoDB: deps.MongoDB,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (receiver *HistoryRepository) Insert(ctx context.Context, history *models.History) (*models.History, errors.Error) {
|
2023-06-15 12:45:38 +00:00
|
|
|
result, err := receiver.mongoDB.InsertOne(ctx, history.Sanitize())
|
2023-05-23 10:52:27 +00:00
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to insert history on <Insert> of <HistoryRepository>",
|
|
|
|
zap.Any("history", history),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to insert history on <Insert> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
|
|
|
|
history.ID = insertedID
|
|
|
|
|
|
|
|
return history, nil
|
|
|
|
}
|
|
|
|
|
2023-09-14 10:02:32 +00:00
|
|
|
func (receiver *HistoryRepository) FindMany(ctx context.Context, dto *dto.GetHistories) ([]models.History, errors.Error) {
|
2023-05-23 15:24:52 +00:00
|
|
|
findOptions := options.Find()
|
|
|
|
|
2023-09-14 10:02:32 +00:00
|
|
|
findOptions.SetSkip((dto.Pagination.Page - 1) * dto.Pagination.Limit)
|
|
|
|
findOptions.SetLimit(dto.Pagination.Limit)
|
2023-10-16 12:12:12 +00:00
|
|
|
findOptions.SetSort(bson.D{{
|
|
|
|
Key: "createdAt", Value: -1,
|
|
|
|
}})
|
2023-05-23 15:24:52 +00:00
|
|
|
|
|
|
|
histories, err := mongoWrapper.Find[models.History](ctx, &mongoWrapper.RequestSettings{
|
|
|
|
Driver: receiver.mongoDB,
|
|
|
|
Options: findOptions,
|
2023-09-14 10:02:32 +00:00
|
|
|
Filter: dto.BSON(),
|
2023-05-23 15:24:52 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to find many histories on <FindMany> of <HistoryRepository>",
|
2023-09-14 10:02:32 +00:00
|
|
|
zap.Int64("page", dto.Pagination.Page),
|
|
|
|
zap.Int64("limit", dto.Pagination.Limit),
|
|
|
|
zap.Int64("skip", (dto.Pagination.Page-1)*dto.Pagination.Limit),
|
2023-05-23 15:24:52 +00:00
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to find many histories on <FindMany> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return histories, nil
|
|
|
|
}
|
|
|
|
|
2023-09-14 23:01:53 +00:00
|
|
|
func (receiver *HistoryRepository) CountAll(ctx context.Context, dto *dto.GetHistories) (int64, errors.Error) {
|
|
|
|
count, err := receiver.mongoDB.CountDocuments(ctx, dto.BSON())
|
2023-05-23 10:52:27 +00:00
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to count all documents on <CountAll> of <HistoryRepository>",
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
return 0, errors.New(
|
|
|
|
fmt.Errorf("failed to count all documents on <CountAll> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return count, nil
|
|
|
|
}
|
2023-11-22 17:31:17 +00:00
|
|
|
|
|
|
|
// TODO:tests
|
2023-11-25 11:23:19 +00:00
|
|
|
// GetRecentTariffs method for processing a user request with data aggregation with a limit of 100 sorted in descending order.
|
2023-11-23 18:55:22 +00:00
|
|
|
func (receiver *HistoryRepository) GetRecentTariffs(ctx context.Context, userID string) ([]models.TariffID, errors.Error) {
|
|
|
|
matchStage := bson.D{
|
|
|
|
{Key: "$match", Value: bson.D{
|
|
|
|
{Key: fields.History.UserID, Value: userID},
|
|
|
|
{Key: fields.History.IsDeleted, Value: false},
|
|
|
|
{Key: fields.History.Type, Value: models.CustomerHistoryKeyPayCart},
|
|
|
|
}},
|
2023-11-22 17:31:17 +00:00
|
|
|
}
|
2023-11-22 21:30:59 +00:00
|
|
|
|
2023-11-23 18:55:22 +00:00
|
|
|
sortStage := bson.D{
|
|
|
|
{Key: "$sort", Value: bson.D{
|
|
|
|
{Key: "createdAt", Value: -1},
|
|
|
|
}},
|
|
|
|
}
|
|
|
|
|
|
|
|
limitStage := bson.D{
|
|
|
|
{Key: "$limit", Value: 100},
|
2023-11-22 17:31:17 +00:00
|
|
|
}
|
2023-11-22 18:07:18 +00:00
|
|
|
|
2023-11-23 18:55:22 +00:00
|
|
|
cursor, err := receiver.mongoDB.Aggregate(ctx, mongo.Pipeline{matchStage, sortStage, limitStage})
|
2023-11-22 17:31:17 +00:00
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to get recent tariffs on <GetRecentTariffs> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to get recent tariffs on <GetRecentTariffs> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-11-23 18:55:22 +00:00
|
|
|
var result []models.TariffID
|
2023-11-22 17:31:17 +00:00
|
|
|
if err := cursor.All(ctx, &result); err != nil {
|
|
|
|
receiver.logger.Error("failed to decode recent tariffs on <GetRecentTariffs> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to decode recent tariffs on <GetRecentTariffs> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
2023-11-23 18:55:22 +00:00
|
|
|
|
|
|
|
return result, nil
|
2023-11-22 17:31:17 +00:00
|
|
|
}
|
2023-11-25 18:28:26 +00:00
|
|
|
|
2023-12-01 11:27:44 +00:00
|
|
|
// TODO:tests.
|
2023-11-25 18:28:26 +00:00
|
|
|
func (receiver *HistoryRepository) GetHistoryById(ctx context.Context, historyID string) (*models.ReportHistory, errors.Error) {
|
|
|
|
history := &models.ReportHistory{}
|
|
|
|
err := receiver.mongoDB.FindOne(ctx, bson.M{"_id": historyID}).Decode(history)
|
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error(
|
|
|
|
"failed to find by id in <GetHistoryById> of <HistoryRepository>",
|
|
|
|
zap.String("historyID", historyID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err == mongo.ErrNoDocuments {
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("history not found with ID: %s", historyID),
|
|
|
|
errors.ErrNotFound,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to find by id: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return history, nil
|
|
|
|
}
|
2023-11-29 19:01:14 +00:00
|
|
|
|
2023-12-01 11:27:44 +00:00
|
|
|
// TODO:tests.
|
2023-11-29 19:01:14 +00:00
|
|
|
func (receiver *HistoryRepository) GetDocNumber(ctx context.Context, userID string) (map[string]int, errors.Error) {
|
|
|
|
findOptions := options.Find()
|
|
|
|
findOptions.SetSort(bson.D{{Key: "createdAt", Value: 1}})
|
|
|
|
|
|
|
|
filter := bson.M{
|
|
|
|
fields.History.UserID: userID,
|
|
|
|
}
|
|
|
|
|
|
|
|
cursor, err := receiver.mongoDB.Find(ctx, filter, findOptions)
|
|
|
|
if err != nil {
|
|
|
|
receiver.logger.Error("failed to get DocNumber list on <GetDocNumber> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to get DocNumber list on <GetDocNumber> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
2023-12-01 11:27:44 +00:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err := cursor.Close(ctx); err != nil {
|
|
|
|
receiver.logger.Error("failed to close cursor on <GetDocNumber> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}()
|
2023-11-29 19:01:14 +00:00
|
|
|
|
|
|
|
result := make(map[string]int)
|
|
|
|
var count int
|
|
|
|
for cursor.Next(ctx) {
|
|
|
|
var history models.History
|
|
|
|
if err := cursor.Decode(&history); err != nil {
|
|
|
|
receiver.logger.Error("failed to decode history on <GetDocNumber> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("failed to decode history on <GetDocNumber> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
result[history.ID] = count
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := cursor.Err(); err != nil {
|
|
|
|
receiver.logger.Error("cursor error on <GetDocNumber> of <HistoryRepository>",
|
|
|
|
zap.String("userId", userID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
return nil, errors.New(
|
|
|
|
fmt.Errorf("cursor error on <GetDocNumber> of <HistoryRepository>: %w", err),
|
|
|
|
errors.ErrInternalError,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|