del first api layer

This commit is contained in:
Pavel 2024-03-11 20:21:32 +03:00
parent be0eee473b
commit d4fc763816
21 changed files with 28 additions and 2119 deletions

@ -4,11 +4,6 @@ import (
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/customer"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/payment"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/account"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/cart"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/currency"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/history"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/wallet"
)
type ControllersDeps struct {
@ -17,38 +12,12 @@ type ControllersDeps struct {
}
type Controllers struct {
AccountController *account.Controller
CurrencyController *currency.Controller
CartController *cart.Controller
HistoryController *history.Controller
WalletController *wallet.Controller
PaymentController *payment.Controller
CustomerController *customer.Controller
}
func NewControllers(deps ControllersDeps) *Controllers {
return &Controllers{
AccountController: account.New(account.Deps{
Logger: deps.Logger,
Service: deps.Services.AccountService,
}),
CurrencyController: currency.New(currency.Deps{
Logger: deps.Logger,
CurrencyService: deps.Services.CurrencyService,
}),
CartController: cart.New(cart.Deps{
Logger: deps.Logger,
CartService: deps.Services.CartService,
}),
HistoryController: history.New(history.Deps{
Logger: deps.Logger,
HistoryService: deps.Services.HistoryService,
}),
WalletController: wallet.New(wallet.Deps{
Logger: deps.Logger,
WalletService: deps.Services.WalletService,
PaymentService: deps.Services.PaymentService,
}),
PaymentController: payment.New(payment.Deps{
Logger: deps.Logger,
PaymentCallbackService: deps.Services.PaymentCallbackService,

@ -53,11 +53,6 @@ func TestNewControllers(t *testing.T) {
})
assert.NotNil(t, controllers)
assert.NotNil(t, controllers.AccountController)
assert.NotNil(t, controllers.CurrencyController)
assert.NotNil(t, controllers.CartController)
assert.NotNil(t, controllers.HistoryController)
assert.NotNil(t, controllers.WalletController)
})
})
}

@ -3,13 +3,9 @@ package initialize
import (
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/account"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/broker/tariff"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/callback"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/cart"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/currency"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/payment"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/wallet"
)
@ -22,12 +18,8 @@ type ServicesDeps struct {
}
type Services struct {
AccountService *account.Service
CurrencyService *currency.Service
CartService *cart.Service
HistoryService *history.Service
WalletService *wallet.Service
PaymentService *payment.Service
PaymentCallbackService *callback.PaymentCallbackService
TariffBrokerService *tariff.Service
}
@ -58,30 +50,6 @@ func NewServices(deps ServicesDeps) *Services {
return &Services{
WalletService: walletService,
HistoryService: historyService,
AccountService: account.New(account.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.AccountRepository,
AuthClient: deps.Clients.AuthClient,
}),
CurrencyService: currency.New(currency.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.CurrencyRepository,
}),
CartService: cart.New(cart.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.AccountRepository,
HubadminClient: deps.Clients.HubadminClient,
DiscountClient: deps.Clients.DiscountClient,
WalletService: walletService,
HistoryService: historyService,
TariffBrokerService: tariffBrokerService,
}),
PaymentService: payment.New(payment.Deps{
Logger: deps.Logger,
ConfigurationGRPC: deps.ConfigurationGRPC,
PaymentClient: deps.Clients.PaymentClient,
AuthClient: deps.Clients.AuthClient,
}),
PaymentCallbackService: callback.NewPaymentCallbackService(callback.PaymentCallbackServiceDeps{
Logger: deps.Logger,
AccountRepository: deps.Repositories.AccountRepository,

@ -48,12 +48,8 @@ func TestNewServices(t *testing.T) {
})
assert.NotNil(t, services)
assert.NotNil(t, services.AccountService)
assert.NotNil(t, services.CartService)
assert.NotNil(t, services.CurrencyService)
assert.NotNil(t, services.HistoryService)
assert.NotNil(t, services.WalletService)
assert.NotNil(t, services.PaymentService)
assert.NotNil(t, services.PaymentCallbackService)
assert.NotNil(t, services.TariffBrokerService)
})

