2024-07-31 23:54:17 +07:00

112 lines
3.1 KiB
Go

package transaction
import (
errors2 "furtuna-be/internal/common/errors"
"furtuna-be/internal/common/logger"
"furtuna-be/internal/common/mycontext"
"furtuna-be/internal/entity"
"furtuna-be/internal/repository"
"go.uber.org/zap"
)
type TransactionService struct {
repo repository.TransactionRepository
wallet repository.WalletRepository
trx repository.TransactionManager
}
func New(repo repository.TransactionRepository,
wallet repository.WalletRepository,
trx repository.TransactionManager,
) *TransactionService {
return &TransactionService{
repo: repo,
wallet: wallet,
trx: trx,
}
}
func (s *TransactionService) GetTransactionList(ctx mycontext.Context,
req entity.TransactionSearch) ([]*entity.TransactionList, int, error) {
transactions, total, err := s.repo.GetTransactionList(ctx, req)
if err != nil {
logger.ContextLogger(ctx).Error("error when get all products", zap.Error(err))
return nil, 0, err
}
return transactions, total, nil
}
func (s *TransactionService) Approval(ctx mycontext.Context, req *entity.TransactionApproval) error {
// Start a transaction
trx, _ := s.trx.Begin(ctx)
// Retrieve the transaction by ID
transaction, err := s.repo.FindByID(ctx, req.TransactionID)
if err != nil {
logger.ContextLogger(ctx).Error("error when retrieving transaction by ID", zap.Error(err))
trx.Rollback()
return errors2.ErrorInternalServer
}
if transaction.Status != "WAITING_APPROVAL" {
return errors2.NewError(errors2.ErrorBadRequest.ErrorType(),
"invalid state, transaction already approved or rejected")
}
// Retrieve the wallet associated with the transaction's partner ID
wallet, err := s.wallet.GetForUpdate(ctx, trx, transaction.PartnerID)
if err != nil {
logger.ContextLogger(ctx).Error("error retrieving wallet by partner ID", zap.Error(err))
trx.Rollback()
return errors2.ErrorInternalServer
}
// Approve or Reject the transaction
switch req.Status {
case "APPROVE":
if wallet.AuthBalance < transaction.Amount {
trx.Rollback()
return errors2.ErrorInsufficientBalance
}
wallet.AuthBalance -= transaction.Amount
case "REJECT":
if wallet.AuthBalance < transaction.Amount {
trx.Rollback()
return errors2.ErrorInsufficientBalance
}
wallet.AuthBalance -= transaction.Amount
wallet.Balance += transaction.Amount
default:
trx.Rollback()
return errors2.ErrorBadRequest
}
// Update the wallet with the new balances
if _, err := s.wallet.Update(ctx, trx, wallet); err != nil {
logger.ContextLogger(ctx).Error("error updating wallet balance", zap.Error(err))
trx.Rollback()
return errors2.ErrorInternalServer
}
// Update the transaction status and persist changes
transaction.Status = req.Status
transaction.UpdatedBy = ctx.RequestedBy()
if _, err := s.repo.Update(ctx, trx, transaction); err != nil {
logger.ContextLogger(ctx).Error("error updating transaction status", zap.Error(err))
trx.Rollback()
return errors2.ErrorInternalServer
}
if err := trx.Commit().Error; err != nil {
logger.ContextLogger(ctx).Error("error committing transaction", zap.Error(err))
return errors2.ErrorInternalServer
}
return nil
}