fix: sending daily result report instead of hourly
This commit is contained in:
parent
c77355ad4c
commit
144cb0a42c
|
|
@ -3,10 +3,9 @@ package messenger
|
|||
import (
|
||||
"context"
|
||||
"github.com/resend/resend-go/v2"
|
||||
|
||||
)
|
||||
|
||||
func (s *Service) SendEmail(ctx context.Context, receiverEmail, message string, subject string) error {
|
||||
func (s *Service) SendEmail(ctx context.Context, receiverEmail, message string, messageHTML string, subject string) error {
|
||||
apiKey := s.config.ResendApiKey
|
||||
client := resend.NewClient(apiKey)
|
||||
formattedSenderEmail := "FortuneBets <" + s.config.ResendSenderEmail + ">"
|
||||
|
|
@ -15,6 +14,7 @@ func (s *Service) SendEmail(ctx context.Context, receiverEmail, message string,
|
|||
To: []string{receiverEmail},
|
||||
Subject: subject,
|
||||
Text: message,
|
||||
Html: messageHTML,
|
||||
}
|
||||
|
||||
_, err := client.Emails.Send(params)
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ func (s *Service) handleNotification(notification *domain.Notification) {
|
|||
}
|
||||
|
||||
case domain.DeliveryChannelEmail:
|
||||
err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Headline, notification.Payload.Message)
|
||||
err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Message, notification.Payload.Headline)
|
||||
if err != nil {
|
||||
notification.DeliveryStatus = domain.DeliveryStatusFailed
|
||||
} else {
|
||||
|
|
@ -371,7 +371,7 @@ func (s *Service) SendNotificationEmail(ctx context.Context, recipientID int64,
|
|||
if user.Email == "" {
|
||||
return fmt.Errorf("email is invalid")
|
||||
}
|
||||
err = s.messengerSvc.SendEmail(ctx, user.Email, message, subject)
|
||||
err = s.messengerSvc.SendEmail(ctx, user.Email, message, message, subject)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("[NotificationSvc.HandleNotification] Failed to send notification SMS",
|
||||
zap.Int64("recipient_id", recipientID),
|
||||
|
|
@ -440,7 +440,7 @@ func (s *Service) retryFailedNotifications() {
|
|||
return
|
||||
}
|
||||
case domain.DeliveryChannelEmail:
|
||||
if err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Headline, notification.Payload.Message); err == nil {
|
||||
if err := s.SendNotificationEmail(ctx, notification.RecipientID, notification.Payload.Message, notification.Payload.Headline); err == nil {
|
||||
notification.DeliveryStatus = domain.DeliveryStatusSent
|
||||
if _, err := s.repo.UpdateNotificationStatus(ctx, notification.ID, string(notification.DeliveryStatus), notification.IsRead, notification.Metadata); err != nil {
|
||||
s.mongoLogger.Error("[NotificationSvc.RetryFailedNotifications] Failed to update after retry",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/league"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
|
|
@ -33,6 +34,7 @@ type Service struct {
|
|||
eventSvc event.Service
|
||||
leagueSvc league.Service
|
||||
notificationSvc *notificationservice.Service
|
||||
messengerSvc *messenger.Service
|
||||
userSvc user.Service
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +48,7 @@ func NewService(
|
|||
eventSvc event.Service,
|
||||
leagueSvc league.Service,
|
||||
notificationSvc *notificationservice.Service,
|
||||
messengerSvc *messenger.Service,
|
||||
userSvc user.Service,
|
||||
) *Service {
|
||||
return &Service{
|
||||
|
|
@ -59,6 +62,7 @@ func NewService(
|
|||
eventSvc: eventSvc,
|
||||
leagueSvc: leagueSvc,
|
||||
notificationSvc: notificationSvc,
|
||||
messengerSvc: messengerSvc,
|
||||
userSvc: userSvc,
|
||||
}
|
||||
}
|
||||
|
|
@ -491,6 +495,7 @@ func (s *Service) CheckAndSendResultNotifications(ctx context.Context, createdAf
|
|||
}
|
||||
|
||||
func buildHeadlineAndMessage(counts domain.ResultLog) (string, string) {
|
||||
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets + counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
if totalIssues == 0 {
|
||||
|
|
@ -521,6 +526,120 @@ func buildHeadlineAndMessage(counts domain.ResultLog) (string, string) {
|
|||
return headline, message
|
||||
}
|
||||
|
||||
func buildHeadlineAndMessageEmail(counts domain.ResultLog, user domain.User) (string, string, string) {
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount +
|
||||
counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalEvents := counts.StatusEndedCount + counts.StatusNotFinishedCount +
|
||||
counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets +
|
||||
counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
|
||||
greeting := fmt.Sprintf("Hi %s %s,", user.FirstName, user.LastName)
|
||||
|
||||
if totalIssues == 0 {
|
||||
headline := "✅ Daily Results Report — All Events Processed Successfully"
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Daily Results Summary:
|
||||
- %d Ended Events
|
||||
- %d Total Bets
|
||||
|
||||
All events were processed successfully, and no issues were detected.
|
||||
|
||||
Best regards,
|
||||
The System`, greeting, counts.StatusEndedCount, totalBets)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Daily Results Summary</h2>
|
||||
<ul>
|
||||
<li><strong>%d Ended Events</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p>All events were processed successfully, and no issues were detected.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting, counts.StatusEndedCount, totalBets)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
partsPlain := []string{}
|
||||
partsHTML := []string{}
|
||||
|
||||
if counts.StatusNotFinishedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Unresolved Events (%d Bets)", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Unresolved Events</strong> (%d Bets)</li>", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
}
|
||||
if counts.StatusToBeFixedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Requires Review (%d Bets)", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Requires Review</strong> (%d Bets)</li>", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
}
|
||||
if counts.StatusPostponedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Postponed Events (%d Bets)", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Postponed Events</strong> (%d Bets)</li>", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
}
|
||||
if counts.StatusRemovedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Discarded Events (%d Bets)", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Discarded Events</strong> (%d Bets)</li>", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
}
|
||||
if counts.StatusEndedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Successfully Ended Events (%d Bets)", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Successfully Ended Events</strong> (%d Bets)</li>", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
}
|
||||
|
||||
headline := "⚠️ Daily Results Report — Review Required"
|
||||
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Daily Results Summary:
|
||||
%s
|
||||
|
||||
Totals:
|
||||
- %d Events Processed
|
||||
- %d Total Bets
|
||||
|
||||
Next Steps:
|
||||
Some events require your attention. Please log into the admin dashboard to review pending issues.
|
||||
|
||||
Best regards,
|
||||
The System`,
|
||||
greeting,
|
||||
strings.Join(partsPlain, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Daily Results Summary</h2>
|
||||
<ul>
|
||||
%s
|
||||
</ul>
|
||||
<h3>Totals</h3>
|
||||
<ul>
|
||||
<li><strong>%d Events Processed</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p><strong>Next Steps:</strong><br>Some events require your attention. Please <a href="https://your-dashboard-url.example">log into the admin dashboard</a> to review pending issues.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting,
|
||||
strings.Join(partsHTML, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
|
||||
func (s *Service) SendAdminResultStatusErrorNotification(
|
||||
ctx context.Context,
|
||||
counts domain.ResultLog,
|
||||
|
|
@ -541,6 +660,8 @@ func (s *Service) SendAdminResultStatusErrorNotification(
|
|||
}
|
||||
|
||||
headline, message := buildHeadlineAndMessage(counts)
|
||||
|
||||
|
||||
notification := &domain.Notification{
|
||||
ErrorSeverity: domain.NotificationErrorSeverityHigh,
|
||||
DeliveryStatus: domain.DeliveryStatusPending,
|
||||
|
|
@ -567,9 +688,14 @@ func (s *Service) SendAdminResultStatusErrorNotification(
|
|||
)
|
||||
sendErrors = append(sendErrors, err)
|
||||
}
|
||||
notification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin email notification",
|
||||
// notification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
if user.Email == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
subject, plain, html := buildHeadlineAndMessageEmail(counts, user)
|
||||
if err := s.messengerSvc.SendEmail(ctx, user.Email, plain, html, subject); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin result report email",
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func (s *Service) SendOtp(ctx context.Context, sentTo string, otpFor domain.OtpF
|
|||
return fmt.Errorf("invalid sms provider: %s", provider)
|
||||
}
|
||||
case domain.OtpMediumEmail:
|
||||
if err := s.messengerSvc.SendEmail(ctx, sentTo, message, "FortuneBets - One Time Password"); err != nil {
|
||||
if err := s.messengerSvc.SendEmail(ctx, sentTo, message, message, "FortuneBets - One Time Password"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,15 +131,15 @@ func (s *Service) StartGame(ctx context.Context, req domain.GameStartRequest) (*
|
|||
|
||||
func (s *Service) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) {
|
||||
// 1. Check if provider is enabled in DB
|
||||
// provider, err := s.repo.GetVirtualGameProviderByID(ctx, req.ProviderID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to check provider %s: %w", req.ProviderID, err)
|
||||
// }
|
||||
provider, err := s.repo.GetVirtualGameProviderByID(ctx, req.ProviderID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to check provider %s: %w", req.ProviderID, err)
|
||||
}
|
||||
|
||||
// if !provider.Enabled {
|
||||
// // Provider exists but is disabled → return error
|
||||
// return nil, fmt.Errorf("provider %s is disabled", req.ProviderID)
|
||||
// }
|
||||
if !provider.Enabled {
|
||||
// Provider exists but is disabled → return error
|
||||
return nil, fmt.Errorf("provider %s is disabled", req.ProviderID)
|
||||
}
|
||||
|
||||
// 2. Prepare signature params
|
||||
sigParams := map[string]any{
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
},
|
||||
},
|
||||
{
|
||||
spec: "0 0 * * * *", // Every Day
|
||||
spec: "0 0 0 * * *", // Every Day
|
||||
task: func() {
|
||||
mongoLogger.Info("Began Send daily result notification cron task")
|
||||
if err := resultService.CheckAndSendResultNotifications(context.Background(), time.Now().Add(-24*time.Hour)); err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user