@ -63,7 +63,7 @@ func (receiver *MailClient) SendMessage(userEmail string, verification *models.V
return handleError(receiver.deps.Logger, "Error closing form writer", err)
}
fmt.Println("SEEEEEND", receiver.deps.ApiUrl)
fmt.Println("SEEEEEND", receiver.deps.ApiUrl)
req := receiver.deps.FiberClient.Post(receiver.deps.ApiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType())
if receiver.deps.ApiKey != "" {
req.Set("Authorization", receiver.deps.ApiKey)

@ -1,166 +0,0 @@
package account
import (
"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/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/account"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
)
type Deps struct {
Logger *zap.Logger
Service *account.Service
}
type Controller struct {
logger *zap.Logger
service *account.Service
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (account controller)>")
}
if deps.Service == nil {
log.Panicln("account service is nil on <New (account controller)>")
}
return &Controller{
logger: deps.Logger,
service: deps.Service,
}
}
func (receiver *Controller) GetAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <GetAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.GetAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetDirectAccount(ctx echo.Context, userID string) error {
account, err := receiver.service.GetAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetAccounts(ctx echo.Context, params swagger.PaginationAccountsParams) error {
response, err := receiver.service.GetAccountsList(
ctx.Request().Context(),
utils.DeterminePagination(params.Page, params.Limit),
)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, response)
}
func (receiver *Controller) CreateAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <CreateAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.CreateAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) RemoveAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <RemoveAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.RemoveAccount(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) RemoveDirectAccount(ctx echo.Context, userID string) error {
account, err := receiver.service.RemoveAccount(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) SetVerificationStatus(ctx echo.Context, userID string) error {
request, bindErr := echotools.Bind[models.SetAccountStatus](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind json request on <SetVerificationStatus> of <AccountController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to bind json: %w", bindErr), errors.ErrInternalError))
}
account, err := receiver.service.SetVerificationStatus(ctx.Request().Context(), userID, request.Status)
if err != nil {
receiver.logger.Error("failed set status on <SetVerificationStatus> of <AccountController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) UpdateAccountName(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <UpdateAccountName> of <AccountController>")
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to convert jwt payload to string: %s", userID), errors.ErrInvalidArgs))
}
request, bindErr := echotools.Bind[models.Name](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind json request on <UpdateAccountName> of <AccountController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to bind json: %w", bindErr), errors.ErrInternalError))
}
account, err := receiver.service.UpdateAccountName(ctx.Request().Context(), userID, request)
if err != nil {
receiver.logger.Error("failed to update account name on <UpdateAccountName> of <AccountController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}

@ -1,118 +0,0 @@
package cart
import (
"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/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/cart"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type Deps struct {
Logger *zap.Logger
CartService *cart.Service
}
type Controller struct {
logger *zap.Logger
cartService *cart.Service
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (cart controller)>")
}
if deps.CartService == nil {
log.Panicln("cart service is nil on <New (cart controller)>")
}
return &Controller{
logger: deps.Logger,
cartService: deps.CartService,
}
}
func (receiver *Controller) Remove(ctx echo.Context, params swagger.RemoveFromCartParams) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Remove> of <CartController>")
return errors.HTTP(ctx, errors.NewWithMessage("failed to convert jwt payload to string", errors.ErrInvalidArgs))
}
if validate.IsStringEmpty(params.Id) {
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to remove cart item from user <%s>: empty item id", userID),
errors.ErrInvalidArgs,
))
}
cartItems, err := receiver.cartService.Remove(ctx.Request().Context(), userID, params.Id)
if err != nil {
receiver.logger.Error("failed to remove item from cart on <Remove> of <CartController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, cartItems)
}
func (receiver *Controller) Add(ctx echo.Context, params swagger.Add2cartParams) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Add> of <CartController>")
return errors.HTTP(ctx, errors.NewWithMessage("failed to convert jwt payload to string", errors.ErrInvalidArgs))
}
token, ok := ctx.Get(models.AuthJWTDecodedAccessTokenKey).(string)
if !ok {
receiver.logger.Error("failed to convert access token payload to string on <Add> of <CartController>")
return errors.HTTP(ctx, errors.NewWithMessage("failed to convert access token payload to string", errors.ErrInvalidArgs))
}
if validate.IsStringEmpty(params.Id) {
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to add cart item to user <%s>: empty item id", userID),
errors.ErrInvalidArgs,
))
}
cartItems, err := receiver.cartService.Add(ctx.Request().Context(), &models.AddItemToCart{
UserID: userID,
TariffID: params.Id,
AccessToken: token,
})
if err != nil {
receiver.logger.Error("failed to add item to cart on <Add> of <CartController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, cartItems)
}
func (receiver *Controller) Pay(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Pay> of <CartController>")
return errors.HTTP(ctx, errors.NewWithMessage("failed to convert jwt payload to string", errors.ErrInvalidArgs))
}
token, ok := ctx.Get(models.AuthJWTDecodedAccessTokenKey).(string)
if !ok {
receiver.logger.Error("failed to convert access token payload to string on <Pay> of <CartController>")
return errors.HTTP(ctx, errors.NewWithMessage("failed to convert access token payload to string", errors.ErrInvalidArgs))
}
account, err := receiver.cartService.Pay(ctx.Request().Context(), token, userID)
if err != nil {
receiver.logger.Error("failed to pay cart on <Pay> of <CartController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}

@ -1,82 +0,0 @@
package currency
import (
"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/service/currency"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
)
type Deps struct {
Logger *zap.Logger
CurrencyService *currency.Service
}
type Controller struct {
logger *zap.Logger
currencyService *currency.Service
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (account controller)>")
}
if deps.CurrencyService == nil {
log.Panicln("currency service is nil on <New (account controller)>")
}
return &Controller{
logger: deps.Logger,
currencyService: deps.CurrencyService,
}
}
func (receiver *Controller) GetCurrencies(ctx echo.Context) error {
currencies, err := receiver.currencyService.GetCurrencies(ctx.Request().Context())
if err != nil {
receiver.logger.Error(
"failed to get currencies on <GetCurrencies> of <CurrencyController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, currencies)
}
func (receiver *Controller) PutCurrencies(ctx echo.Context) error {
currencies, bindErr := echotools.Bind[[]string](ctx)
if bindErr != nil {
receiver.logger.Error(
"failed to parse body on <PutCurrencies> of <CurrencyController>",
zap.Error(bindErr),
)
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body: %w", bindErr),
errors.ErrInvalidArgs,
))
}
currenciesCopy := *currencies
if len(currenciesCopy) < 1 {
currenciesCopy = make([]string, 0)
}
updatedCurrencies, err := receiver.currencyService.PutCurrencies(ctx.Request().Context(), currenciesCopy)
if err != nil {
receiver.logger.Error(
"failed to put currencies on <PutCurrencies> of <CurrencyController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, updatedCurrencies)
}

@ -1,135 +0,0 @@
package history
import (
"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/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
)
type Deps struct {
Logger *zap.Logger
HistoryService *history.Service
}
type Controller struct {
logger *zap.Logger
historyService *history.Service
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (history controller)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (history controller)>")
}
return &Controller{
logger: deps.Logger,
historyService: deps.HistoryService,
}
}
func (receiver *Controller) GetHistoryList(ctx echo.Context, params swagger.GetHistoryParams) error {
var userID string
if params.AccountID != nil && *params.AccountID != "" {
userID = *params.AccountID
} else {
userID, _ = ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
}
histories, err := receiver.historyService.GetHistoryList(ctx.Request().Context(), &history.GetHistories{
Type: params.Type,
UserID: userID,
Pagination: &models.Pagination{
Page: int64(*params.Page),
Limit: int64(*params.Limit),
},
})
if err != nil {
receiver.logger.Error("failed to get histories on <GetHistoryList> of <HistoryController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, histories)
}
// TODO:tests.
func (receiver *Controller) GetRecentTariffs(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <GetRecentTariffs> of <HistoryController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
tariffs, err := receiver.historyService.GetRecentTariffs(ctx.Request().Context(), userID)
if err != nil {
receiver.logger.Error("failed to get recent tariffs on <GetRecentTariffs> of <HistoryController>",
zap.String("userId", userID),
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, tariffs)
}
// TODO:tests.
func (receiver *Controller) SendReport(ctx echo.Context) error {
historyID := ctx.Param("id")
err := receiver.historyService.GetHistoryByID(ctx.Request().Context(), historyID)
if err != nil {
receiver.logger.Error("failed to send report on <SendReport> of <HistoryController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.NoContent(http.StatusOK)
}
// TODO:tests.
func (receiver *Controller) CalculateLTV(ctx echo.Context) error {
var req swagger.CalculateLTVJSONBody
if err := ctx.Bind(&req); err != nil {
receiver.logger.Error("failed to bind request", zap.Error(err))
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to bind request: %s", err),
errors.ErrInvalidArgs,
))
}
if req.From > req.To && req.To != 0 {
receiver.logger.Error("From timestamp must be less than To timestamp unless To is 0")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("From timestamp must be less than To timestamp unless To is 0"),
errors.ErrInvalidArgs,
))
}
ltv, err := receiver.historyService.CalculateCustomerLTV(ctx.Request().Context(), req.From, req.To)
if err != nil {
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
return errors.HTTP(ctx, err)
}
response := struct {
LTV int64 `json:"LTV"`
}{
LTV: ltv,
}
return ctx.JSON(http.StatusOK, response)
}

@ -1,161 +0,0 @@
package wallet
import (
"fmt"
"log"
"net/http"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"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/service/payment"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/wallet"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type Deps struct {
Logger *zap.Logger
WalletService *wallet.Service
PaymentService *payment.Service
}
type Controller struct {
logger *zap.Logger
walletService *wallet.Service
paymentService *payment.Service
}
func New(deps Deps) *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)>")
}
if deps.PaymentService == nil {
log.Panicln("payment service is nil on <New (wallet controller)>")
}
return &Controller{
logger: deps.Logger,
walletService: deps.WalletService,
paymentService: deps.PaymentService,
}
}
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 errors.HTTP(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 errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body on <ChangeCurrency> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
if validate.IsStringEmpty(request.Currency) {
return errors.HTTP(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))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetPaymentLink(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <GetPaymentLink> of <WallerController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
request, bindErr := echotools.Bind[models.GetPaymentLinkBody](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind body on <GetPaymentLink> of <WalletController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body on <GetPaymentLink> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
if validateErr := utils.ValidateGetPaymentLinkBody(request); validateErr != nil {
receiver.logger.Error("failed to validate body on <GetPaymentLink> of <WalletController>", zap.Error(validateErr))
return errors.HTTP(ctx, validateErr)
}
link, err := receiver.paymentService.GetPaymentLink(ctx.Request().Context(), &models.GetPaymentLinkRequest{
Body: request,
UserID: userID,
ClientIP: ctx.RealIP(),
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLink> of <WalletController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, &models.GetPaymentLinkResponse{Link: link})
}
func (receiver *Controller) PostWalletRspay(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <PostWalletRspay> of <WallerController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
var req swagger.PostWalletRspayJSONBody
if err := ctx.Bind(&req); err != nil {
receiver.logger.Error("failed to bind request", zap.Error(err))
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to bind request: %s", err),
errors.ErrInvalidArgs,
))
}
token := ctx.Request().Header.Get("Authorization")
fmt.Println("HEADERS", ctx.Request().Header)
if err := receiver.walletService.PostWalletRspay(ctx.Request().Context(), token, userID, req); err != nil {
if err == errors.ErrNoAccess {
return errors.HTTP(ctx, err)
}
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to process rspay: %w", err),
errors.ErrInternalError,
))
}
return ctx.NoContent(http.StatusOK)
}

