188 lines
6.0 KiB
Go
188 lines
6.0 KiB
Go
package transaction
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
|
)
|
|
|
|
var (
|
|
ErrBranchRequiredForRole = errors.New("branch_id is required to be passed for this role")
|
|
ErrInvalidBranchID = errors.New("invalid branch id")
|
|
ErrUnauthorizedCompanyID = errors.New("unauthorized company id")
|
|
ErrUnauthorizedBranchManager = errors.New("unauthorized branch manager")
|
|
ErrCustomerRoleNotAuthorized = errors.New("customer role not authorized")
|
|
ErrDepositCannotBeUnverified = errors.New("deposit cannot be unverified")
|
|
ErrShopBetHasExpired = errors.New("shop bet has already been expired")
|
|
)
|
|
|
|
type Service struct {
|
|
transactionStore ports.TransactionStore
|
|
branchSvc branch.Service
|
|
betSvc bet.Service
|
|
walletSvc wallet.Service
|
|
userSvc user.Service
|
|
}
|
|
|
|
func NewService(
|
|
transactionStore ports.TransactionStore,
|
|
branchSvc branch.Service,
|
|
betSvc bet.Service,
|
|
walletSvc wallet.Service,
|
|
userSvc user.Service,
|
|
) *Service {
|
|
return &Service{
|
|
transactionStore: transactionStore,
|
|
branchSvc: branchSvc,
|
|
betSvc: betSvc,
|
|
walletSvc: walletSvc,
|
|
userSvc: userSvc,
|
|
}
|
|
}
|
|
|
|
func (s *Service) CreateShopTransaction(ctx context.Context, transaction domain.CreateShopTransaction) (domain.ShopTransaction, error) {
|
|
return s.transactionStore.CreateShopTransaction(ctx, transaction)
|
|
}
|
|
func (s *Service) GetShopTransactionByID(ctx context.Context, id int64) (domain.ShopTransactionDetail, error) {
|
|
return s.transactionStore.GetShopTransactionByID(ctx, id)
|
|
}
|
|
func (s *Service) GetAllShopTransactions(ctx context.Context, filter domain.ShopTransactionFilter) ([]domain.ShopTransactionDetail, error) {
|
|
return s.transactionStore.GetAllShopTransactions(ctx, filter)
|
|
}
|
|
func (s *Service) GetShopTransactionByBranch(ctx context.Context, id int64) ([]domain.ShopTransactionDetail, error) {
|
|
return s.transactionStore.GetShopTransactionByBranch(ctx, id)
|
|
}
|
|
func (s *Service) UpdateShopTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, role domain.Role, companyID domain.ValidInt64, branchID domain.ValidInt64) error {
|
|
// TODO: Move this into a service role verification service
|
|
// Checks to make sure only the same company and branch can modify this
|
|
transaction, err := s.GetShopTransactionByID(ctx, id)
|
|
if role != domain.RoleSuperAdmin {
|
|
if !companyID.Valid || companyID.Value != transaction.CompanyID {
|
|
// s.logger.Error("Failed to parse UpdateTransactionVerified request", "error", err)
|
|
return fmt.Errorf("user cannot modify another companies data")
|
|
}
|
|
if role == domain.RoleCashier {
|
|
if !branchID.Valid || branchID.Value != transaction.BranchID {
|
|
// h.logger.Error("Failed to parse UpdateTransactionVerified request", "error", "Unauthorized")
|
|
return fmt.Errorf("user cannot modify another companies data")
|
|
}
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch transaction.Type {
|
|
case domain.TRANSACTION_BET:
|
|
if verified {
|
|
bet, err := s.GetShopBetByShopTransactionID(ctx, transaction.ID)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var firstEvent time.Time = bet.Outcomes[0].Expires
|
|
for _, outcome := range bet.Outcomes {
|
|
if outcome.Expires.Before(firstEvent) {
|
|
firstEvent = outcome.Expires
|
|
}
|
|
}
|
|
|
|
fmt.Printf("\n\n Shop bet expire %v - now %v \n\n", firstEvent, time.Now().UTC())
|
|
if firstEvent.Before(time.Now()) {
|
|
return ErrShopBetHasExpired
|
|
}
|
|
|
|
}
|
|
|
|
case domain.TRANSACTION_DEPOSIT:
|
|
if !verified {
|
|
// TODO: Figure out what to do here? Should i return the money or verify the faulty verify
|
|
return ErrDepositCannotBeUnverified
|
|
}
|
|
|
|
deposit, err := s.GetShopDepositByShopTransactionID(ctx, transaction.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
customerWallet, err := s.walletSvc.GetCustomerWallet(ctx, deposit.CustomerID)
|
|
|
|
if err != nil {
|
|
return ErrUserHasNoCustomerWallet
|
|
}
|
|
|
|
transfer, err := s.walletSvc.TransferToWallet(ctx,
|
|
deposit.BranchWalletID, customerWallet.RegularID, transaction.Amount, domain.TRANSFER_DIRECT, domain.ValidInt64{
|
|
Value: transaction.UserID,
|
|
Valid: true,
|
|
},
|
|
fmt.Sprintf("Transferred %v to customer wallet due to shop deposit", transaction.Amount),
|
|
)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.UpdateShopDepositTransferID(ctx, deposit.ID, domain.ValidInt64{
|
|
Value: transfer.ID,
|
|
Valid: true,
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return s.transactionStore.UpdateShopTransactionVerified(ctx, id, verified, approvedBy)
|
|
}
|
|
|
|
func (s *Service) GetBranchByRole(ctx context.Context, branchID *int64, role domain.Role, userID int64, userCompanyID domain.ValidInt64) (*int64, *int64, error) {
|
|
// var branchID int64
|
|
// var companyID int64
|
|
|
|
switch role {
|
|
case domain.RoleAdmin, domain.RoleBranchManager, domain.RoleSuperAdmin:
|
|
if branchID == nil {
|
|
// h.logger.Error("CashoutReq Branch ID is required for this user role")
|
|
return nil, nil, ErrBranchRequiredForRole
|
|
}
|
|
branch, err := s.branchSvc.GetBranchByID(ctx, *branchID)
|
|
if err != nil {
|
|
// h.logger.Error("CashoutReq no branches")
|
|
return nil, nil, ErrInvalidBetID
|
|
}
|
|
|
|
// Check if the user has access to the company
|
|
if role != domain.RoleSuperAdmin {
|
|
if userCompanyID.Valid && userCompanyID.Value != branch.CompanyID {
|
|
return nil, nil, ErrUnauthorizedCompanyID
|
|
}
|
|
}
|
|
|
|
if role == domain.RoleBranchManager {
|
|
if branch.BranchManagerID != userID {
|
|
return nil, nil, ErrUnauthorizedBranchManager
|
|
}
|
|
}
|
|
|
|
return &branch.ID, &branch.CompanyID, nil
|
|
case domain.RoleCashier:
|
|
branch, err := s.branchSvc.GetBranchByCashier(ctx, userID)
|
|
if err != nil {
|
|
// h.logger.Error("CashoutReq failed, branch id invalid")
|
|
return nil, nil, ErrInvalidBranchID
|
|
}
|
|
return &branch.ID, &branch.CompanyID, nil
|
|
default:
|
|
return nil, nil, ErrCustomerRoleNotAuthorized
|
|
}
|
|
}
|