- Added new notification handling in the wallet service to notify admins when wallet balances are low or insufficient. - Created a new file for wallet notifications and moved relevant functions from the wallet service to this new file. - Updated the wallet service to publish wallet events including wallet type. - Refactored the client code to improve readability and maintainability. - Enhanced the bet handler to support pagination and status filtering for bets. - Updated routes and handlers for user search functionality to improve clarity and organization. - Modified cron job scheduling to comment out unused jobs for clarity. - Updated the WebSocket broadcast to include wallet type in notifications. - Adjusted the makefile to include Kafka in the docker-compose setup for local development.
235 lines
7.1 KiB
Go
235 lines
7.1 KiB
Go
package wallet
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"go.uber.org/zap"
|
|
"time"
|
|
)
|
|
|
|
func (s *Service) GetAdminNotificationRecipients(ctx context.Context, walletID int64, walletType domain.WalletType) ([]int64, error) {
|
|
var recipients []int64
|
|
|
|
switch walletType {
|
|
case domain.BranchWalletType:
|
|
branch, err := s.GetBranchByWalletID(ctx, walletID)
|
|
if err != nil {
|
|
s.mongoLogger.Error("[GetAdminNotificationRecipients] failed to GetBranchWalletByID", zap.Int64("walletID", walletID))
|
|
return nil, err
|
|
}
|
|
|
|
// Branch managers will be notified when branch wallet is empty
|
|
recipients = append(recipients, branch.BranchManagerID)
|
|
|
|
// Cashier will be notified
|
|
cashiers, err := s.userSvc.GetCashiersByBranch(ctx, branch.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, cashier := range cashiers {
|
|
recipients = append(recipients, cashier.ID)
|
|
}
|
|
|
|
// Admin will also be notified
|
|
admin, err := s.userSvc.GetAdminByCompanyID(ctx, branch.CompanyID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
recipients = append(recipients, admin.ID)
|
|
|
|
case domain.CompanyWalletType:
|
|
company, err := s.GetCompanyByWalletID(ctx, walletID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
recipients = append(recipients, company.AdminID)
|
|
default:
|
|
return nil, fmt.Errorf("Invalid wallet type")
|
|
}
|
|
|
|
users, _, err := s.userSvc.GetAllUsers(ctx, domain.UserFilter{
|
|
Role: string(domain.RoleSuperAdmin),
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, user := range users {
|
|
recipients = append(recipients, user.ID)
|
|
}
|
|
|
|
return recipients, nil
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWallet domain.Wallet) error {
|
|
// Send different messages
|
|
|
|
// Send notification to admin team
|
|
adminNotification := &domain.Notification{
|
|
ErrorSeverity: "low",
|
|
IsRead: false,
|
|
DeliveryStatus: domain.DeliveryStatusPending,
|
|
RecipientID: adminWallet.UserID,
|
|
Type: domain.NOTIFICATION_TYPE_ADMIN_ALERT,
|
|
Level: domain.NotificationLevelWarning,
|
|
Reciever: domain.NotificationRecieverSideAdmin,
|
|
DeliveryChannel: domain.DeliveryChannelInApp, // Or any preferred admin channel
|
|
Payload: domain.NotificationPayload{
|
|
Headline: "CREDIT WARNING: System Running Out of Funds",
|
|
Message: fmt.Sprintf(
|
|
"Wallet ID %d is running low. Current balance: %.2f",
|
|
adminWallet.ID,
|
|
adminWallet.Balance.Float32(),
|
|
),
|
|
},
|
|
Priority: 1, // High priority for admin alerts
|
|
Metadata: fmt.Appendf(nil, `{
|
|
"wallet_id": %d,
|
|
"balance": %d,
|
|
"notification_type": "admin_alert"
|
|
}`, adminWallet.ID, adminWallet.Balance),
|
|
}
|
|
|
|
// Get admin recipients and send to all
|
|
adminRecipients, err := s.GetAdminNotificationRecipients(ctx, adminWallet.ID, adminWallet.Type)
|
|
if err != nil {
|
|
s.mongoLogger.Error("failed to get admin recipients",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return err
|
|
}
|
|
|
|
for _, adminID := range adminRecipients {
|
|
adminNotification.RecipientID = adminID
|
|
if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
|
s.mongoLogger.Error("failed to send admin notification",
|
|
zap.Int64("admin_id", adminID),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
|
|
adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
|
|
|
|
if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
|
s.mongoLogger.Error("failed to send email admin notification",
|
|
zap.Int64("admin_id", adminID),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, adminWallet domain.Wallet, amount domain.Currency) error {
|
|
// Send notification to admin team
|
|
adminNotification := &domain.Notification{
|
|
ErrorSeverity: domain.NotificationErrorSeverityLow,
|
|
IsRead: false,
|
|
DeliveryStatus: domain.DeliveryStatusPending,
|
|
RecipientID: adminWallet.UserID,
|
|
Type: domain.NOTIFICATION_TYPE_ADMIN_ALERT,
|
|
Level: domain.NotificationLevelError,
|
|
Reciever: domain.NotificationRecieverSideAdmin,
|
|
DeliveryChannel: domain.DeliveryChannelInApp, // Or any preferred admin channel
|
|
Payload: domain.NotificationPayload{
|
|
Headline: "CREDIT Error: Admin Wallet insufficient to process customer request",
|
|
Message: fmt.Sprintf(
|
|
"Wallet ID %d. Transaction Amount %.2f. Current balance: %.2f",
|
|
adminWallet.ID,
|
|
amount.Float32(),
|
|
adminWallet.Balance.Float32(),
|
|
),
|
|
},
|
|
Priority: 1, // High priority for admin alerts
|
|
Metadata: fmt.Appendf(nil, `{
|
|
"wallet_id": %d,
|
|
"balance": %d,
|
|
"transaction amount": %.2f,
|
|
"notification_type": "admin_alert"
|
|
}`, adminWallet.ID, adminWallet.Balance, amount.Float32()),
|
|
}
|
|
|
|
// Get admin recipients and send to all
|
|
|
|
recipients, err := s.GetAdminNotificationRecipients(ctx, adminWallet.ID, adminWallet.Type)
|
|
if err != nil {
|
|
s.mongoLogger.Error("failed to get admin recipients",
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return err
|
|
}
|
|
for _, adminID := range recipients {
|
|
adminNotification.RecipientID = adminID
|
|
if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
|
s.mongoLogger.Error("failed to send admin notification",
|
|
zap.Int64("admin_id", adminID),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
}
|
|
adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
|
|
|
|
if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
|
s.mongoLogger.Error("failed to send email admin notification",
|
|
zap.Int64("admin_id", adminID),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return err
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) SendCustomerWalletInsufficientNotification(ctx context.Context, customerWallet domain.Wallet, amount domain.Currency) error {
|
|
// Send notification to admin team
|
|
customerNotification := &domain.Notification{
|
|
ErrorSeverity: domain.NotificationErrorSeverityLow,
|
|
IsRead: false,
|
|
DeliveryStatus: domain.DeliveryStatusPending,
|
|
RecipientID: customerWallet.UserID,
|
|
Type: domain.NOTIFICATION_TYPE_WALLET,
|
|
Level: domain.NotificationLevelError,
|
|
Reciever: domain.NotificationRecieverSideCustomer,
|
|
DeliveryChannel: domain.DeliveryChannelInApp, // Or any preferred admin channel
|
|
Payload: domain.NotificationPayload{
|
|
Headline: "CREDIT Error: Wallet insufficient",
|
|
Message: fmt.Sprintf(
|
|
"Wallet ID %d. Transaction Amount %.2f. Current balance: %.2f",
|
|
customerWallet.ID,
|
|
amount.Float32(),
|
|
customerWallet.Balance.Float32(),
|
|
),
|
|
},
|
|
Priority: 1, // High priority for admin alerts
|
|
Metadata: fmt.Appendf(nil, `{
|
|
"wallet_id": %d,
|
|
"balance": %d,
|
|
"transaction amount": %.2f,
|
|
"notification_type": "admin_alert"
|
|
}`, customerWallet.ID, customerWallet.Balance, amount.Float32()),
|
|
}
|
|
|
|
if err := s.notificationSvc.SendNotification(ctx, customerNotification); err != nil {
|
|
s.mongoLogger.Error("failed to create customer notification",
|
|
zap.Int64("customer_id", customerWallet.UserID),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|