@ -174,35 +174,6 @@ func (receiver *AccountRepository) Remove(ctx context.Context, id string) (*mode
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.IsDeleted: 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.IsDeleted: false})
if err != nil {

@ -415,13 +415,13 @@ func (api *API2) PayCart(ctx echo.Context) error {
}
if _, err := api.history.Insert(ctx.Request().Context(), &models.History{
Key: models.CustomerHistoryKeyPayCart,
UserID: account.UserID,
Comment: "Успешная оплата корзины",
Key: models.CustomerHistoryKeyPayCart,
UserID: account.UserID,
Comment: "Успешная оплата корзины",
RawDetails: models.RawDetails{
Tariffs: tariffs,
Price: int64(discountResponse.Price),
},
Tariffs: tariffs,
Price: int64(discountResponse.Price),
},
}); err != nil {
return api.errorOld(ctx, err)
}
@ -522,7 +522,7 @@ func (api *API2) GetHistory(ctx echo.Context, params GetHistoryParams) error {
dto := &history.GetHistories{
UserID: userID,
Type: params.Type,
Type: params.Type,
Pagination: &models.Pagination{
Page: int64(*params.Page),
Limit: int64(*params.Limit),
@ -717,10 +717,10 @@ func (api *API2) SendReport(ctx echo.Context) error {
)
return api.errorOld(ctx, err)
}
token := ctx.Request().Header.Get("Authorization")
fmt.Println("HEADERS", ctx.Request().Header)
token := ctx.Request().Header.Get("Authorization")
fmt.Println("HEADERS", ctx.Request().Header)
verifuser, err := api.clients.verify.GetVerification(ctx.Request().Context(),token, tariffs.UserID)
verifuser, err := api.clients.verify.GetVerification(ctx.Request().Context(), token, tariffs.UserID)
if err != nil {
api.logger.Error("failed to get user verification on <GetHistoryById> of <HistoryService>",
zap.Error(err),
@ -799,10 +799,10 @@ func (api *API2) PostWalletRspay(ctx echo.Context) error {
if user.Status != models.AccountStatusNko && user.Status != models.AccountStatusOrg {
return api.error(ctx, http.StatusForbidden, "not allowed for non organizations")
}
token := ctx.Request().Header.Get("Authorization")
fmt.Println("HEADERS", ctx.Request().Header)
token := ctx.Request().Header.Get("Authorization")
fmt.Println("HEADERS", ctx.Request().Header)
verification, err := api.clients.verify.GetVerification(ctx.Request().Context(),token, userID)
verification, err := api.clients.verify.GetVerification(ctx.Request().Context(), token, userID)
if err == errors.ErrNotFound {
return api.error(ctx, http.StatusForbidden, "no verification data found")
}

@ -1,178 +0,0 @@
package swagger
import (
"log"
"github.com/labstack/echo/v4"
)
type accountController interface {
RemoveAccount(ctx echo.Context) error
GetAccount(ctx echo.Context) error
CreateAccount(ctx echo.Context) error
RemoveDirectAccount(ctx echo.Context, userID string) error
GetDirectAccount(ctx echo.Context, userID string) error
GetAccounts(echo.Context, PaginationAccountsParams) error
SetVerificationStatus(ctx echo.Context, userID string) error
UpdateAccountName(ctx echo.Context) error
}
type currencyController interface {
GetCurrencies(ctx echo.Context) error
PutCurrencies(ctx echo.Context) error
}
type cartController interface {
Remove(echo.Context, RemoveFromCartParams) error
Add(echo.Context, Add2cartParams) error
Pay(echo.Context) error
}
type walletController interface {
ChangeCurrency(ctx echo.Context) error
GetPaymentLink(ctx echo.Context) error
PostWalletRspay(ctx echo.Context) error
}
type historyController interface {
GetHistoryList(ctx echo.Context, params GetHistoryParams) error
GetRecentTariffs(ctx echo.Context) error
SendReport(ctx echo.Context) error
CalculateLTV(ctx echo.Context) error
}
type Deps struct {
AccountController accountController
CurrencyController currencyController
CartController cartController
WalletController walletController
HistoryController historyController
}
type API struct {
accountController accountController
currencyController currencyController
cartController cartController
walletController walletController
historyController historyController
}
func New(deps Deps) *API {
if deps.AccountController == nil {
log.Panicln("AccountController is nil on <New (API)>")
}
if deps.CurrencyController == nil {
log.Panicln("currencyController is nil on <New (API)>")
}
if deps.CartController == nil {
log.Panicln("cartController is nil on <New (API)>")
}
if deps.WalletController == nil {
log.Panicln("walletController is nil on <New (API)>")
}
if deps.HistoryController == nil {
log.Panicln("historyController is nil on <New (API)>")
}
return &API{
accountController: deps.AccountController,
currencyController: deps.CurrencyController,
cartController: deps.CartController,
walletController: deps.WalletController,
historyController: deps.HistoryController,
}
}
// Account
func (receiver *API) DeleteAccount(ctx echo.Context) error {
return receiver.accountController.RemoveAccount(ctx)
}
func (receiver *API) ChangeAccount(ctx echo.Context) error {
return receiver.accountController.UpdateAccountName(ctx)
}
func (receiver *API) SetAccountVerificationStatus(ctx echo.Context, userID string) error {
return receiver.accountController.SetVerificationStatus(ctx, userID)
}
func (receiver *API) GetAccount(ctx echo.Context) error {
return receiver.accountController.GetAccount(ctx)
}
func (receiver *API) AddAccount(ctx echo.Context) error {
return receiver.accountController.CreateAccount(ctx)
}
func (receiver *API) DeleteDirectAccount(ctx echo.Context, userID string) error {
return receiver.accountController.RemoveDirectAccount(ctx, userID)
}
func (receiver *API) GetDirectAccount(ctx echo.Context, userID string) error {
return receiver.accountController.GetDirectAccount(ctx, userID)
}
func (receiver *API) PaginationAccounts(ctx echo.Context, params PaginationAccountsParams) error {
return receiver.accountController.GetAccounts(ctx, params)
}
// Cart
func (receiver *API) RemoveFromCart(ctx echo.Context, params RemoveFromCartParams) error {
return receiver.cartController.Remove(ctx, params)
}
func (receiver *API) Add2cart(ctx echo.Context, params Add2cartParams) error {
return receiver.cartController.Add(ctx, params)
}
func (receiver *API) PayCart(ctx echo.Context) error {
return receiver.cartController.Pay(ctx)
}
// Currency
func (receiver *API) GetCurrencies(ctx echo.Context) error {
return receiver.currencyController.GetCurrencies(ctx)
}
func (receiver *API) UpdateCurrencies(ctx echo.Context) error {
return receiver.currencyController.PutCurrencies(ctx)
}
// History
func (receiver *API) GetHistory(ctx echo.Context, params GetHistoryParams) error {
return receiver.historyController.GetHistoryList(ctx, params)
}
func (receiver *API) GetRecentTariffs(ctx echo.Context) error {
return receiver.historyController.GetRecentTariffs(ctx)
}
func (receiver *API) SendReport(ctx echo.Context) error {
return receiver.historyController.SendReport(ctx)
}
func (receiver *API) CalculateLTV(ctx echo.Context) error {
return receiver.historyController.CalculateLTV(ctx)
}
// Wallet
func (receiver *API) RequestMoney(ctx echo.Context) error {
return receiver.walletController.GetPaymentLink(ctx)
}
func (receiver *API) ChangeCurrency(ctx echo.Context) error {
return receiver.walletController.ChangeCurrency(ctx)
}
func (receiver *API) PostWalletRspay(ctx echo.Context) error {
return receiver.walletController.PostWalletRspay(ctx)
}

@ -1,239 +0,0 @@
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)
SetStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error)
UpdateName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error)
}
const defaultCurrency = "RUB"
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.Logger == nil {
log.Panicln("logger is nil on <New (account service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (account service)>")
}
if deps.AuthClient == nil {
log.Panicln("auth client is nil on <New (account service)>")
}
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 <GetAccountByUserID> of <AccountService>",
zap.Error(err),
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 <GetAccountsList> of <AccountService>: %w", errors.ErrInternalError),
errors.ErrInternalError,
)
}
count, err := receiver.repository.CountAll(ctx)
if err != nil {
receiver.logger.Error("failed to count accounts on <GetAccountsList> of <AccountService>",
zap.Error(err),
)
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 <GetAccountsList> of <AccountService>",
zap.Error(err),
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 <CreateAccount> of <AccountService>",
zap.Error(err),
)
return nil, err
}
if findedAccount != nil {
return nil, errors.New(
fmt.Errorf("failed to create account with <%s> on <CreateAccount> of <AccountService>: %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 <CreateAccount> of <AccountService>",
zap.Error(err),
zap.Any("account", account),
)
return nil, err
}
return createdAccount, nil
}
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 <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
)
return nil, err
}
if account != nil {
return nil, errors.New(
fmt.Errorf("failed to create account with <%s> on <CreateAccountByUserID> of <AccountService>: %w",
userID,
errors.ErrConflict,
),
errors.ErrConflict,
)
}
user, err := receiver.authClient.GetUser(ctx, userID)
if err != nil {
receiver.logger.Error("failed to get user on <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
createdAccount, err := receiver.repository.Insert(ctx, &models.Account{UserID: user.ID, Wallet: models.Wallet{Currency: defaultCurrency}})
if err != nil {
receiver.logger.Error("failed to create account on <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
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 <RemoveAccount> of <AccountService>",
zap.Error(err),
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 <DeleteAccount> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
return account, nil
}
func (receiver *Service) SetVerificationStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error) {
account, err := receiver.repository.SetStatus(ctx, userID, status)
if err != nil {
receiver.logger.Error("failed to set status on <SetVerificationStatus> of <AccountService>", zap.Error(err))
return nil, err
}
return account, nil
}
func (receiver *Service) UpdateAccountName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error) {
account, err := receiver.repository.UpdateName(ctx, userID, name)
if err != nil {
receiver.logger.Error("failed to update account name on <UpdateAccountName> of <AccountService>", zap.Error(err))
return nil, err
}
return account, nil
}

@ -1,238 +0,0 @@
package cart
import (
"context"
"fmt"
"log"
"time"
"go.uber.org/zap"
"google.golang.org/protobuf/types/known/timestamppb"
"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/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer"
)
type accountRepository interface {
FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error)
AddItemToCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
RemoveItemFromCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
ClearCart(ctx context.Context, userID string) (*models.Account, errors.Error)
}
type hubadminClient interface {
GetTariff(ctx context.Context, accessToken, tariffID string) (*models.Tariff, errors.Error)
GetTariffs(ctx context.Context, accessToken string, tarriffIDs []string) ([]models.Tariff, errors.Error)
}
type discountClient interface {
Apply(context.Context, *discount.ApplyDiscountRequest) (*discount.ApplyDiscountResponse, errors.Error)
}
type walletService interface {
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
WithdrawAccountWalletMoney(context.Context, *models.WithdrawAccountWallet) (*models.Account, errors.Error)
}
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type tariffBrokerService interface {
SendMany(ctx context.Context, userID string, tariffs []models.Tariff) []errors.Error
}
type Deps struct {
Logger *zap.Logger
Repository accountRepository
HubadminClient hubadminClient
DiscountClient discountClient
WalletService walletService
HistoryService historyService
TariffBrokerService tariffBrokerService
}
type Service struct {
logger *zap.Logger
repository accountRepository
hubadminClient hubadminClient
discountClient discountClient
walletService walletService
historyService historyService
tariffBrokerService tariffBrokerService
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (cart service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (cart service)>")
}
if deps.HubadminClient == nil {
log.Panicln("HubadminClient is nil on <New (cart service)>")
}
if deps.DiscountClient == nil {
log.Panicln("DiscountClient is nil on <New (cart service)>")
}
if deps.WalletService == nil {
log.Panicln("WalletService is nil on <New (cart service)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (cart service)>")
}
if deps.TariffBrokerService == nil {
log.Panicln("TariffBrokerService is nil on <New (cart service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
hubadminClient: deps.HubadminClient,
discountClient: deps.DiscountClient,
walletService: deps.WalletService,
historyService: deps.HistoryService,
tariffBrokerService: deps.TariffBrokerService,
}
}
func (receiver *Service) Remove(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
account, err := receiver.repository.RemoveItemFromCart(ctx, userID, itemID)
if err != nil {
receiver.logger.Error("failed to remove item from cart on <Remove> of <CartService>", zap.Error(err))
return nil, err
}
return account, nil
}
func (receiver *Service) Add(ctx context.Context, request *models.AddItemToCart) (*models.Account, errors.Error) {
tariff, err := receiver.hubadminClient.GetTariff(ctx, request.AccessToken, request.TariffID)
if err != nil {
receiver.logger.Error("failed to get tariff on <Add> of <CartService>",
zap.Error(err),
zap.String("tariffID", request.TariffID),
zap.String("accessToken", request.AccessToken),
)
return nil, err
}
if tariff == nil {
return nil, errors.New(
fmt.Errorf("failed to get tariff <%s> on <Add> of <CartService>: tariff not found", request.TariffID),
errors.ErrNotFound,
)
}
account, err := receiver.repository.AddItemToCart(ctx, request.UserID, request.TariffID)
if err != nil {
receiver.logger.Error("failed to add item to cart on <Add> of <CartService>", zap.Error(err))
return nil, err
}
return account, nil
}
func (receiver *Service) Pay(ctx context.Context, accessToken string, userID string) (*models.Account, errors.Error) {
account, err := receiver.repository.FindByUserID(ctx, userID)
if err != nil {
receiver.logger.Error("failed to find account on <Pay> of <CartService>", zap.String("userID", userID), zap.Error(err))
return nil, err
}
receiver.logger.Info("account for pay", zap.Any("acc", account))
tariffs, err := receiver.hubadminClient.GetTariffs(ctx, accessToken, account.Cart)
if err != nil {
receiver.logger.Error("failed to get tarrifs on <Pay> of <CartService>", zap.Strings("cart", account.Cart), zap.Error(err))
return nil, err
}
receiver.logger.Info("tariffs for pay", zap.Any("acc", tariffs))
tariffsAmount := utils.CalculateCartPurchasesAmount(tariffs)
discountResponse, err := receiver.discountClient.Apply(ctx, &discount.ApplyDiscountRequest{
UserInformation: &discount.UserInformation{
ID: account.UserID,
Type: string(account.Status),
PurchasesAmount: uint64(account.Wallet.Spent),
CartPurchasesAmount: tariffsAmount,
},
Products: transfer.TariffsToProductInformations(tariffs),
Date: timestamppb.New(time.Now()),
})
if err != nil {
receiver.logger.Error("failed to discount on <Pay> of <CartService>", zap.Error(err))
return nil, err
}
receiver.logger.Info("discountResponse for pay", zap.Any("acc", discount.ApplyDiscountRequest{
UserInformation: &discount.UserInformation{
ID: account.UserID,
Type: string(account.Status),
PurchasesAmount: uint64(account.Wallet.Spent),
CartPurchasesAmount: tariffsAmount,
},
Products: transfer.TariffsToProductInformations(tariffs),
Date: timestamppb.New(time.Now()),
}))
if account.Wallet.Money < int64(discountResponse.Price) {
receiver.logger.Error("insufficient funds on <Pay> of <CartService>")
return nil, errors.New(fmt.Errorf("insufficient funds: %d", int64(discountResponse.Price)-account.Wallet.Money), errors.ErrInsufficientFunds)
}
updatedAccount, err := receiver.walletService.WithdrawAccountWalletMoney(ctx, &models.WithdrawAccountWallet{
Money: int64(discountResponse.Price),
Account: account,
})
if err != nil {
receiver.logger.Error("failed to withdraw money on <Pay> of <CartService>", zap.Error(err))
return nil, err
}
go func(tariffs []models.Tariff) {
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyPayCart,
UserID: account.UserID,
Comment: "Успешная оплата корзины",
RawDetails: models.RawDetails{
Tariffs: tariffs,
Price: int64(discountResponse.Price),
},
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <Pay> of <CartService>", zap.Error(historyErr))
}
}(tariffs)
// TODO: обработать ошибки при отправке сообщений
receiver.logger.Error("send to redpanda", zap.String("userID", account.UserID), zap.Any("bought tariffs", tariffs))
if sendErrors := receiver.tariffBrokerService.SendMany(ctx, account.UserID, tariffs); len(sendErrors) > 0 {
for _, err := range sendErrors {
receiver.logger.Error("failed to send tariffs to broker on <Pay> of <CartService>", zap.Error(err))
}
return nil, errors.NewWithMessage("failed to send tariffs to broker", errors.ErrInternalError)
}
if _, err := receiver.repository.ClearCart(ctx, account.UserID); err != nil {
receiver.logger.Error("failed to clear cart on <Pay> of <CartService>", zap.Error(err))
return nil, err
}
updatedAccount.Cart = []string{}
return updatedAccount, nil
}

