virtual games transaction amount mapping to domain.Currency fix
This commit is contained in:
parent
5693526bb5
commit
2a41a2426c
|
|
@ -26,7 +26,7 @@ services:
|
|||
image: mongo:7.0.11
|
||||
restart: always
|
||||
ports:
|
||||
- "27017:27017"
|
||||
- "27020:27017"
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: secret
|
||||
|
|
|
|||
|
|
@ -72,168 +72,176 @@ func (s *Service) GetUserData(ctx context.Context, req domain.AtlasGetUserDataRe
|
|||
// 4. Build response
|
||||
res := &domain.AtlasGetUserDataResponse{
|
||||
PlayerID: req.PlayerID,
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessBet(ctx context.Context, req domain.AtlasBetRequest) (*domain.AtlasBetResponse, error) {
|
||||
// --- 1. Validate CasinoID ---
|
||||
if req.CasinoID != s.client.CasinoID {
|
||||
return nil, fmt.Errorf("invalid casino_id")
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid casino_id")
|
||||
}
|
||||
|
||||
// --- 2. Validate PlayerID ---
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid playerID %q", req.PlayerID)
|
||||
}
|
||||
|
||||
// --- 3. Fetch player wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
// if player == nil {
|
||||
// return nil, ErrPlayerNotFound
|
||||
// }
|
||||
|
||||
// 3. Check for duplicate transaction
|
||||
// exists, err := s.repo.TransactionExists(ctx, req.TransactionID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to check transaction: %w", err)
|
||||
// }
|
||||
// if exists {
|
||||
// return nil, ErrDuplicateTransaction
|
||||
// }
|
||||
// --- 4. Convert balance using Float32() ---
|
||||
realBalance := float64(wallet.RegularBalance.Float32())
|
||||
|
||||
// // 4. Get current balance
|
||||
// balance, err := s.walletSvc.GetBalance(ctx, req.PlayerID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to fetch wallet balance: %w", err)
|
||||
// }
|
||||
|
||||
// 5. Ensure sufficient balance
|
||||
if float64(wallet.RegularBalance) < req.Amount {
|
||||
// --- 5. Ensure sufficient balance ---
|
||||
if realBalance < req.Amount {
|
||||
return nil, domain.ErrInsufficientBalance
|
||||
}
|
||||
|
||||
// 6. Deduct amount from wallet (record transaction)
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)-req.Amount))
|
||||
// --- 6. Deduct amount from wallet ---
|
||||
newBalance := realBalance - req.Amount
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.ToCurrency(float32(newBalance)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to debit wallet: %w", err)
|
||||
}
|
||||
|
||||
// 7. Save transaction record to DB (optional but recommended)
|
||||
// if err := s.repo.SaveBetTransaction(ctx, req); err != nil {
|
||||
// // log warning but don’t fail response to Atlas
|
||||
// fmt.Printf("warning: failed to save bet transaction: %v\n", err)
|
||||
// }
|
||||
|
||||
// 8. Build response
|
||||
// --- 7. Build response ---
|
||||
res := &domain.AtlasBetResponse{
|
||||
PlayerID: req.PlayerID,
|
||||
Balance: float64(wallet.RegularBalance) - req.Amount,
|
||||
Balance: newBalance,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessBetWin(ctx context.Context, req domain.AtlasBetWinRequest) (*domain.AtlasBetWinResponse, error) {
|
||||
// --- 1. Validate CasinoID ---
|
||||
if req.CasinoID != s.client.CasinoID {
|
||||
return nil, fmt.Errorf("invalid casino_id")
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid casino_id")
|
||||
}
|
||||
|
||||
// --- 2. Validate PlayerID ---
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid playerID %q", req.PlayerID)
|
||||
}
|
||||
|
||||
// --- 3. Fetch player wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
|
||||
// 5. Ensure sufficient balance
|
||||
if float64(wallet.RegularBalance) < req.BetAmount {
|
||||
// --- 4. Convert balance using Float32() ---
|
||||
realBalance := float64(wallet.RegularBalance.Float32())
|
||||
|
||||
// --- 5. Ensure sufficient balance for bet ---
|
||||
if realBalance < req.BetAmount {
|
||||
return nil, domain.ErrInsufficientBalance
|
||||
}
|
||||
|
||||
// 6. Deduct amount from wallet (record transaction)
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)-req.BetAmount))
|
||||
// --- 6. Deduct bet amount ---
|
||||
debitedBalance := realBalance - req.BetAmount
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.ToCurrency(float32(debitedBalance)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to debit wallet: %w", err)
|
||||
}
|
||||
|
||||
// --- 7. Apply win amount (if any) ---
|
||||
finalBalance := debitedBalance
|
||||
if req.WinAmount > 0 {
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)+req.WinAmount))
|
||||
finalBalance = debitedBalance + req.WinAmount
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.ToCurrency(float32(finalBalance)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to credit wallet: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Build response
|
||||
// --- 8. Build response ---
|
||||
res := &domain.AtlasBetWinResponse{
|
||||
PlayerID: req.PlayerID,
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: finalBalance,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessRoundResult(ctx context.Context, req domain.RoundResultRequest) (*domain.RoundResultResponse, error) {
|
||||
// --- 1. Validate required fields ---
|
||||
if req.PlayerID == "" || req.TransactionID == "" {
|
||||
return nil, errors.New("missing player_id or transaction_id")
|
||||
return nil, fmt.Errorf("BAD_REQUEST: missing player_id or transaction_id")
|
||||
}
|
||||
|
||||
// Credit player with win amount if > 0
|
||||
// --- 2. Credit player if win amount > 0 ---
|
||||
if req.Amount > 0 {
|
||||
// This will credit player's balance
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid playerID %q", req.PlayerID)
|
||||
}
|
||||
|
||||
// --- 3. Fetch player wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)+req.Amount))
|
||||
// --- 4. Convert balance and apply win amount ---
|
||||
currentBalance := float64(wallet.RegularBalance.Float32())
|
||||
newBalance := currentBalance + req.Amount
|
||||
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.ToCurrency(float32(newBalance)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to credit wallet: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &domain.RoundResultResponse{Success: true}, nil
|
||||
// --- 5. Build response ---
|
||||
return &domain.RoundResultResponse{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessRollBack(ctx context.Context, req domain.RollbackRequest) (*domain.RollbackResponse, error) {
|
||||
// --- 1. Validate required fields ---
|
||||
if req.PlayerID == "" || req.BetTransactionID == "" {
|
||||
return nil, errors.New("missing player_id or transaction_id")
|
||||
return nil, fmt.Errorf("BAD_REQUEST: missing player_id or bet_transaction_id")
|
||||
}
|
||||
|
||||
// Credit player with win amount if > 0
|
||||
// This will credit player's balance
|
||||
// --- 2. Parse PlayerID ---
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid playerID %q", req.PlayerID)
|
||||
}
|
||||
|
||||
// --- 3. Fetch player wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
|
||||
// --- 4. Fetch original transfer ---
|
||||
transfer, err := s.transfetStore.GetTransferByReference(ctx, req.BetTransactionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch transfer for reference %s: %w", req.BetTransactionID, err)
|
||||
}
|
||||
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)+float64(transfer.Amount)))
|
||||
// --- 5. Compute new balance using Float32() conversion ---
|
||||
currentBalance := float64(wallet.RegularBalance.Float32())
|
||||
newBalance := currentBalance + float64(transfer.Amount)
|
||||
|
||||
// --- 6. Credit player wallet ---
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.ToCurrency(float32(newBalance)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to credit wallet: %w", err)
|
||||
}
|
||||
|
||||
// --- 7. Update transfer status and verification ---
|
||||
err = s.transfetStore.UpdateTransferStatus(ctx, transfer.ID, string(domain.STATUS_CANCELLED))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update transfer status: %w", err)
|
||||
|
|
@ -244,7 +252,10 @@ func (s *Service) ProcessRollBack(ctx context.Context, req domain.RollbackReques
|
|||
return nil, fmt.Errorf("failed to update transfer verification: %w", err)
|
||||
}
|
||||
|
||||
return &domain.RollbackResponse{Success: true}, nil
|
||||
// --- 8. Build response ---
|
||||
return &domain.RollbackResponse{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateFreeSpin(ctx context.Context, req domain.FreeSpinRequest) (*domain.FreeSpinResponse, error) {
|
||||
|
|
@ -266,14 +277,15 @@ func (s *Service) CreateFreeSpin(ctx context.Context, req domain.FreeSpinRequest
|
|||
}
|
||||
|
||||
func (s *Service) ProcessFreeSpinResult(ctx context.Context, req domain.FreeSpinResultRequest) (*domain.FreeSpinResultResponse, error) {
|
||||
|
||||
if req.PlayerID == "" || req.TransactionID == "" {
|
||||
return nil, errors.New("missing player_id or transaction_id")
|
||||
}
|
||||
|
||||
// Credit player with win amount if > 0
|
||||
if req.Amount > 0 {
|
||||
// This will credit player's balance
|
||||
if req.Amount <= 0 {
|
||||
// No winnings to process
|
||||
return &domain.FreeSpinResultResponse{Success: true}, nil
|
||||
}
|
||||
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
|
|
@ -281,7 +293,7 @@ func (s *Service) ProcessFreeSpinResult(ctx context.Context, req domain.FreeSpin
|
|||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
|
||||
err = s.walletSvc.UpdateBalance(ctx, wallet.RegularID, domain.Currency(float64(wallet.RegularBalance)+req.Amount))
|
||||
|
|
@ -289,20 +301,22 @@ func (s *Service) ProcessFreeSpinResult(ctx context.Context, req domain.FreeSpin
|
|||
return nil, fmt.Errorf("failed to credit wallet: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
// Optionally record the transaction in your transfer history for auditing
|
||||
// _ = s.transfetStore.CreateGamePayoutTransfer(...)
|
||||
|
||||
return &domain.FreeSpinResultResponse{Success: true}, nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessJackPot(ctx context.Context, req domain.JackpotRequest) (*domain.JackpotResponse, error) {
|
||||
|
||||
if req.PlayerID == "" || req.TransactionID == "" {
|
||||
return nil, errors.New("missing player_id or transaction_id")
|
||||
}
|
||||
|
||||
// Credit player with win amount if > 0
|
||||
if req.Amount > 0 {
|
||||
// This will credit player's balance
|
||||
if req.Amount <= 0 {
|
||||
// No jackpot winnings
|
||||
return &domain.JackpotResponse{Success: true}, nil
|
||||
}
|
||||
|
||||
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid playerID: %w", err)
|
||||
|
|
@ -310,15 +324,27 @@ func (s *Service) ProcessJackPot(ctx context.Context, req domain.JackpotRequest)
|
|||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
|
||||
return nil, fmt.Errorf("failed to fetch wallet for player %d: %w", playerIDInt, err)
|
||||
}
|
||||
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallet.RegularID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(req.Amount),
|
||||
domain.ValidInt64{},
|
||||
domain.PaymentMethod(domain.DEPOSIT),
|
||||
domain.PaymentDetails{
|
||||
ReferenceNumber: domain.ValidString{
|
||||
Value: req.TransactionID,
|
||||
Valid: true,
|
||||
},
|
||||
// Description: fmt.Sprintf("Jackpot win - Txn: %s", req.TransactionID),
|
||||
},
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to credit wallet: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &domain.JackpotResponse{Success: true}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,42 +233,53 @@ func (s *service) GetPlayerInfo(ctx context.Context, req *domain.PopOKPlayerInfo
|
|||
return &domain.PopOKPlayerInfoResponse{
|
||||
Country: "ET",
|
||||
Currency: claims.Currency,
|
||||
Balance: float64(wallet.RegularBalance), // Convert cents to currency
|
||||
Balance: float64(wallet.RegularBalance.Float32()), // Convert cents to currency
|
||||
PlayerID: fmt.Sprintf("%d", claims.UserID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessBet(ctx context.Context, req *domain.PopOKBetRequest) (*domain.PopOKBetResponse, error) {
|
||||
// Validate token and get user ID
|
||||
// Validate external token and extract user context
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
return nil, fmt.Errorf("invalid or expired token: %w", err)
|
||||
}
|
||||
|
||||
// Convert amount to cents (assuming wallet uses cents)
|
||||
// amount := int64(req.Amount)
|
||||
|
||||
// Deduct from wallet
|
||||
// Validate required fields
|
||||
if req.Amount <= 0 {
|
||||
return nil, errors.New("invalid bet amount")
|
||||
}
|
||||
if req.TransactionID == "" {
|
||||
return nil, errors.New("missing transaction_id")
|
||||
}
|
||||
|
||||
// Retrieve user's wallet
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return &domain.PopOKBetResponse{}, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallet.RegularID, domain.Currency(req.Amount),
|
||||
domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing virtual game bet", req.Amount))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("insufficient balance")
|
||||
return nil, fmt.Errorf("failed to fetch wallet for user %d: %w", claims.UserID, err)
|
||||
}
|
||||
|
||||
// Create transaction record
|
||||
// Deduct amount from wallet
|
||||
_, err = s.walletSvc.DeductFromWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(req.Amount),
|
||||
domain.ValidInt64{}, // optional linked transfer ID
|
||||
domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Virtual game bet placed (PopOK) - Txn: %s", req.TransactionID),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to deduct from wallet (insufficient balance or wallet error): %w", err)
|
||||
}
|
||||
|
||||
// Record the transaction
|
||||
tx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
CompanyID: claims.CompanyID.Value,
|
||||
Provider: string(domain.PROVIDER_POPOK),
|
||||
GameID: req.GameID,
|
||||
TransactionType: "BET",
|
||||
Amount: int64(req.Amount), // Negative for bets
|
||||
Amount: -int64(req.Amount), // Represent bet as negative in accounting
|
||||
Currency: req.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
Status: "COMPLETED",
|
||||
|
|
@ -276,14 +287,34 @@ func (s *service) ProcessBet(ctx context.Context, req *domain.PopOKBetRequest) (
|
|||
}
|
||||
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, tx); err != nil {
|
||||
s.logger.Error("Failed to create bet transaction", "error", err)
|
||||
return nil, fmt.Errorf("transaction failed")
|
||||
// Optionally rollback wallet deduction if transaction record fails
|
||||
_, addErr := s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(req.Amount),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{},
|
||||
fmt.Sprintf("Rollback refund for failed bet transaction (PopOK) - Txn: %s", req.TransactionID),
|
||||
)
|
||||
|
||||
if addErr != nil {
|
||||
return nil, fmt.Errorf("failed to credit wallet: %w", addErr)
|
||||
}
|
||||
s.logger.Error("Failed to create bet transaction", "error", err, "txn_id", req.TransactionID, "user_id", claims.UserID)
|
||||
return nil, fmt.Errorf("failed to record bet transaction: %w", err)
|
||||
}
|
||||
|
||||
// Return updated wallet balance
|
||||
updatedWallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh wallet balance: %w", err)
|
||||
}
|
||||
|
||||
return &domain.PopOKBetResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID), // Your internal transaction ID
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID), // internal reference
|
||||
Balance: float64(updatedWallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -306,15 +337,15 @@ func (s *service) ProcessWin(ctx context.Context, req *domain.PopOKWinRequest) (
|
|||
|
||||
if existingTx != nil && existingTx.TransactionType == "WIN" {
|
||||
s.logger.Warn("Duplicate win transaction", "transactionID", req.TransactionID)
|
||||
wallets, _ := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
balance := 0.0
|
||||
if len(wallets) > 0 {
|
||||
balance = float64(wallets[0].Balance)
|
||||
}
|
||||
wallet, _ := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
// balance := 0.0
|
||||
// if len(wallets) > 0 {
|
||||
// balance = float64(wallets[0].Balance)
|
||||
// }
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%d", existingTx.ID),
|
||||
Balance: balance,
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +354,7 @@ func (s *service) ProcessWin(ctx context.Context, req *domain.PopOKWinRequest) (
|
|||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read user wallets")
|
||||
return nil, fmt.Errorf("failed to read user wallets")
|
||||
}
|
||||
|
||||
// 4. Credit to wallet
|
||||
|
|
@ -359,29 +390,24 @@ func (s *service) ProcessWin(ctx context.Context, req *domain.PopOKWinRequest) (
|
|||
return nil, fmt.Errorf("transaction recording failed")
|
||||
}
|
||||
|
||||
fmt.Printf("\n\n Win balance is:%v\n\n", float64(wallet.RegularBalance))
|
||||
fmt.Printf("\n\n Win balance is:%v\n\n", float64(wallet.RegularBalance.Float32()))
|
||||
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessTournamentWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error) {
|
||||
// 1. Validate token and get user ID
|
||||
// --- 1. Validate token and get user ID ---
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid token in tournament win request", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
|
||||
// 2. Check for duplicate tournament win transaction
|
||||
// --- 2. Check for duplicate tournament win transaction (idempotency) ---
|
||||
existingTx, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to check existing tournament transaction", "error", err)
|
||||
|
|
@ -389,34 +415,48 @@ func (s *service) ProcessTournamentWin(ctx context.Context, req *domain.PopOKWin
|
|||
}
|
||||
if existingTx != nil && existingTx.TransactionType == "TOURNAMENT_WIN" {
|
||||
s.logger.Warn("Duplicate tournament win", "transactionID", req.TransactionID)
|
||||
// wallet, _ := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
// balance := 0.0
|
||||
// if len(wallets) > 0 {
|
||||
// balance = float64(wallets[0].Balance)
|
||||
// }
|
||||
wallet, _ := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", existingTx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. Convert amount to cents
|
||||
amountCents := int64(req.Amount)
|
||||
// --- 3. Fetch wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch wallet for user %d: %w", claims.UserID, err)
|
||||
}
|
||||
|
||||
// 4. Credit user wallet
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallet.RegularID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
||||
fmt.Sprintf("Added %v to wallet for winning Popok Tournament", req.Amount))
|
||||
// --- 4. Credit user wallet ---
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(req.Amount),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{
|
||||
ReferenceNumber: domain.ValidString{
|
||||
Value: req.TransactionID,
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
fmt.Sprintf("Added %v to wallet for winning PopOK Tournament", req.Amount),
|
||||
)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to credit wallet for tournament", "userID", claims.UserID, "error", err)
|
||||
return nil, fmt.Errorf("wallet credit failed")
|
||||
}
|
||||
|
||||
// 5. Log tournament win transaction
|
||||
// --- 5. Record tournament win transaction ---
|
||||
tx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
CompanyID: claims.CompanyID.Value,
|
||||
Provider: string(domain.PROVIDER_POPOK),
|
||||
GameID: req.GameID,
|
||||
TransactionType: "TOURNAMENT_WIN",
|
||||
Amount: amountCents,
|
||||
Amount: int64(req.Amount),
|
||||
Currency: req.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
Status: "COMPLETED",
|
||||
|
|
@ -428,31 +468,23 @@ func (s *service) ProcessTournamentWin(ctx context.Context, req *domain.PopOKWin
|
|||
return nil, fmt.Errorf("transaction recording failed")
|
||||
}
|
||||
|
||||
// 6. Fetch updated balance
|
||||
// wallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("Failed to get wallet balance")
|
||||
// }
|
||||
|
||||
// --- 6. Return response with updated balance ---
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessPromoWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error) {
|
||||
// --- 1. Validate token and get user ID ---
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid token in promo win request", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
|
||||
// --- 2. Check for duplicate promo win transaction (idempotency) ---
|
||||
existingTx, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to check existing promo transaction", "error", err)
|
||||
|
|
@ -460,30 +492,48 @@ func (s *service) ProcessPromoWin(ctx context.Context, req *domain.PopOKWinReque
|
|||
}
|
||||
if existingTx != nil && existingTx.TransactionType == "PROMO_WIN" {
|
||||
s.logger.Warn("Duplicate promo win", "transactionID", req.TransactionID)
|
||||
// wallets, _ := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
// balance := 0.0
|
||||
// if len(wallets) > 0 {
|
||||
// balance = float64(wallets[0].Balance)
|
||||
// }
|
||||
wallet, _ := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", existingTx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// amountCents := int64(req.Amount * 100)
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallet.RegularID, domain.Currency(req.Amount), domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Added %v to wallet for winning PopOk Promo Win", req.Amount))
|
||||
// --- 3. Fetch wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch wallet for user %d: %w", claims.UserID, err)
|
||||
}
|
||||
|
||||
// --- 4. Credit user wallet ---
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(req.Amount),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{
|
||||
ReferenceNumber: domain.ValidString{
|
||||
Value: req.TransactionID,
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
fmt.Sprintf("Added %v to wallet for winning PopOK Promo Win", req.Amount),
|
||||
)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to credit wallet for promo", "userID", claims.UserID, "error", err)
|
||||
return nil, fmt.Errorf("wallet credit failed")
|
||||
}
|
||||
|
||||
// --- 5. Record promo win transaction ---
|
||||
tx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
CompanyID: claims.CompanyID.Value,
|
||||
Provider: string(domain.PROVIDER_POPOK),
|
||||
GameID: req.GameID,
|
||||
TransactionType: "PROMO_WIN",
|
||||
Amount: int64(wallet.RegularBalance),
|
||||
Amount: int64(req.Amount),
|
||||
Currency: req.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
Status: "COMPLETED",
|
||||
|
|
@ -491,114 +541,77 @@ func (s *service) ProcessPromoWin(ctx context.Context, req *domain.PopOKWinReque
|
|||
}
|
||||
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, tx); err != nil {
|
||||
s.logger.Error("Failed to create promo win transaction", "error", err)
|
||||
s.logger.Error("Failed to record promo win transaction", "error", err)
|
||||
return nil, fmt.Errorf("transaction recording failed")
|
||||
}
|
||||
|
||||
// wallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to read wallets")
|
||||
// }
|
||||
|
||||
// --- 6. Return response with updated balance ---
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// func (s *service) GenerateNewToken(ctx context.Context, req *domain.PopOKGenerateTokenRequest) (*domain.PopOKGenerateTokenResponse, error) {
|
||||
// userID, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
// if err != nil {
|
||||
// s.logger.Error("Invalid player ID", "playerID", req.PlayerID, "error", err)
|
||||
// return nil, fmt.Errorf("invalid player ID")
|
||||
// }
|
||||
|
||||
// user, err := s.store.GetUserByID(ctx, userID)
|
||||
// if err != nil {
|
||||
// s.logger.Error("Failed to find user for token refresh", "userID", userID, "error", err)
|
||||
// return nil, fmt.Errorf("user not found")
|
||||
// }
|
||||
|
||||
// newSessionID := fmt.Sprintf("%d-%s-%d", userID, req.GameID, time.Now().UnixNano())
|
||||
|
||||
// token, err := jwtutil.CreatePopOKJwt(
|
||||
// userID,
|
||||
// user.FirstName,
|
||||
// req.Currency,
|
||||
// "en",
|
||||
// req.Mode,
|
||||
// newSessionID,
|
||||
// s.config.PopOK.SecretKey,
|
||||
// 24*time.Hour,
|
||||
// )
|
||||
// if err != nil {
|
||||
// s.logger.Error("Failed to generate new token", "userID", userID, "error", err)
|
||||
// return nil, fmt.Errorf("token generation failed")
|
||||
// }
|
||||
|
||||
// return &domain.PopOKGenerateTokenResponse{
|
||||
// NewToken: token,
|
||||
// }, nil
|
||||
// }
|
||||
|
||||
func (s *service) ProcessCancel(ctx context.Context, req *domain.PopOKCancelRequest) (*domain.PopOKCancelResponse, error) {
|
||||
// 1. Validate token and get user ID
|
||||
// --- 1. Validate token and get user ID ---
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
// if err != nil {
|
||||
// s.logger.Error("Invalid token in cancel request", "error", err)
|
||||
// return nil, fmt.Errorf("invalid token")
|
||||
// }
|
||||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read user wallets")
|
||||
s.logger.Error("Invalid token in cancel request", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
// 2. Find the original bet transaction
|
||||
// --- 2. Fetch wallet ---
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch wallet for user %d: %w", claims.UserID, err)
|
||||
}
|
||||
|
||||
// --- 3. Find the original bet transaction ---
|
||||
originalBet, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to find original bet", "transactionID", req.TransactionID, "error", err)
|
||||
return nil, fmt.Errorf("original bet not found")
|
||||
}
|
||||
|
||||
// 3. Validate the original transaction
|
||||
// --- 4. Validate original transaction ---
|
||||
if originalBet == nil || originalBet.TransactionType != "BET" {
|
||||
s.logger.Error("Invalid original transaction for cancel", "transactionID", req.TransactionID)
|
||||
return nil, fmt.Errorf("invalid original transaction")
|
||||
}
|
||||
|
||||
// 4. Check if already cancelled
|
||||
// --- 5. Check for duplicate cancellation ---
|
||||
if originalBet.Status == "CANCELLED" {
|
||||
s.logger.Warn("Transaction already cancelled", "transactionID", req.TransactionID)
|
||||
// wallets, _ := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
// balance := 0.0
|
||||
// if len(wallets) > 0 {
|
||||
// balance = float64(wallets[0].Balance)
|
||||
// }
|
||||
return &domain.PopOKCancelResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", originalBet.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. Refund the bet amount (absolute value since bet amount is negative)
|
||||
refundAmount := -originalBet.Amount
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallet.RegularID, domain.Currency(refundAmount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
||||
fmt.Sprintf("Added %v to wallet as refund for cancelling PopOk bet", refundAmount),
|
||||
// --- 6. Refund the bet amount ---
|
||||
refundAmount := -originalBet.Amount // Bet amounts are negative
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(refundAmount),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{
|
||||
ReferenceNumber: domain.ValidString{
|
||||
Value: req.TransactionID,
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
fmt.Sprintf("Refunded %v to wallet for cancelling PopOK bet", refundAmount),
|
||||
)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to refund bet", "userID", claims.UserID, "error", err)
|
||||
return nil, fmt.Errorf("refund failed")
|
||||
}
|
||||
|
||||
// userWallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
// if err != nil {
|
||||
// return &domain.PopOKCancelResponse{}, fmt.Errorf("Failed to read user wallets")
|
||||
// }
|
||||
|
||||
// 6. Mark original bet as cancelled and create cancel record
|
||||
// --- 7. Mark original bet as cancelled and create cancel record ---
|
||||
cancelTx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
TransactionType: "CANCEL",
|
||||
|
|
@ -610,6 +623,7 @@ func (s *service) ProcessCancel(ctx context.Context, req *domain.PopOKCancelRequ
|
|||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Update original transaction status
|
||||
if err := s.repo.UpdateVirtualGameTransactionStatus(ctx, originalBet.ID, "CANCELLED"); err != nil {
|
||||
s.logger.Error("Failed to update transaction status", "error", err)
|
||||
return nil, fmt.Errorf("update failed")
|
||||
|
|
@ -618,24 +632,18 @@ func (s *service) ProcessCancel(ctx context.Context, req *domain.PopOKCancelRequ
|
|||
// Create cancel transaction
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, cancelTx); err != nil {
|
||||
s.logger.Error("Failed to create cancel transaction", "error", err)
|
||||
|
||||
// Attempt to revert the status update
|
||||
// Attempt to revert original transaction status
|
||||
if revertErr := s.repo.UpdateVirtualGameTransactionStatus(ctx, originalBet.ID, originalBet.Status); revertErr != nil {
|
||||
s.logger.Error("Failed to revert transaction status", "error", revertErr)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("create failed")
|
||||
return nil, fmt.Errorf("create cancel transaction failed")
|
||||
}
|
||||
|
||||
// if err != nil {
|
||||
// s.logger.Error("Failed to process cancel transaction", "error", err)
|
||||
// return nil, fmt.Errorf("transaction processing failed")
|
||||
// }
|
||||
|
||||
// --- 8. Return response with updated balance ---
|
||||
return &domain.PopOKCancelResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", cancelTx.ID),
|
||||
Balance: float64(wallet.RegularBalance),
|
||||
Balance: float64(wallet.RegularBalance.Float32()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ func (s *Service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*d
|
|||
Amount float64 `json:"amount"`
|
||||
}{
|
||||
Currency: req.Currency,
|
||||
Amount: float64(wallet.RegularBalance),
|
||||
Amount: (float64(wallet.RegularBalance.Float32())),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -285,60 +285,23 @@ func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
|||
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
|
||||
}
|
||||
|
||||
// // --- 2. Validate session (optional, if you have sessionSvc) ---
|
||||
// sessionValid, expired, err := s.sessionSvc.ValidateSession(ctx, req.SessionID, req.PlayerID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("session validation failed")
|
||||
// }
|
||||
// if !sessionValid {
|
||||
// if expired {
|
||||
// return nil, fmt.Errorf("SESSION_EXPIRED: session %s expired", req.SessionID)
|
||||
// }
|
||||
// return nil, fmt.Errorf("SESSION_NOT_FOUND: session %s not found", req.SessionID)
|
||||
// }
|
||||
|
||||
// --- 3. Get player wallets ---
|
||||
// playerWallets, err := s.walletSvc.GetWalletsByUser(ctx, playerIDInt64)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to get real balance: %w", err)
|
||||
// }
|
||||
// if len(playerWallets) == 0 {
|
||||
// return nil, fmt.Errorf("no wallets found for player %s", req.PlayerID)
|
||||
// }
|
||||
|
||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read user wallets")
|
||||
}
|
||||
|
||||
// realWallet := playerWallets[0]
|
||||
// realBalance := float64(realWallet.Balance)
|
||||
|
||||
// var bonusBalance float64
|
||||
// if len(playerWallets) > 1 {
|
||||
// bonusBalance = float64(playerWallets[1].Balance)
|
||||
// }
|
||||
|
||||
bonusBalance := float64(wallet.StaticBalance)
|
||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||
|
||||
// --- 4. Check sufficient balance ---
|
||||
// totalBalance := float64(wallet.RegularBalance) + bonusBalance
|
||||
if float64(wallet.RegularBalance) < req.Amount.Amount {
|
||||
return nil, fmt.Errorf("INSUFFICIENT_BALANCE")
|
||||
}
|
||||
|
||||
// --- 5. Deduct funds (bonus first, then real) ---
|
||||
remaining := req.Amount.Amount
|
||||
// var usedBonus, usedReal float64
|
||||
|
||||
if remaining > float64(wallet.RegularBalance) {
|
||||
if float64(wallet.RegularBalance.Float32()) < req.Amount.Amount {
|
||||
return nil, fmt.Errorf("INSUFFICIENT_BALANCE")
|
||||
}
|
||||
|
||||
// --- 6. Persist wallet deductions ---
|
||||
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallet.RegularID,
|
||||
domain.Currency(req.Amount.Amount),
|
||||
domain.ToCurrency(float32(req.Amount.Amount)),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deduct amount %.2f for bet %s", req.Amount.Amount, req.TransactionID),
|
||||
|
|
@ -350,8 +313,8 @@ func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
|||
// --- 7. Build response ---
|
||||
res := &domain.BetResponse{
|
||||
Real: domain.BalanceDetail{
|
||||
Currency: "ETB",
|
||||
Amount: float64(wallet.RegularBalance),
|
||||
Currency: req.Amount.Currency,
|
||||
Amount: float64(wallet.RegularBalance.Float32()) - req.Amount.Amount,
|
||||
},
|
||||
WalletTransactionID: req.TransactionID,
|
||||
UsedRealAmount: req.Amount.Amount,
|
||||
|
|
@ -360,7 +323,7 @@ func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
|||
|
||||
if bonusBalance > 0 {
|
||||
res.Bonus = &domain.BalanceDetail{
|
||||
Currency: "ETB",
|
||||
Currency: req.Amount.Currency,
|
||||
Amount: bonusBalance,
|
||||
}
|
||||
}
|
||||
|
|
@ -381,27 +344,20 @@ func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
|||
return nil, fmt.Errorf("failed to read user wallets")
|
||||
}
|
||||
|
||||
// realWallet := playerWallets[0]
|
||||
realBalance := float64(wallet.RegularBalance)
|
||||
// --- 3. Convert balances safely using Float32() ---
|
||||
realBalance := float64(wallet.RegularBalance.Float32())
|
||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||
|
||||
// var bonusBalance float64
|
||||
// if len(playerWallets) > 1 {
|
||||
// bonusBalance = float64(playerWallets[1].Balance)
|
||||
// }
|
||||
bonusBalance := float64(wallet.StaticBalance)
|
||||
|
||||
// --- 3. Apply winnings (for now, everything goes to real wallet) ---
|
||||
// --- 4. Apply winnings ---
|
||||
winAmount := req.Amount.Amount
|
||||
usedReal := winAmount
|
||||
usedBonus := 0.0
|
||||
|
||||
// TODO: If you want to split between bonus/real (e.g. free spins),
|
||||
// you can extend logic here based on req.WinType / req.RewardID.
|
||||
|
||||
// Future extension: split winnings between bonus and real wallets if needed
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(winAmount),
|
||||
domain.ToCurrency(float32(winAmount)),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{},
|
||||
|
|
@ -411,24 +367,11 @@ func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
|||
return nil, fmt.Errorf("failed to credit real wallet: %w", err)
|
||||
}
|
||||
|
||||
// // --- 4. Reload balances after credit ---
|
||||
// updatedWallets, err := s.walletSvc.GetWalletsByUser(ctx, playerIDInt64)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to reload balances: %w", err)
|
||||
// }
|
||||
|
||||
// updatedReal := updatedWallets[0]
|
||||
// realBalance = float64(wallet.RegularBalance)
|
||||
|
||||
// if len(updatedWallets) > 1 {
|
||||
// bonusBalance = float64(updatedWallets[1].Balance)
|
||||
// }
|
||||
|
||||
// --- 5. Build response ---
|
||||
res := &domain.WinResponse{
|
||||
Real: domain.BalanceDetail{
|
||||
Currency: req.Amount.Currency,
|
||||
Amount: realBalance,
|
||||
Amount: realBalance + winAmount, // reflect the credited win amount
|
||||
},
|
||||
WalletTransactionID: req.TransactionID,
|
||||
UsedRealAmount: usedReal,
|
||||
|
|
@ -449,7 +392,7 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
// --- 1. Validate PlayerID ---
|
||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid PlayerID %q", req.PlayerID)
|
||||
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %q", req.PlayerID)
|
||||
}
|
||||
|
||||
// --- 2. Get player wallets ---
|
||||
|
|
@ -458,15 +401,11 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
return nil, fmt.Errorf("failed to read user wallets")
|
||||
}
|
||||
|
||||
// realWallet := playerWallets[0]
|
||||
realBalance := float64(wallet.RegularBalance)
|
||||
// --- 3. Convert balances using Float32() ---
|
||||
realBalance := float64(wallet.RegularBalance.Float32())
|
||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||
|
||||
// var bonusBalance float64
|
||||
// if len(playerWallets) > 1 {
|
||||
bonusBalance := float64(wallet.StaticBalance)
|
||||
// }
|
||||
|
||||
// --- 3. Determine refund amount based on IsAdjustment ---
|
||||
// --- 4. Determine refund amount ---
|
||||
var refundAmount float64
|
||||
if req.IsAdjustment {
|
||||
if req.AdjustmentRefund.Amount <= 0 {
|
||||
|
|
@ -474,7 +413,6 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
}
|
||||
refundAmount = req.AdjustmentRefund.Amount
|
||||
} else {
|
||||
// Regular cancel: fetch original bet amount if needed
|
||||
originalTransfer, err := s.transfetStore.GetTransferByReference(ctx, req.RefTransactionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get original bet for cancellation: %w", err)
|
||||
|
|
@ -482,14 +420,14 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
refundAmount = float64(originalTransfer.Amount)
|
||||
}
|
||||
|
||||
// --- 4. Refund to wallet ---
|
||||
// --- 5. Refund to wallet ---
|
||||
usedReal := refundAmount
|
||||
usedBonus := 0.0
|
||||
|
||||
_, err = s.walletSvc.AddToWallet(
|
||||
ctx,
|
||||
wallet.RegularID,
|
||||
domain.Currency(refundAmount),
|
||||
domain.ToCurrency(float32(refundAmount)),
|
||||
domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{
|
||||
|
|
@ -505,25 +443,12 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
return nil, fmt.Errorf("failed to refund wallet: %w", err)
|
||||
}
|
||||
|
||||
// --- 5. Reload balances after refund ---
|
||||
// updatedWallets, err := s.walletSvc.GetWalletsByUser(ctx, playerIDInt64)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to reload balances: %w", err)
|
||||
// }
|
||||
|
||||
// updatedReal := updatedWallets[0]
|
||||
// realBalance = float64(wallet.RegularBalance)
|
||||
|
||||
// if len(updatedWallets) > 1 {
|
||||
// bonusBalance = float64(updatedWallets[1].Balance)
|
||||
// }
|
||||
|
||||
// --- 6. Build response ---
|
||||
res := &domain.CancelResponse{
|
||||
WalletTransactionID: req.TransactionID,
|
||||
Real: domain.BalanceDetail{
|
||||
Currency: req.AdjustmentRefund.Currency,
|
||||
Amount: realBalance,
|
||||
Amount: realBalance + refundAmount, // reflect refunded balance
|
||||
},
|
||||
UsedRealAmount: usedReal,
|
||||
UsedBonusAmount: usedBonus,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user