customer/internal/repository/account.go

196 lines
5.1 KiB
Go
Raw Normal View History

2023-05-17 20:27:09 +00:00
package repository
import (
"context"
"fmt"
"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"
"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"
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
type AccountRepositoryDeps struct {
MongoDB *mongo.Collection
Logger *zap.Logger
}
type AccountRepository struct {
mongoDB *mongo.Collection
logger *zap.Logger
}
func NewAccountRepository(deps *AccountRepositoryDeps) *AccountRepository {
return &AccountRepository{
mongoDB: deps.MongoDB,
logger: deps.Logger,
}
}
func (receiver *AccountRepository) FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error) {
filter := bson.M{
fields.Account.UserID: id,
fields.Account.Deleted: false,
}
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) {
filter := bson.M{fields.Account.Deleted: false}
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) {
account.CreatedAt = time.Now()
account.UpdatedAt = time.Now()
account.Deleted = false
result, err := receiver.mongoDB.InsertOne(ctx, account)
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{}
update := bson.M{"$set": bson.M{fields.Account.Deleted: true}}
filter := bson.M{
fields.Account.UserID: id,
fields.Account.Deleted: false,
}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update).Decode(&account); err != nil {
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
}
func (receiver *AccountRepository) Delete(ctx context.Context, id string) (*models.Account, errors.Error) {
account := models.Account{}
filter := bson.M{
fields.Account.UserID: id,
fields.Account.Deleted: false,
}
if err := receiver.mongoDB.FindOneAndDelete(ctx, filter).Decode(&account); err != nil {
receiver.logger.Error("failed delete account on <Delete> of <AccountRepository>",
zap.String("id", id),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to remove account with <%s> on <Delete> of <AccountRepository>: %w", id, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) CountAll(ctx context.Context) (int64, errors.Error) {
count, err := receiver.mongoDB.CountDocuments(ctx, bson.M{fields.Account.Deleted: false})
if err != nil {
receiver.logger.Error("failed to count all documents on <CountAll> of <AccountRepository>",
zap.Error(err),
)
return 0, errors.New(
fmt.Errorf("failed to count all documents on <CountAll> of <AccountRepository>: %w", err),
errors.ErrInternalError,
)
}
return count, nil
}