Add Balance and Withdrawal
This commit is contained in:
@@ -2,20 +2,36 @@ package balance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"furtuna-be/internal/common/logger"
|
||||
"furtuna-be/internal/common/mycontext"
|
||||
"furtuna-be/internal/entity"
|
||||
"furtuna-be/internal/repository"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type BalanceService struct {
|
||||
repo repository.WalletRepository
|
||||
type Config interface {
|
||||
GetPlatformFee() int64
|
||||
}
|
||||
|
||||
func NewBalanceService(repo repository.WalletRepository) *BalanceService {
|
||||
type BalanceService struct {
|
||||
repo repository.WalletRepository
|
||||
trx repository.TransactionManager
|
||||
crypt repository.Crypto
|
||||
transaction repository.TransactionRepository
|
||||
cfg Config
|
||||
}
|
||||
|
||||
func NewBalanceService(repo repository.WalletRepository,
|
||||
trx repository.TransactionManager,
|
||||
crypt repository.Crypto, cfg Config,
|
||||
transaction repository.TransactionRepository) *BalanceService {
|
||||
return &BalanceService{
|
||||
repo: repo,
|
||||
repo: repo,
|
||||
trx: trx,
|
||||
crypt: crypt,
|
||||
cfg: cfg,
|
||||
transaction: transaction,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,3 +48,92 @@ func (s *BalanceService) GetByID(ctx context.Context, id int64) (*entity.Balance
|
||||
AuthBalance: balanceDB.AuthBalance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *BalanceService) WithdrawInquiry(ctx context.Context, req *entity.BalanceWithdrawInquiry) (*entity.BalanceWithdrawInquiryResponse, error) {
|
||||
balanceDB, err := s.repo.GetForUpdate(ctx, nil, req.PartnerID)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get branch by id", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if float64(req.Amount) > balanceDB.Balance {
|
||||
logger.ContextLogger(ctx).Error("requested amount exceeds available balance")
|
||||
return nil, errors.New("insufficient balance")
|
||||
}
|
||||
|
||||
token, err := s.crypt.GenerateJWTWithdraw(&entity.WalletWithdrawRequest{
|
||||
ID: balanceDB.ID,
|
||||
PartnerID: req.PartnerID,
|
||||
Amount: req.Amount - s.cfg.GetPlatformFee(),
|
||||
Fee: s.cfg.GetPlatformFee(),
|
||||
Total: req.Amount,
|
||||
})
|
||||
|
||||
return &entity.BalanceWithdrawInquiryResponse{
|
||||
PartnerID: req.PartnerID,
|
||||
Amount: req.Amount - s.cfg.GetPlatformFee(),
|
||||
Token: token,
|
||||
Fee: s.cfg.GetPlatformFee(),
|
||||
Total: req.Amount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *BalanceService) WithdrawExecute(ctx mycontext.Context, req *entity.WalletWithdrawRequest) (*entity.WalletWithdrawResponse, error) {
|
||||
decodedReq, err := s.crypt.ValidateJWTWithdraw(req.Token)
|
||||
if err != nil || decodedReq.PartnerID != req.PartnerID {
|
||||
logger.ContextLogger(ctx).Error("invalid withdrawal token", zap.Error(err))
|
||||
return nil, errors.New("invalid withdrawal token")
|
||||
}
|
||||
|
||||
trx, _ := s.trx.Begin(ctx)
|
||||
wallet, err := s.repo.GetForUpdate(ctx, trx, decodedReq.PartnerID)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error retrieving wallet by partner ID", zap.Error(err))
|
||||
trx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalAmount := float64(decodedReq.Total)
|
||||
if totalAmount > wallet.Balance {
|
||||
logger.ContextLogger(ctx).Error("insufficient balance for withdrawal", zap.Float64("available", wallet.Balance), zap.Float64("requested", totalAmount))
|
||||
trx.Rollback()
|
||||
return nil, errors.New("insufficient balance")
|
||||
}
|
||||
|
||||
wallet.Balance -= totalAmount
|
||||
wallet.AuthBalance += totalAmount
|
||||
|
||||
if _, err := s.repo.Update(ctx, trx, wallet); err != nil {
|
||||
logger.ContextLogger(ctx).Error("error updating wallet balance", zap.Error(err))
|
||||
trx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transaction := &entity.Transaction{
|
||||
PartnerID: wallet.PartnerID,
|
||||
TransactionType: "WITHDRAW",
|
||||
ReferenceID: "",
|
||||
Status: "WAITING_APPROVAL",
|
||||
CreatedBy: ctx.RequestedBy(),
|
||||
Amount: totalAmount,
|
||||
}
|
||||
|
||||
transaction, err = s.transaction.Create(ctx, trx, transaction)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error creating transaction record", zap.Error(err))
|
||||
trx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := trx.Commit().Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error committing transaction", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &entity.WalletWithdrawResponse{
|
||||
TransactionID: transaction.ID,
|
||||
Status: "WAITING_APPROVAL",
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user