feat: translate currency

This commit is contained in:
Kirill 2023-05-22 15:43:15 +03:00
parent eca6e8c087
commit d7b9a2836e
10 changed files with 415 additions and 62 deletions

@ -0,0 +1,104 @@
package wallet
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"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/internal/utils/echotools"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type walletService interface {
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
ChangeCurrency(ctx context.Context, userID string, currency models.CurrencyKey) (*models.Account, errors.Error)
}
type Deps struct {
Logger *zap.Logger
WalletService walletService
}
type Controller struct {
logger *zap.Logger
walletService walletService
}
func New(deps *Deps) *Controller {
if deps == nil {
log.Panicln("deps is nil on <New (wallet controller)>")
}
if deps.Logger == nil {
log.Panicln("logger is nil on <New (wallet controller)>")
}
if deps.WalletService == nil {
log.Panicln("wallet service is nil on <New (wallet controller)>")
}
return &Controller{
logger: deps.Logger,
walletService: deps.WalletService,
}
}
func (receiver *Controller) PutMoney(ctx echo.Context) error {
request, bindErr := echotools.Bind[models.ReplenishAccountWallet](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind body on <PutMoney> of <WalletController>", zap.Error(bindErr))
return echotools.ResponseError(ctx, errors.New(
fmt.Errorf("failed to parse body on <PutMoney> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
account, err := receiver.walletService.ReplenishAccountWallet(ctx.Request().Context(), request)
if err != nil {
receiver.logger.Error("failed to put money on <PutMoney> of <WalletController>", zap.Error(err.Extract()))
return echotools.ResponseError(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) ChangeCurrency(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <ChangeCurrency> of <WallerController>")
return echotools.ResponseError(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
request, bindErr := echotools.Bind[models.ChangeCurrency](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind body on <ChangeCurrency> of <WalletController>", zap.Error(bindErr))
return echotools.ResponseError(ctx, errors.New(
fmt.Errorf("failed to parse body on <ChangeCurrency> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
if validate.IsStringEmpty(request.Currency) {
return echotools.ResponseError(ctx, errors.New(
fmt.Errorf("empty currency key on <ChangeCurrency> of <WalletController>: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
))
}
account, err := receiver.walletService.ChangeCurrency(ctx.Request().Context(), userID, request.Currency)
if err != nil {
receiver.logger.Error("failed to put money on <ChangeCurrency> of <WalletController>", zap.Error(err.Extract()))
return echotools.ResponseError(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}

@ -14,12 +14,12 @@ type Account struct {
}
type Wallet struct {
Cash int64 `json:"cash"`
Currency string `json:"currency"`
Cash float64 `json:"cash"`
Currency string `json:"currency"`
/*
Money деньги на счету в копейках. Чтобы при перессчётах не возникало денег из ни откуда.
Фиксируемся к одной валюте, она будет внутренней, никому её не покажем.
*/
Money int64 `json:"money"`
Money float64 `json:"money"`
}

@ -15,5 +15,16 @@ type CurrencyList struct {
}
const (
DefaultCurrencyListName = "currency_list"
DefaultCurrencyListName = "currency_list"
InternalCurrencyKey CurrencyKey = "RUB"
)
type TranslateCurrency struct {
Money float64 `json:"money"`
From CurrencyKey `json:"from"`
To CurrencyKey `json:"to"`
}
type ChangeCurrency struct {
Currency CurrencyKey `json:"currency"`
}

@ -0,0 +1,7 @@
package models
type ReplenishAccountWallet struct {
Cash float64 `json:"cash"`
Currency string `json:"currency"`
UserID string `json:"userId"`
}

@ -288,3 +288,38 @@ func (receiver *AccountRepository) RemoveItemFromCart(ctx context.Context, userI
return &account, nil
}
func (receiver *AccountRepository) ChangeWallet(ctx context.Context, userID string, wallet *models.Wallet) (*models.Account, errors.Error) {
account := models.Account{}
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.Deleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.Wallet: wallet,
fields.Account.UpdatedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update).Decode(&account); err != nil {
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
}

@ -0,0 +1,183 @@
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 <New (wallet service)>")
}
if deps.Logger == nil {
log.Panicln("logger is nil on <New (v service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (wallet service)>")
}
if deps.CurrencyClient == nil {
log.Panicln("CurrencyClient is nil on <New (wallet service)>")
}
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 <ReplenishAccountWallet> of <WalletService>",
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 <ReplenishAccountWallet> of <WalletService>", 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 <ReplenishAccountWallet> of <WalletService>",
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 <ReplenishAccountWallet> of <WalletService>",
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 <ReplenishAccountWallet> of <WalletService>",
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 <ReplenishAccountWallet> of <WalletService>",
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 <ChangeCurrency> of <WalletService>",
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 <ChangeCurrency> of <WalletService>",
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 <ChangeCurrency> of <WalletService>",
zap.Error(err.Extract()),
)
return nil, err
}
return updatedAccount, nil
}

@ -383,53 +383,53 @@ var swaggerSpec = []string{
"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",
"AAD//wvut5HlQgAA",
"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",
"uUFLicVOfEOYEa8urP4vAAD//0M8kFn2QgAA",
}
// GetSwagger returns the content of the embedded swagger specification file

@ -29,16 +29,23 @@ type cartController interface {
Add(echo.Context, Add2cartParams) error
}
type walletController interface {
ChangeCurrency(ctx echo.Context) error
PutMoney(ctx echo.Context) error
}
type Deps struct {
AccountController accountController
CurrencyController currencyController
CartController cartController
WalletController walletController
}
type API struct {
accountController accountController
currencyController currencyController
cartController cartController
walletController walletController
}
func New(deps *Deps) *API {
@ -58,10 +65,15 @@ func New(deps *Deps) *API {
log.Panicln("cartController is nil on <New (API)>")
}
if deps.WalletController == nil {
log.Panicln("walletController is nil on <New (API)>")
}
return &API{
accountController: deps.AccountController,
currencyController: deps.CurrencyController,
cartController: deps.CartController,
walletController: deps.WalletController,
}
}
@ -136,5 +148,5 @@ func (receiver *API) ChangeCurrency(ctx echo.Context) error {
}
func (receiver *API) PutMoney(ctx echo.Context) error {
return ctx.String(http.StatusNotImplemented, "method not implemented")
return receiver.walletController.PutMoney(ctx)
}

@ -59,13 +59,13 @@ type HistoryType string
// Wallet defines model for Wallet.
type Wallet struct {
// Cash Сумма money переведённая на текущий курс
Cash int64 `json:"cash"`
Cash float64 `json:"cash"`
// Currency Текущий курс валюты
Currency string `json:"currency"`
// Money Деньги на счету в копейках. Чтобы при перессчётах не возникало денег изниоткуда. фиксируемся к одной валюте, она будет внутренней, никому её не покажем
Money int64 `json:"money"`
Money float64 `json:"money"`
}
// PaginationAccountsParams defines parameters for PaginationAccounts.
@ -118,9 +118,9 @@ type ChangeCurrencyJSONBody struct {
// PutMoneyJSONBody defines parameters for PutMoney.
type PutMoneyJSONBody struct {
Cash int `json:"cash"`
Currency string `json:"currency"`
UserId string `json:"userId"`
Cash float64 `json:"cash"`
Currency string `json:"currency"`
UserId string `json:"userId"`
}
// PayCartJSONRequestBody defines body for PayCart for application/json ContentType.

@ -438,7 +438,8 @@ paths:
required: [cash, currency, userId]
properties:
cash:
type: integer
type: number
format: double
example: 10000
currency:
type: string
@ -621,12 +622,12 @@ components:
example: "RUB"
cash:
description: Сумма money переведённая на текущий курс
type: integer
format: int64
type: number
format: double
example: 10701
money:
type: integer
format: int64
type: number
format: double
description: >-
Деньги на счету в копейках. Чтобы при перессчётах не
возникало денег изниоткуда. фиксируемся к одной валюте,