package wallet import ( "context" "fmt" "log" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate" ) type accountRepository interface { ChangeWallet(ctx context.Context, userID string, wallet *models.Wallet) (*models.Account, errors.Error) FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error) } type currencyClient interface { Translate(context.Context, *models.TranslateCurrency) (float64, errors.Error) } type Deps struct { Logger *zap.Logger Repository accountRepository CurrencyClient currencyClient } type Service struct { logger *zap.Logger repository accountRepository currencyClient currencyClient } 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.CurrencyClient == nil { log.Panicln("CurrencyClient is nil on ") } return &Service{ logger: deps.Logger, repository: deps.Repository, currencyClient: deps.CurrencyClient, } } func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *models.ReplenishAccountWallet) (*models.Account, errors.Error) { account, err := receiver.repository.FindByUserID(ctx, request.UserID) if err != nil { receiver.logger.Error("failed to find account on of ", zap.Error(err.Extract()), zap.String("userID", request.UserID), ) return nil, err } if validate.IsStringEmpty(account.Wallet.Currency) { return nil, errors.New( fmt.Errorf("currency of account <%s> is empty of ", account.UserID), errors.ErrInternalError, ) } cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{ Money: request.Cash, From: request.Currency, To: account.Wallet.Currency, }) if err != nil { receiver.logger.Error("failed to translate cash on of ", zap.Error(err.Extract()), ) return nil, err } if request.Currency == models.InternalCurrencyKey { updatedAccount, changeErr := receiver.repository.ChangeWallet(ctx, account.UserID, &models.Wallet{ Cash: account.Wallet.Cash + cash, Money: account.Wallet.Money + request.Cash, Currency: account.Wallet.Currency, }) if changeErr != nil { receiver.logger.Error("failed to replenish wallet on of ", zap.Error(changeErr.Extract()), zap.String("Currency", account.Wallet.Currency), zap.Float64("Money", account.Wallet.Money+request.Cash), zap.Float64("Cash", account.Wallet.Cash+cash), zap.Bool("Is currensy equal internal", request.Currency == models.InternalCurrencyKey), ) return nil, changeErr } return updatedAccount, nil } money, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{ Money: request.Cash, From: request.Currency, To: models.InternalCurrencyKey, }) if err != nil { receiver.logger.Error("failed to translate money on of ", zap.Error(err.Extract()), ) return nil, err } updatedAccount, err := receiver.repository.ChangeWallet(ctx, account.UserID, &models.Wallet{ Cash: account.Wallet.Cash + cash, Money: account.Wallet.Money + money, Currency: account.Wallet.Currency, }) if err != nil { receiver.logger.Error("failed to replenish wallet on of ", zap.Error(err.Extract()), zap.String("Currency", account.Wallet.Currency), zap.Float64("Money", account.Wallet.Money+request.Cash), zap.Float64("Cash", account.Wallet.Cash+cash), zap.Bool("Is currensy equal internal", request.Currency == models.InternalCurrencyKey), ) return nil, err } return updatedAccount, nil } func (receiver *Service) ChangeCurrency(ctx context.Context, userID string, currency models.CurrencyKey) (*models.Account, errors.Error) { account, err := receiver.repository.FindByUserID(ctx, userID) if err != nil { receiver.logger.Error("failed to find account on of ", zap.Error(err.Extract()), zap.String("userID", userID), zap.Any("currency", currency), ) return nil, err } cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{ Money: account.Wallet.Cash, From: account.Wallet.Currency, To: currency, }) if err != nil { receiver.logger.Error("failed to translate currency on of ", zap.Error(err.Extract()), ) return nil, err } updatedAccount, err := receiver.repository.ChangeWallet(ctx, account.UserID, &models.Wallet{ Cash: cash, Currency: currency, Money: account.Wallet.Money, }) if err != nil { receiver.logger.Error("failed to update wallet on of ", zap.Error(err.Extract()), ) return nil, err } return updatedAccount, nil }