backend-service/internal/jobs/reminder_config.go

140 lines
3.7 KiB
Go
Raw Normal View History

package jobs
import (
"time"
)
// ReminderConfig represents the configuration for reminder scheduling
type ReminderConfig struct {
// Default reminder times before the meeting (in minutes)
DefaultReminders []int `json:"default_reminders"`
// Maximum number of reminders per booking
MaxReminders int `json:"max_reminders"`
// Minimum time before meeting to send reminder (in minutes)
MinReminderTime int `json:"min_reminder_time"`
// Whether reminders are enabled globally
Enabled bool `json:"enabled"`
}
// DefaultReminderConfig returns the default reminder configuration
func DefaultReminderConfig() *ReminderConfig {
return &ReminderConfig{
DefaultReminders: []int{1440, 60, 15}, // 24 hours, 1 hour, 15 minutes before
MaxReminders: 3,
MinReminderTime: 5, // Don't send reminders less than 5 minutes before
Enabled: true,
}
}
// ReminderScheduler handles the scheduling of reminder notifications
type ReminderScheduler struct {
config *ReminderConfig
jobScheduler *JobScheduler
}
// NewReminderScheduler creates a new reminder scheduler
func NewReminderScheduler(config *ReminderConfig, jobScheduler *JobScheduler) *ReminderScheduler {
if config == nil {
config = DefaultReminderConfig()
}
return &ReminderScheduler{
config: config,
jobScheduler: jobScheduler,
}
}
// ScheduleRemindersForBooking schedules all reminders for a booking
func (rs *ReminderScheduler) ScheduleRemindersForBooking(bookingID uint, userID uint, meetingTime time.Time) error {
if !rs.config.Enabled {
return nil
}
now := time.Now()
scheduledCount := 0
for _, reminderMinutes := range rs.config.DefaultReminders {
if scheduledCount >= rs.config.MaxReminders {
break
}
reminderTime := meetingTime.Add(-time.Duration(reminderMinutes) * time.Minute)
// Skip if reminder time is in the past
if reminderTime.Before(now) {
continue
}
// Skip if reminder is too close to the meeting
if meetingTime.Sub(reminderTime).Minutes() < float64(rs.config.MinReminderTime) {
continue
}
// Schedule the reminder job
rs.jobScheduler.ScheduleReminderJob(bookingID, userID, reminderTime)
scheduledCount++
}
return nil
}
// CancelRemindersForBooking cancels all scheduled reminders for a booking
func (rs *ReminderScheduler) CancelRemindersForBooking(bookingID uint) error {
// In a production system, this would mark the reminders as cancelled in a persistent store
// For now, we'll just log the cancellation
// The actual implementation would depend on how jobs are persisted
return nil
}
// UpdateReminderConfig updates the reminder configuration
func (rs *ReminderScheduler) UpdateReminderConfig(config *ReminderConfig) {
rs.config = config
}
// GetReminderConfig returns the current reminder configuration
func (rs *ReminderScheduler) GetReminderConfig() *ReminderConfig {
return rs.config
}
// GetNextReminderTime calculates the next reminder time for a meeting
func (rs *ReminderScheduler) GetNextReminderTime(meetingTime time.Time) *time.Time {
if !rs.config.Enabled {
return nil
}
now := time.Now()
for _, reminderMinutes := range rs.config.DefaultReminders {
reminderTime := meetingTime.Add(-time.Duration(reminderMinutes) * time.Minute)
if reminderTime.After(now) {
return &reminderTime
}
}
return nil
}
// IsReminderTimeValid checks if a reminder time is valid
func (rs *ReminderScheduler) IsReminderTimeValid(reminderTime, meetingTime time.Time) bool {
if !rs.config.Enabled {
return false
}
// Check if reminder is in the future
if reminderTime.Before(time.Now()) {
return false
}
// Check if reminder is not too close to the meeting
timeDiff := meetingTime.Sub(reminderTime).Minutes()
if timeDiff < float64(rs.config.MinReminderTime) {
return false
}
return true
}