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 }