package transaction import ( errors2 "enaklo-pos-be/internal/common/errors" "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/entity" "enaklo-pos-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 transaction.Status = "APPROVED" case "REJECT": if wallet.AuthBalance < transaction.Amount { trx.Rollback() return errors2.ErrorInsufficientBalance } transaction.Status = "REJECTED" 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.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 }