5906904caf
- Added new endpoints for marking notifications as seen and retrieving detailed notification information for both admin and user contexts, improving the flexibility of the notification system. - Implemented the MarkSeen and ViewNotification methods in the NotificationHandler, ensuring proper handling of notification visibility and details retrieval. - Updated the NotificationService interface to include methods for getting notification details and marking notifications as seen, enhancing service capabilities. - Enhanced the notification response structures to include additional fields such as Image, Seen, and ScheduledAt, providing richer data in API responses. - Updated API documentation with Swagger comments for the new endpoints and response formats, ensuring clarity for API consumers.
203 lines
6.9 KiB
Go
203 lines
6.9 KiB
Go
package notification
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/asaskevich/govalidator"
|
|
)
|
|
|
|
// EventType represents the type of notification event
|
|
type EventType string
|
|
|
|
const (
|
|
EventTypeEmail EventType = "EMAIL"
|
|
EventTypeSMS EventType = "SMS"
|
|
EventTypePush EventType = "PUSH"
|
|
EventTypeOTP EventType = "OTP"
|
|
)
|
|
|
|
// NotificationMethods contains different delivery methods for notifications
|
|
type NotificationMethods struct {
|
|
OTP string `json:"otp,omitempty" valid:"optional"`
|
|
SMS string `json:"sms,omitempty" valid:"optional"`
|
|
Push string `json:"push,omitempty" valid:"optional"`
|
|
Email string `json:"email,omitempty" valid:"optional,email"`
|
|
}
|
|
|
|
// NotificationRequest represents the request structure for sending notifications
|
|
type NotificationRequest struct {
|
|
UserID string `json:"user_id"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
Type string `json:"type"`
|
|
EventType EventType `json:"event_type"`
|
|
Priority string `json:"priority"`
|
|
ScheduledAt int64 `json:"scheduled_at"`
|
|
Metadata map[string]any `json:"metadata"`
|
|
Methods NotificationMethods `json:"methods"`
|
|
}
|
|
|
|
// NotificationResponse represents the successful response from notification service
|
|
type NotificationResponse struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
// DetailedNotificationResponse represents a detailed notification response
|
|
type DetailedNotificationResponse struct {
|
|
Data struct {
|
|
ID string `json:"id"`
|
|
UserID string `json:"user_id"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
Link string `json:"link"`
|
|
Image string `json:"image"`
|
|
Type string `json:"type"` // info, warning, alert, reject
|
|
Priority string `json:"priority"` // low, medium, important
|
|
EventType string `json:"event_type"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Methods map[string]string `json:"methods"`
|
|
Metadata map[string]any `json:"metadata"`
|
|
Status string `json:"status"` // pending, sent, failed
|
|
Seen bool `json:"seen"`
|
|
SeenAt int64 `json:"seen_at"`
|
|
ScheduledAt int64 `json:"scheduled_at"`
|
|
IsScheduled bool `json:"is_scheduled"`
|
|
} `json:"data"`
|
|
}
|
|
|
|
// NotificationErrorResponse represents the error response from notification service
|
|
type NotificationErrorResponse struct {
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
// Validate validates the notification request
|
|
func (nr *NotificationRequest) Validate() error {
|
|
// First run govalidator validation
|
|
if _, err := govalidator.ValidateStruct(nr); err != nil {
|
|
return ErrValidation{Field: "struct", Message: err.Error()}
|
|
}
|
|
|
|
// Custom validation: ensure at least one method is provided based on event type
|
|
switch nr.EventType {
|
|
case EventTypeEmail:
|
|
if nr.Methods.Email == "" {
|
|
return ErrValidation{Field: "methods.email", Message: "email address is required for EMAIL event type"}
|
|
}
|
|
case EventTypeSMS:
|
|
if nr.Methods.SMS == "" {
|
|
return ErrValidation{Field: "methods.sms", Message: "SMS number is required for SMS event type"}
|
|
}
|
|
case EventTypePush:
|
|
if nr.Methods.Push == "" {
|
|
return ErrValidation{Field: "methods.push", Message: "push device token is required for PUSH event type"}
|
|
}
|
|
case EventTypeOTP:
|
|
if nr.Methods.OTP == "" {
|
|
return ErrValidation{Field: "methods.otp", Message: "OTP number is required for OTP event type"}
|
|
}
|
|
}
|
|
|
|
// Validate scheduled_at: 0 means immediate delivery, otherwise must be future timestamp
|
|
if nr.ScheduledAt < 0 {
|
|
return ErrValidation{Field: "scheduled_at", Message: "scheduled_at cannot be negative"}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HasMethod checks if a specific method is configured
|
|
func (nm *NotificationMethods) HasMethod(eventType EventType) bool {
|
|
switch eventType {
|
|
case EventTypeEmail:
|
|
return nm.Email != ""
|
|
case EventTypeSMS:
|
|
return nm.SMS != ""
|
|
case EventTypePush:
|
|
return nm.Push != ""
|
|
case EventTypeOTP:
|
|
return nm.OTP != ""
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// GetMethodValue returns the value for a specific method
|
|
func (nm *NotificationMethods) GetMethodValue(eventType EventType) string {
|
|
switch eventType {
|
|
case EventTypeEmail:
|
|
return nm.Email
|
|
case EventTypeSMS:
|
|
return nm.SMS
|
|
case EventTypePush:
|
|
return nm.Push
|
|
case EventTypeOTP:
|
|
return nm.OTP
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// IsImmediate returns true if the notification should be sent immediately (scheduled_at = 0)
|
|
func (nr *NotificationRequest) IsImmediate() bool {
|
|
return nr.ScheduledAt == 0
|
|
}
|
|
|
|
// NotificationItem represents a single notification in the list response
|
|
type NotificationItem struct {
|
|
ID string `json:"id"`
|
|
UserID string `json:"user_id"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
Link string `json:"link"`
|
|
Image string `json:"image"`
|
|
Type string `json:"type"`
|
|
Priority string `json:"priority"`
|
|
EventType string `json:"event_type"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
Methods map[string]string `json:"methods"`
|
|
Metadata map[string]any `json:"metadata"`
|
|
Status string `json:"status"`
|
|
ScheduledAt int64 `json:"scheduled_at"`
|
|
IsScheduled bool `json:"is_scheduled"`
|
|
Seen bool `json:"seen"`
|
|
SeenAt int64 `json:"seen_at"`
|
|
}
|
|
|
|
// NotificationListResponse represents the response from getting notifications list
|
|
type NotificationListResponse struct {
|
|
Data []NotificationItem `json:"data"`
|
|
Pagination PaginationInfo `json:"pagination"`
|
|
}
|
|
|
|
// PaginationInfo represents pagination information in responses
|
|
type PaginationInfo struct {
|
|
Total int `json:"total"`
|
|
Count int `json:"count"`
|
|
PerPage int `json:"per_page"`
|
|
CurrentPage int `json:"current_page"`
|
|
TotalPages int `json:"total_pages"`
|
|
}
|
|
|
|
// GetNotificationsRequest represents the request parameters for getting notifications
|
|
type GetNotificationsRequest struct {
|
|
Status string `json:"status,omitempty" valid:"optional"`
|
|
Method string `json:"method,omitempty" valid:"optional"`
|
|
EventType string `json:"event_type,omitempty" valid:"optional"`
|
|
Type string `json:"type,omitempty" valid:"optional"`
|
|
UserID string `json:"user_id,omitempty" valid:"optional"`
|
|
Page int `json:"page,omitempty" valid:"optional"`
|
|
PerPage int `json:"per_page,omitempty" valid:"optional"`
|
|
}
|
|
|
|
// MarkSeenRequest represents the request for marking a notification as seen
|
|
type MarkSeenRequest struct {
|
|
NotificationID string `json:"notification_id" valid:"required"`
|
|
}
|
|
|
|
// MarkSeenResponse represents the response from marking a notification as seen
|
|
type MarkSeenResponse struct {
|
|
Status string `json:"status"`
|
|
}
|