customer/internal/service/wallet/wallet.go

334 lines
11 KiB
Go
Raw Normal View History

2023-06-22 09:36:43 +00:00
package wallet
import (
"context"
2023-09-14 10:07:28 +00:00
"fmt"
2023-06-22 09:36:43 +00:00
"log"
2024-02-05 11:13:36 +00:00
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/client"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
2023-06-22 09:36:43 +00:00
"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) (int64, errors.Error)
}
2024-02-04 20:20:52 +00:00
type verificationClient interface {
GetVerification(ctx context.Context, userID string) (*models.Verification, errors.Error)
}
2024-02-05 08:23:35 +00:00
type authClient interface {
GetUser(ctx context.Context, userID string) (*models.User, errors.Error)
}
2023-06-22 09:36:43 +00:00
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type Deps struct {
2024-02-04 20:20:52 +00:00
Logger *zap.Logger
Repository accountRepository
CurrencyClient currencyClient
HistoryService historyService
VerificationClient verificationClient
2024-02-05 08:23:35 +00:00
AuthClient authClient
2024-02-05 11:13:36 +00:00
MailClient *client.MailClient
2023-06-22 09:36:43 +00:00
}
type Service struct {
2024-02-04 20:20:52 +00:00
logger *zap.Logger
repository accountRepository
currencyClient currencyClient
historyService historyService
verificationClient verificationClient
2024-02-05 08:23:35 +00:00
authClient authClient
2024-02-05 11:13:36 +00:00
mailClient *client.MailClient
2023-06-22 09:36:43 +00:00
}
func New(deps Deps) *Service {
2024-02-16 17:41:40 +00:00
fmt.Println("AAAAABBAAAAa", deps)
2023-06-22 09:36:43 +00:00
if deps.Logger == nil {
log.Panicln("logger is nil on <New (wallet 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)>")
}
2024-02-04 20:20:52 +00:00
if deps.VerificationClient == nil {
log.Panicln("VerificationClient is nil on <New (wallet service)>")
}
2024-02-05 08:23:35 +00:00
if deps.AuthClient == nil {
log.Panicln("AuthClient is nil on <New (wallet service)>")
}
2024-02-05 11:13:36 +00:00
if deps.MailClient == nil {
log.Panicln("MailClient is nil on <New (wallet service)>")
}
2023-06-22 09:36:43 +00:00
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (wallet service)>")
}
return &Service{
2024-02-05 08:23:35 +00:00
logger: deps.Logger,
repository: deps.Repository,
currencyClient: deps.CurrencyClient,
verificationClient: deps.VerificationClient,
authClient: deps.AuthClient,
2024-02-05 11:13:36 +00:00
mailClient: deps.MailClient,
2024-02-05 08:23:35 +00:00
historyService: deps.HistoryService,
2023-06-22 09:36:43 +00:00
}
}
func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *models.ReplenishAccountWallet) (*models.Account, errors.Error) {
if validate.IsStringEmpty(request.Account.Wallet.Currency) {
2023-09-14 10:07:28 +00:00
request.Account.Wallet.Currency = models.InternalCurrencyKey
2023-06-22 09:36:43 +00:00
}
cash := request.Cash
if request.Currency != request.Account.Wallet.Currency {
translatedCash, translateErr := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Cash,
From: request.Currency,
To: request.Account.Wallet.Currency,
})
if translateErr != nil {
2023-07-07 01:57:06 +00:00
receiver.logger.Error("failed to translate cash on <ReplenishAccountWallet> of <WalletService>", zap.Error(translateErr))
2023-06-22 09:36:43 +00:00
return nil, translateErr
}
cash = translatedCash
}
if request.Currency == models.InternalCurrencyKey {
updatedAccount, changeErr := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash + cash,
Money: request.Account.Wallet.Money + request.Cash,
PurchasesAmount: request.Account.Wallet.PurchasesAmount + request.Cash,
Currency: request.Account.Wallet.Currency,
LastPaymentID: request.PaymentID,
})
if changeErr != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(changeErr),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money+request.Cash),
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
)
return nil, changeErr
}
2023-09-14 10:07:28 +00:00
go func() {
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyReplenish,
UserID: request.Account.UserID,
Comment: "Успешное пополнение средств (Без конвертации валюты)",
RawDetails: fmt.Sprintf("%d%s", cash, models.InternalCurrencyKey),
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <ReplenishAccountWallet> of <WalletService>", zap.Error(historyErr))
}
}()
2023-06-22 09:36:43 +00:00
return updatedAccount, nil
}
money, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Cash,
From: request.Currency,
To: models.InternalCurrencyKey,
})
if err != nil {
2023-07-07 01:57:06 +00:00
receiver.logger.Error("failed to translate money on <ReplenishAccountWallet> of <WalletService>", zap.Error(err))
2023-06-22 09:36:43 +00:00
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash + cash,
Money: request.Account.Wallet.Money + money,
PurchasesAmount: request.Account.Wallet.PurchasesAmount + money,
Spent: request.Account.Wallet.Spent,
Currency: request.Account.Wallet.Currency,
LastPaymentID: request.PaymentID,
})
if err != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
zap.String("Currency", request.Account.Wallet.Currency),
2023-09-14 10:07:28 +00:00
zap.Int64("Money", request.Account.Wallet.Money+money),
2023-06-22 09:36:43 +00:00
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
zap.Bool("Is currensy equal internal", request.Currency == models.InternalCurrencyKey),
)
return nil, err
}
2023-09-14 10:07:28 +00:00
go func() {
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyReplenish,
UserID: request.Account.UserID,
Comment: "Успешное пополнение средств (C конвертацией валюты)",
RawDetails: fmt.Sprintf("%d%s", cash, request.Currency),
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <ReplenishAccountWallet> of <WalletService>", zap.Error(historyErr))
}
}()
2023-06-22 09:36:43 +00:00
return updatedAccount, nil
}
func (receiver *Service) WithdrawAccountWalletMoney(ctx context.Context, request *models.WithdrawAccountWallet) (*models.Account, errors.Error) {
if validate.IsStringEmpty(request.Account.Wallet.Currency) {
2023-09-14 10:07:28 +00:00
request.Account.Wallet.Currency = models.InternalCurrencyKey
}
if request.Account.Wallet.Currency == models.InternalCurrencyKey {
updatedAccount, err := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash - request.Money,
Money: request.Account.Wallet.Money - request.Money,
Spent: request.Account.Wallet.Spent + request.Money,
PurchasesAmount: request.Account.Wallet.PurchasesAmount,
Currency: request.Account.Wallet.Currency,
})
if err != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money-request.Money),
zap.Int64("Cash", request.Account.Wallet.Cash+request.Money),
)
return nil, err
}
return updatedAccount, nil
2023-06-22 09:36:43 +00:00
}
cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Money,
From: models.InternalCurrencyKey,
To: request.Account.Wallet.Currency,
})
if err != nil {
2023-07-07 01:57:06 +00:00
receiver.logger.Error("failed to translate money on <WithdrawAccountWalletMoney> of <WalletService>", zap.Error(err))
2023-06-22 09:36:43 +00:00
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash - cash,
Money: request.Account.Wallet.Money - request.Money,
Spent: request.Account.Wallet.Spent + request.Money,
PurchasesAmount: request.Account.Wallet.PurchasesAmount,
Currency: request.Account.Wallet.Currency,
})
if err != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money-request.Money),
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
)
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),
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 {
2023-07-07 01:57:06 +00:00
receiver.logger.Error("failed to translate currency on <ChangeCurrency> of <WalletService>", zap.Error(err))
2023-06-22 09:36:43 +00:00
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, account.UserID, &models.Wallet{
Cash: cash,
Currency: currency,
Money: account.Wallet.Money,
})
if err != nil {
2023-07-07 01:57:06 +00:00
receiver.logger.Error("failed to update wallet on <ChangeCurrency> of <WalletService>", zap.Error(err))
2023-06-22 09:36:43 +00:00
return nil, err
}
return updatedAccount, nil
}
2024-02-04 19:30:57 +00:00
func (receiver *Service) PostWalletRspay(ctx context.Context, userID string, req swagger.PostWalletRspayJSONBody) errors.Error {
2024-02-04 19:30:57 +00:00
user, err := receiver.repository.FindByUserID(ctx, userID)
if err != nil {
return err
}
if user.Status != models.AccountStatusNko && user.Status != models.AccountStatusOrg {
return errors.New(
fmt.Errorf("not allowed for non organizations"),
errors.ErrNoAccess,
)
}
2024-02-16 17:41:40 +00:00
fmt.Println("AAAAABBBAAAa", receiver.verificationClient)
2024-02-04 20:20:52 +00:00
verification, err := receiver.verificationClient.GetVerification(ctx, userID)
if err == errors.ErrNotFound {
return errors.New(
fmt.Errorf("no verification data found"),
errors.ErrNoAccess,
)
}
if user.Status == models.AccountStatusOrg && len(verification.Files) != 3 {
return errors.New(
fmt.Errorf("not enough verification files"),
errors.ErrNoAccess,
)
} else if user.Status == models.AccountStatusNko && len(verification.Files) != 4 {
return errors.New(
fmt.Errorf("not enough verification files"),
errors.ErrNoAccess,
)
}
2024-02-05 08:23:35 +00:00
authData, err := receiver.authClient.GetUser(ctx, userID)
if err != nil {
return err
}
err = receiver.mailClient.SendMessage(authData.Login, verification, *req.Money)
2024-02-05 11:13:36 +00:00
if err != nil {
return err
}
2024-02-04 19:30:57 +00:00
return nil
}