package account import ( "context" "fmt" "log" "math" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" ) type accountRepository interface { FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error) FindMany(ctx context.Context, page, limit int64) ([]models.Account, errors.Error) Insert(ctx context.Context, account *models.Account) (*models.Account, errors.Error) Remove(ctx context.Context, id string) (*models.Account, errors.Error) Delete(ctx context.Context, id string) (*models.Account, errors.Error) CountAll(ctx context.Context) (int64, errors.Error) } type authClient interface { GetUser(ctx context.Context, userID string) (*models.User, errors.Error) } type Deps struct { Logger *zap.Logger Repository accountRepository AuthClient authClient } type Service struct { logger *zap.Logger repository accountRepository authClient authClient } func New(deps *Deps) *Service { if deps == nil { log.Panicln("deps is nil on ") } if deps.Logger == nil { log.Panicln("logger is nil on ") } if deps.Repository == nil { log.Panicln("repository is nil on ") } if deps.AuthClient == nil { log.Panicln("auth client is nil on ") } return &Service{ logger: deps.Logger, repository: deps.Repository, authClient: deps.AuthClient, } } func (receiver *Service) GetAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error) { account, err := receiver.repository.FindByUserID(ctx, userID) if err != nil { receiver.logger.Error("failed to get account by id on of ", zap.Error(err.Extract()), zap.String("userID", userID), ) return nil, err } return account, nil } func (receiver *Service) GetAccountsList(ctx context.Context, pagination *models.Pagination) (*models.PaginationResponse[models.Account], errors.Error) { if pagination == nil { return nil, errors.New( fmt.Errorf("pagination is nil on of : %w", errors.ErrInternalError), errors.ErrInternalError, ) } count, err := receiver.repository.CountAll(ctx) if err != nil { receiver.logger.Error("failed to count accounts on of ", zap.Error(err.Extract()), ) return nil, err } if count == 0 { return &models.PaginationResponse[models.Account]{TotalPages: 0, Records: []models.Account{}}, nil } totalPages := int64(math.Ceil(float64(count) / float64(pagination.Limit))) accounts, err := receiver.repository.FindMany(ctx, pagination.Page, pagination.Limit) if err != nil { receiver.logger.Error("failed to get accounts list on of ", zap.Error(err.Extract()), zap.Int64("page", pagination.Page), zap.Int64("limit", pagination.Limit), ) return nil, err } return &models.PaginationResponse[models.Account]{ TotalPages: totalPages, Records: accounts, }, nil } func (receiver *Service) CreateAccount(ctx context.Context, account *models.Account) (*models.Account, errors.Error) { findedAccount, err := receiver.GetAccountByUserID(ctx, account.UserID) if err != nil && err.Type() != errors.ErrNotFound { receiver.logger.Error("failed to find account on of ", zap.Error(err.Extract()), ) return nil, err } if findedAccount != nil { return nil, errors.New( fmt.Errorf("failed to create account with <%s> on of : %w", account.UserID, errors.ErrConflict, ), errors.ErrConflict, ) } createdAccount, err := receiver.repository.Insert(ctx, account) if err != nil { receiver.logger.Error("failed to create account on of ", zap.Error(err.Extract()), zap.Any("account", account), ) return nil, err } return createdAccount, nil } /* CreateAccountByUserID возвращает аккаут по id пользователя TODO: Дополнить проверку на дефолтное значение Currency. */ func (receiver *Service) CreateAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error) { account, err := receiver.GetAccountByUserID(ctx, userID) if err != nil && err.Type() != errors.ErrNotFound { receiver.logger.Error("failed to find account on of ", zap.Error(err.Extract()), ) return nil, err } if account != nil { return nil, errors.New( fmt.Errorf("failed to create account with <%s> on of : %w", userID, errors.ErrConflict, ), errors.ErrConflict, ) } user, err := receiver.authClient.GetUser(ctx, userID) if err != nil { receiver.logger.Error("failed to get user on of ", zap.Error(err.Extract()), zap.String("userID", userID), ) return nil, err } createdAccount, err := receiver.repository.Insert(ctx, &models.Account{ UserID: user.ID, Cart: make([]string, 0), Wallet: models.Wallet{ Cash: 0, Money: 0, Currency: "", }, }) if err != nil { receiver.logger.Error("failed to create account on of ", zap.Error(err.Extract()), zap.String("userID", userID), ) return nil, err } return createdAccount, nil } func (receiver *Service) RemoveAccount(ctx context.Context, userID string) (*models.Account, errors.Error) { account, err := receiver.repository.Remove(ctx, userID) if err != nil { receiver.logger.Error("failed to remove account on of ", zap.Error(err.Extract()), zap.String("userID", userID), ) return nil, err } return account, nil } func (receiver *Service) DeleteAccount(ctx context.Context, userID string) (*models.Account, errors.Error) { account, err := receiver.repository.Delete(ctx, userID) if err != nil { receiver.logger.Error("failed to delete account on of ", zap.Error(err.Extract()), zap.String("userID", userID), ) return nil, err } return account, nil }