@ -1,93 +0,0 @@
package currency
import (
"context"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type currencyRepository interface {
FindCurrenciesList(ctx context.Context, name string) (*models.CurrencyList, errors.Error)
ReplaceCurrencies(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error)
Insert(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository currencyRepository
}
type Service struct {
logger *zap.Logger
repository currencyRepository
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (currency service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (currency service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
}
}
func (receiver *Service) GetCurrencies(ctx context.Context) ([]string, errors.Error) {
currencyList, err := receiver.repository.FindCurrenciesList(ctx, models.DefaultCurrencyListName)
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to get currencies on <GetCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
if err != nil && err.Type() == errors.ErrNotFound {
return []string{}, nil
}
return currencyList.Currencies, nil
}
func (receiver *Service) PutCurrencies(ctx context.Context, currencies []string) ([]string, errors.Error) {
currencyList, err := receiver.repository.ReplaceCurrencies(ctx, &models.CurrencyList{
Name: models.DefaultCurrencyListName,
Currencies: currencies,
})
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to put currencies on <PutCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
if err != nil && err.Type() == errors.ErrNotFound {
newCurrencyList, err := receiver.repository.Insert(ctx, &models.CurrencyList{
Name: models.DefaultCurrencyListName,
Currencies: currencies,
})
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to insert new currency list on <PutCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
return newCurrencyList.Currencies, nil
}
return currencyList.Currencies, nil
}

@ -2,14 +2,9 @@ package history
import (
"context"
"fmt"
"log"
"math"
"os"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.uber.org/zap"
"log"
"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"
@ -89,44 +84,6 @@ func New(deps Deps) *Service {
}
}
func (receiver *Service) GetHistoryList(ctx context.Context, dto *GetHistories) (*models.PaginationResponse[models.History], errors.Error) {
if dto == nil {
return nil, errors.New(
fmt.Errorf("pagination is nil on <GetHistoryList> of <HistoryService>: %w", errors.ErrInternalError),
errors.ErrInternalError,
)
}
count, err := receiver.repository.CountAll(ctx, dto)
if err != nil {
receiver.logger.Error("failed to count histories on <GetHistoryList> of <HistoryService>",
zap.Error(err),
)
return nil, err
}
if count == 0 {
return &models.PaginationResponse[models.History]{TotalPages: 0, Records: []models.History{}}, nil
}
totalPages := int64(math.Ceil(float64(count) / float64(dto.Pagination.Limit)))
histories, err := receiver.repository.FindMany(ctx, dto)
if err != nil {
receiver.logger.Error("failed to get historiy list on <GetHistoryList> of <HistoryService>",
zap.Error(err),
)
return nil, err
}
return &models.PaginationResponse[models.History]{
TotalPages: totalPages,
Records: histories,
}, nil
}
func (receiver *Service) CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error) {
createdHistory, err := receiver.repository.Insert(ctx, history)
if err != nil {
@ -136,138 +93,3 @@ func (receiver *Service) CreateHistory(ctx context.Context, history *models.Hist
return createdHistory, nil
}
// TODO:tests.
func (receiver *Service) GetRecentTariffs(ctx context.Context, userID string) ([]models.TariffID, errors.Error) {
if userID == "" {
receiver.logger.Error("user id is missing in <GetRecentTariffs> of <HistoryService>")
return nil, errors.New(
fmt.Errorf("user id is missing: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
)
}
tariffs, err := receiver.repository.GetRecentTariffs(ctx, userID)
if err != nil {
receiver.logger.Error(
"failed to get recent tariffs in <GetRecentTariffs> of <HistoryService>",
zap.String("userId", userID),
zap.Error(err),
)
return nil, err
}
return tariffs, nil
}
func (receiver *Service) GetHistoryByID(ctx context.Context, historyID string) errors.Error {
if historyID == "" {
receiver.logger.Error("history id is missing in <GetHistoryById> of <HistoryService>")
return errors.New(
fmt.Errorf("history id is missing: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
)
}
tariffs, err := receiver.repository.GetHistoryByID(ctx, historyID)
if err != nil {
receiver.logger.Error(
"failed to get history by id in <GetHistoryById> of <HistoryService>",
zap.String("historyID", historyID),
zap.Error(err),
)
return err
}
if tariffs.Key != models.CustomerHistoryKeyPayCart {
receiver.logger.Error(
"invalid history record key",
zap.String("historyID", historyID),
zap.Error(err),
)
return err
}
historyMap, err := receiver.repository.GetDocNumber(ctx, tariffs.UserID)
if err != nil {
receiver.logger.Error(
"failed to get history of sorting by date created in <GetDocNumber> of <HistoryService>",
zap.String("historyID", historyID),
zap.Error(err),
)
return err
}
verifuser, err := receiver.VerificationClient.GetVerification(ctx, tariffs.UserID)
if err != nil {
receiver.logger.Error("failed to get user verification on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
if !verifuser.Accepted {
receiver.logger.Error(
"verification not accepted",
zap.String("userID", tariffs.UserID),
zap.Error(err),
)
return err
}
authuser, err := receiver.AuthClient.GetUser(ctx, tariffs.UserID)
if err != nil {
receiver.logger.Error("failed to get user on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
fileContents, readerr := os.ReadFile("./report.docx")
if readerr != nil {
return errors.New(
fmt.Errorf("failed to read file: %w", errors.ErrInternalError),
errors.ErrInternalError,
)
}
for _, tariff := range tariffs.RawDetails.Tariffs {
totalAmount := uint64(0)
for _, privilege := range tariff.Privileges {
totalAmount += privilege.Amount
}
data := models.RespGeneratorService{
DocNumber: historyMap[historyID] + 1,
Date: time.Now().Format("2006-01-02"),
OrgTaxNum: verifuser.TaxNumber,
OrgName: models.Name{Orgname: "Orgname"},
Name: tariff.Name,
Amount: totalAmount,
Price: tariffs.RawDetails.Price,
Sum: tariffs.RawDetails.Price,
}
err = receiver.TemlategenClient.SendData(ctx, data, fileContents, authuser.Email)
if err != nil {
receiver.logger.Error("failed to send report to user on <GetHistoryById> of <HistoryService>",
zap.Error(err),
zap.String("userID", tariffs.UserID),
)
return err
}
}
return nil
}
func (receiver *Service) CalculateCustomerLTV(ctx context.Context, from, to int64) (int64, errors.Error) {
ltv, err := receiver.repository.CalculateCustomerLTV(ctx, from, to)
if err != nil {
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
return 0, err
}
return ltv, nil
}

@ -1,261 +0,0 @@
package payment
import (
"context"
"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/internal/proto/treasurer"
)
type paymentClient interface {
GetPaymentLinkBankCard(ctx context.Context, request *treasurer.GetBankCardPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkYooMoney(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
GetPaymentLinkQIWI(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkSberPay(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkAlfaClick(ctx context.Context, request *treasurer.GetLoginPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkTinkoff(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
GetPaymentLinkSberbankB2B(ctx context.Context, request *treasurer.GetB2BPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkMobile(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkCash(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkInstallments(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
}
type authClient interface {
GetUser(ctx context.Context, userID string) (*models.User, errors.Error)
}
type Deps struct {
Logger *zap.Logger
ConfigurationGRPC *models.ConfigurationGRPC
PaymentClient paymentClient
AuthClient authClient
}
type Service struct {
logger *zap.Logger
configurationGRPC *models.ConfigurationGRPC
paymentClient paymentClient
authClient authClient
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (payment service)>")
}
if deps.ConfigurationGRPC == nil {
log.Panicln("ConfigurationGRPC is nil on <New (payment service)>")
}
if deps.PaymentClient == nil {
log.Panicln("PaymentClient is nil on <New (payment service)>")
}
if deps.AuthClient == nil {
log.Panicln("AuthClient is nil on <New (payment service)>")
}
return &Service{
logger: deps.Logger,
paymentClient: deps.PaymentClient,
authClient: deps.AuthClient,
configurationGRPC: deps.ConfigurationGRPC,
}
}
func (receiver *Service) GetPaymentLink(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
if _, userErr := receiver.authClient.GetUser(ctx, request.UserID); userErr != nil {
receiver.logger.Error("failed to get user on <GetPaymentLink> on <PaymentService>",
zap.Error(userErr),
zap.String("userID", request.UserID),
)
return "", userErr
}
switch request.Body.Type {
case models.PaymentTypeBankCard:
return receiver.GetPaymentLinkBankCard(ctx, request)
case models.PaymentTypeYoomoney:
return receiver.GetPaymentLinkYooMoney(ctx, request)
case models.PaymentTypeQiwi:
return receiver.GetPaymentLinkQIWI(ctx, request)
case models.PaymentTypeSberPay:
return receiver.GetPaymentLinkSberPay(ctx, request)
case models.PaymentTypeAlfabank:
return receiver.GetPaymentLinkAlfaClick(ctx, request)
case models.PaymentTypeTinkoff:
return receiver.GetPaymentLinkTinkoff(ctx, request)
case models.PaymentTypeMobile:
return receiver.GetPaymentLinkMobile(ctx, request)
case models.PaymentTypeCash:
return receiver.GetPaymentLinkCash(ctx, request)
}
return "", errors.NewWithMessage("invalid payment method type", errors.ErrInvalidArgs)
}
func (receiver *Service) GetPaymentLinkBankCard(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkBankCard(ctx, &treasurer.GetBankCardPaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
BankCard: &treasurer.BankCardInformation{
Number: request.Body.BankCard.Number,
ExpiryYear: request.Body.BankCard.ExpiryYear,
ExpiryMonth: request.Body.BankCard.ExpiryMonth,
},
})
if err != nil {
receiver.logger.Error("failed to get bankcard payment link on <GetPaymentLinkBankCard> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkYooMoney(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkYooMoney(ctx, &treasurer.GetPaymentLinkBody{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
})
if err != nil {
receiver.logger.Error("failed to get yoomoney payment link on <GetPaymentLinkYooMoney> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkQIWI(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkQIWI(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get qiwi payment link on <GetPaymentLinkQIWI> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkSberPay(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkSberPay(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get sberpay payment link on <GetPaymentLinkSberPay> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkAlfaClick(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkAlfaClick(ctx, &treasurer.GetLoginPaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Login: request.Body.Login,
})
if err != nil {
receiver.logger.Error("failed to get alfaclick payment link on <GetPaymentLinkAlfaClick> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkTinkoff(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkTinkoff(ctx, &treasurer.GetPaymentLinkBody{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
})
if err != nil {
receiver.logger.Error("failed to get tinkoff payment link on <GetPaymentLinkTinkoff> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkMobile(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkMobile(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get mobile payment link on <GetPaymentLinkMobile> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkCash(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkCash(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get cash payment link on <GetPaymentLinkCash> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}

@ -2,13 +2,10 @@ package wallet
import (
"context"
"fmt"
"log"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/client"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"go.uber.org/zap"
"log"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/client"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
@ -136,10 +133,10 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo
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),
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))
}
@ -180,9 +177,9 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo
go func() {
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyReplenish,
UserID: request.Account.UserID,
Comment: "Успешное пополнение средств (C конвертацией валюты)",
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))
@ -191,141 +188,3 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo
return updatedAccount, nil
}
func (receiver *Service) WithdrawAccountWalletMoney(ctx context.Context, request *models.WithdrawAccountWallet) (*models.Account, errors.Error) {
if validate.IsStringEmpty(request.Account.Wallet.Currency) {
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
}
cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Money,
From: models.InternalCurrencyKey,
To: request.Account.Wallet.Currency,
})
if err != nil {
receiver.logger.Error("failed to translate money on <WithdrawAccountWalletMoney> of <WalletService>", zap.Error(err))
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 {
receiver.logger.Error("failed to translate currency on <ChangeCurrency> of <WalletService>", zap.Error(err))
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))
return nil, err
}
return updatedAccount, nil
}
func (receiver *Service) PostWalletRspay(ctx context.Context, token, userID string, req swagger.PostWalletRspayJSONBody) errors.Error {
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,
)
}
verification, err := receiver.verificationClient.GetVerification(ctx, token, 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,
)
}
authData, err := receiver.authClient.GetUser(ctx, userID)
if err != nil {
return err
}
err = receiver.mailClient.SendMessage(authData.Login, verification, *req.Money)
if err != nil {
return err
}
return nil
}

@ -2,7 +2,7 @@ package client
import (
"context"
"fmt"
"fmt"
"github.com/go-resty/resty/v2"
)
@ -44,7 +44,7 @@ func makeRequest[T any, R any](url string, requestMethod func(url string) (*rest
Error: responseBody,
}, nil
}
fmt.Println("OOOOO", responseInstance.RawResponse)
fmt.Println("OOOOO", responseInstance.RawResponse)
responseBody, parseErr := parseResponse[T](responseInstance.Body(), responseInstance.RawResponse)
if parseErr != nil {

@ -2,15 +2,15 @@ package client
import (
"bytes"
"fmt"
"net/http"
"fmt"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/json"
)
func parseResponse[T any](body []byte, response *http.Response) (*T, error) {
isJSONResponse := response.Header.Get("Content-Type") == "application/json"
fmt.Println("1OOOO", response.Header.Get("Content-Type"), string(body))
fmt.Println("1OOOO", response.Header.Get("Content-Type"), string(body))
if !isJSONResponse {
responseBody, unmarshalErr := json.Unmarshal[T](body)