customer/internal/service/cart/cart.go

239 lines
8.1 KiB
Go
Raw Normal View History

2023-05-19 07:09:04 +00:00
package cart
import (
"context"
2023-05-19 09:08:15 +00:00
"fmt"
2023-05-19 07:09:04 +00:00
"log"
2023-05-30 11:33:57 +00:00
"time"
2023-05-19 07:09:04 +00:00
"go.uber.org/zap"
2023-05-30 11:33:57 +00:00
"google.golang.org/protobuf/types/known/timestamppb"
2023-05-19 07:09:04 +00:00
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
2023-05-30 11:33:57 +00:00
"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"
2023-05-19 07:09:04 +00:00
)
type accountRepository interface {
2023-05-30 11:33:57 +00:00
FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error)
2023-05-19 07:09:04 +00:00
AddItemToCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
RemoveItemFromCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
2023-05-30 11:33:57 +00:00
ClearCart(ctx context.Context, userID string) (*models.Account, errors.Error)
2023-05-19 07:09:04 +00:00
}
2023-05-19 09:08:15 +00:00
type hubadminClient interface {
2023-06-29 13:31:16 +00:00
GetTariff(ctx context.Context, accessToken, tariffID string) (*models.Tariff, errors.Error)
GetTariffs(ctx context.Context, accessToken string, tarriffIDs []string) ([]models.Tariff, errors.Error)
2023-05-30 11:33:57 +00:00
}
type discountClient interface {
Apply(context.Context, *discount.ApplyDiscountRequest) (*discount.ApplyDiscountResponse, errors.Error)
}
type walletService interface {
2023-06-01 11:38:53 +00:00
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
WithdrawAccountWalletMoney(context.Context, *models.WithdrawAccountWallet) (*models.Account, errors.Error)
2023-05-19 09:08:15 +00:00
}
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
2023-07-06 18:50:46 +00:00
type tariffBrokerService interface {
SendMany(ctx context.Context, userID string, tariffs []models.Tariff) []errors.Error
}
2023-05-19 07:09:04 +00:00
type Deps struct {
2023-07-06 18:50:46 +00:00
Logger *zap.Logger
Repository accountRepository
HubadminClient hubadminClient
DiscountClient discountClient
WalletService walletService
HistoryService historyService
TariffBrokerService tariffBrokerService
2023-05-19 07:09:04 +00:00
}
type Service struct {
2023-07-06 18:50:46 +00:00
logger *zap.Logger
repository accountRepository
hubadminClient hubadminClient
discountClient discountClient
walletService walletService
historyService historyService
tariffBrokerService tariffBrokerService
2023-05-19 07:09:04 +00:00
}
2023-06-13 19:33:40 +00:00
func New(deps Deps) *Service {
2023-05-19 07:09:04 +00:00
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)>")
}
2023-05-19 09:08:15 +00:00
if deps.HubadminClient == nil {
log.Panicln("HubadminClient is nil on <New (cart service)>")
}
2023-05-30 11:33:57 +00:00
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)>")
}
2023-07-06 18:50:46 +00:00
if deps.TariffBrokerService == nil {
log.Panicln("TariffBrokerService is nil on <New (cart service)>")
}
2023-05-19 07:09:04 +00:00
return &Service{
2023-07-06 18:50:46 +00:00
logger: deps.Logger,
repository: deps.Repository,
hubadminClient: deps.HubadminClient,
discountClient: deps.DiscountClient,
walletService: deps.WalletService,
historyService: deps.HistoryService,
tariffBrokerService: deps.TariffBrokerService,
2023-05-19 07:09:04 +00:00
}
}
2023-09-09 22:44:46 +00:00
func (receiver *Service) Remove(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
2023-05-19 07:09:04 +00:00
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))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-19 07:09:04 +00:00
}
2023-09-09 22:44:46 +00:00
return account, nil
2023-05-19 07:09:04 +00:00
}
2023-09-09 22:44:46 +00:00
func (receiver *Service) Add(ctx context.Context, request *models.AddItemToCart) (*models.Account, errors.Error) {
2023-06-29 13:31:16 +00:00
tariff, err := receiver.hubadminClient.GetTariff(ctx, request.AccessToken, request.TariffID)
2023-05-19 09:08:15 +00:00
if err != nil {
2023-06-29 13:31:16 +00:00
receiver.logger.Error("failed to get tariff on <Add> of <CartService>",
zap.Error(err),
zap.String("tariffID", request.TariffID),
zap.String("accessToken", request.AccessToken),
)
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-19 09:08:15 +00:00
}
if tariff == nil {
2023-09-09 22:44:46 +00:00
return nil, errors.New(
2023-06-29 13:31:16 +00:00
fmt.Errorf("failed to get tariff <%s> on <Add> of <CartService>: tariff not found", request.TariffID),
2023-05-19 09:08:15 +00:00
errors.ErrNotFound,
)
}
2023-06-29 13:31:16 +00:00
account, err := receiver.repository.AddItemToCart(ctx, request.UserID, request.TariffID)
2023-05-19 07:09:04 +00:00
if err != nil {
receiver.logger.Error("failed to add item to cart on <Add> of <CartService>", zap.Error(err))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-19 07:09:04 +00:00
}
2023-09-09 22:44:46 +00:00
return account, nil
2023-05-19 07:09:04 +00:00
}
2023-05-30 11:33:57 +00:00
2023-09-09 22:44:46 +00:00
func (receiver *Service) Pay(ctx context.Context, accessToken string, userID string) (*models.Account, errors.Error) {
2023-05-30 11:33:57 +00:00
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))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-30 11:33:57 +00:00
}
2023-08-18 16:57:12 +00:00
2023-09-15 19:55:39 +00:00
receiver.logger.Info("account for pay", zap.Any("acc", account))
2023-06-29 13:31:16 +00:00
tariffs, err := receiver.hubadminClient.GetTariffs(ctx, accessToken, account.Cart)
2023-05-30 11:33:57 +00:00
if err != nil {
receiver.logger.Error("failed to get tarrifs on <Pay> of <CartService>", zap.Strings("cart", account.Cart), zap.Error(err))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-30 11:33:57 +00:00
}
2023-08-18 16:57:12 +00:00
2023-09-15 19:55:39 +00:00
receiver.logger.Info("tariffs for pay", zap.Any("acc", tariffs))
2023-05-30 11:33:57 +00:00
tariffsAmount := utils.CalculateCartPurchasesAmount(tariffs)
2023-09-09 22:44:46 +00:00
discountResponse, err := receiver.discountClient.Apply(ctx, &discount.ApplyDiscountRequest{
2023-05-30 11:33:57 +00:00
UserInformation: &discount.UserInformation{
ID: account.UserID,
2023-05-31 21:28:35 +00:00
Type: string(account.Status),
PurchasesAmount: uint64(account.Wallet.Spent),
2023-09-09 22:44:46 +00:00
CartPurchasesAmount: tariffsAmount,
2023-05-30 11:33:57 +00:00
},
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))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-30 11:33:57 +00:00
}
2023-08-18 18:43:22 +00:00
2023-09-16 21:01:44 +00:00
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),
2023-09-16 21:01:44 +00:00
CartPurchasesAmount: tariffsAmount,
},
Products: transfer.TariffsToProductInformations(tariffs),
Date: timestamppb.New(time.Now()),
}))
2023-09-15 19:55:39 +00:00
2023-09-09 22:44:46 +00:00
if account.Wallet.Money < int64(discountResponse.Price) {
receiver.logger.Error("insufficient funds on <Pay> of <CartService>")
2023-09-09 22:44:46 +00:00
return nil, errors.New(fmt.Errorf("insufficient funds: %d", int64(discountResponse.Price)-account.Wallet.Money), errors.ErrInsufficientFunds)
2023-05-30 11:33:57 +00:00
}
2023-09-09 22:44:46 +00:00
updatedAccount, err := receiver.walletService.WithdrawAccountWalletMoney(ctx, &models.WithdrawAccountWallet{
Money: int64(discountResponse.Price),
2023-06-13 19:20:11 +00:00
Account: account,
2023-09-09 22:44:46 +00:00
})
if err != nil {
receiver.logger.Error("failed to withdraw money on <Pay> of <CartService>", zap.Error(err))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-30 11:33:57 +00:00
}
2023-09-10 14:54:41 +00:00
go func(tariffs []models.Tariff) {
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
2023-10-16 13:16:41 +00:00
Key: models.CustomerHistoryKeyPayCart,
UserID: account.UserID,
Comment: "Успешная оплата корзины",
RawDetails: map[string]any{
"tariffs": tariffs,
"price": discountResponse.Price,
},
2023-09-10 14:54:41 +00:00
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <Pay> of <CartService>", zap.Error(historyErr))
}
}(tariffs)
2023-07-06 19:09:12 +00:00
// TODO: обработать ошибки при отправке сообщений
2023-11-15 14:17:05 +00:00
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 {
2023-07-06 18:50:46 +00:00
for _, err := range sendErrors {
receiver.logger.Error("failed to send tariffs to broker on <Pay> of <CartService>", zap.Error(err))
}
2023-09-09 22:44:46 +00:00
return nil, errors.NewWithMessage("failed to send tariffs to broker", errors.ErrInternalError)
2023-07-06 18:50:46 +00:00
}
2023-05-30 11:33:57 +00:00
if _, err := receiver.repository.ClearCart(ctx, account.UserID); err != nil {
receiver.logger.Error("failed to clear cart on <Pay> of <CartService>", zap.Error(err))
2023-09-09 22:44:46 +00:00
return nil, err
2023-05-30 11:33:57 +00:00
}
2023-09-09 22:44:46 +00:00
updatedAccount.Cart = []string{}
return updatedAccount, nil
2023-05-30 11:33:57 +00:00
}