Enhance Notification Management with New Endpoints and Response Structures

- Added new endpoints for retrieving notifications for both admins and users, improving the flexibility of the notification system.
- Implemented query parameters for filtering notifications by status, method, event type, type, and recipient, enhancing usability.
- Introduced new response structures for notifications, including pagination information, to provide better data handling in API responses.
- Updated API documentation with Swagger comments for the new endpoints and response formats, ensuring clarity for API consumers.
- Refactored notification handling logic to support the new features, promoting a more robust notification management system.
This commit is contained in:
n.nakhostin
2025-09-20 17:41:21 +03:30
parent ab6eb3b3ed
commit 19cd346b1c
13 changed files with 1637 additions and 16 deletions
+72
View File
@@ -68,10 +68,82 @@ requests := []*notification.NotificationRequest{...}
batchResponse, err := sdk.SendBatch(ctx, requests)
```
### Getting Notifications
#### Get All Notifications
```go
// Get all notifications
response, err := sdk.GetNotifications(ctx, &notification.GetNotificationsRequest{})
```
#### Get Notifications with Filters
```go
// Get notifications for specific user
response, err := sdk.GetNotificationsByUser(ctx, "user_id_here", 1, 10)
// Get notifications by status
response, err := sdk.GetNotificationsByStatus(ctx, "sent", 1, 10)
// Get notifications with custom filters
req := &notification.GetNotificationsRequest{
Status: "sent",
Method: "email",
EventType: "EMAIL",
Type: "info",
UserID: "user_id_here",
Page: 1,
PerPage: 10,
}
response, err := sdk.GetNotifications(ctx, req)
```
#### Quick Get Notifications
```go
// Quick method for basic filtering
response, err := sdk.QuickGetNotifications(ctx, "user_id_here", "sent")
```
## API Response
### Send Notification Response
- **Success**: `{"status": "Notification sent"}`
- **Error**: `{"error": "error message"}`
### Get Notifications Response
```json
{
"data": [
{
"id": "68ceaaec99c78402b5fec555",
"user_id": "689a0aca36bf9aae890c30c1",
"title": "CHECK",
"message": "Check Send Notification Channels",
"link": "",
"image": "",
"type": "info",
"priority": "low",
"event_type": "EMAIL",
"created_at": "2025-09-20T13:23:56.664Z",
"updated_at": "0001-01-01T00:00:00Z",
"methods": {
"email": "nakhostin.nima1998@gmail.com"
},
"metadata": null,
"status": "sent",
"scheduled_at": 0,
"is_scheduled": false
}
],
"pagination": {
"total": 3,
"count": 3,
"per_page": 10,
"current_page": 1,
"total_pages": 1
}
}
```
## Error Handling
```go
if err != nil {
+107
View File
@@ -197,6 +197,113 @@ func (c *Client) sendRequest(ctx context.Context, req *NotificationRequest) (*No
return &notificationResp, nil
}
// GetNotifications retrieves a list of notifications from the notification service
func (c *Client) GetNotifications(ctx context.Context, req *GetNotificationsRequest) (*NotificationListResponse, error) {
if c.config.EnableLogging && c.logger != nil {
c.logger.Debug("Getting notifications", map[string]interface{}{
"status": req.Status,
"method": req.Method,
"event_type": req.EventType,
"type": req.Type,
"user_id": req.UserID,
"base_url": c.config.BaseURL,
})
}
// Build query parameters
queryParams := c.buildQueryParams(req)
// Create HTTP request
url := fmt.Sprintf("%s/api/v1/notifications?%s", c.config.BaseURL, queryParams)
httpReq, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create HTTP request: %w", err)
}
// Set headers
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("User-Agent", c.config.UserAgent)
// Send request
resp, err := c.httpClient.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("HTTP request failed: %w", err)
}
defer resp.Body.Close()
// Read response body
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
// Handle non-2xx status codes
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
// Try to parse error response
var errorResp NotificationErrorResponse
if json.Unmarshal(body, &errorResp) == nil && errorResp.Error != "" {
return nil, MapHTTPError(resp.StatusCode, errorResp.Error)
}
return nil, MapHTTPError(resp.StatusCode, string(body))
}
// Parse success response
var notificationsResp NotificationListResponse
if err := json.Unmarshal(body, &notificationsResp); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
if c.config.EnableLogging && c.logger != nil {
c.logger.Info("Notifications retrieved successfully", map[string]interface{}{
"count": len(notificationsResp.Data),
"total": notificationsResp.Pagination.Total,
"page": notificationsResp.Pagination.CurrentPage,
"total_pages": notificationsResp.Pagination.TotalPages,
})
}
return &notificationsResp, nil
}
// buildQueryParams builds query parameters from the request
func (c *Client) buildQueryParams(req *GetNotificationsRequest) string {
params := make([]string, 0)
if req.Status != "" {
params = append(params, fmt.Sprintf("status=%s", req.Status))
}
if req.Method != "" {
params = append(params, fmt.Sprintf("method=%s", req.Method))
}
if req.EventType != "" {
params = append(params, fmt.Sprintf("event_type=%s", req.EventType))
}
if req.Type != "" {
params = append(params, fmt.Sprintf("type=%s", req.Type))
}
if req.UserID != "" {
params = append(params, fmt.Sprintf("user_id=%s", req.UserID))
}
if req.Page > 0 {
params = append(params, fmt.Sprintf("page=%d", req.Page))
}
if req.PerPage > 0 {
params = append(params, fmt.Sprintf("per_page=%d", req.PerPage))
}
// Join parameters with &
if len(params) == 0 {
return ""
}
result := params[0]
for i := 1; i < len(params); i++ {
result += "&" + params[i]
}
return result
}
// shouldRetry determines if a request should be retried based on the error
func (c *Client) shouldRetry(err error) bool {
switch e := err.(type) {
+46
View File
@@ -116,3 +116,49 @@ func (nm *NotificationMethods) GetMethodValue(eventType EventType) string {
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"`
}
// 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"`
}
+3
View File
@@ -21,6 +21,9 @@ type NotificationService interface {
// SendOTP sends an OTP notification
SendOTP(ctx context.Context, model Model) (*NotificationResponse, error)
// GetNotifications retrieves a list of notifications
GetNotifications(ctx context.Context, req *GetNotificationsRequest) (*NotificationListResponse, error)
// Health checks if the notification service is available
Health(ctx context.Context) error
+34
View File
@@ -74,6 +74,11 @@ func (s *SDK) SendOTP(ctx context.Context, model Model) (*NotificationResponse,
return s.service.SendOTP(ctx, model)
}
// GetNotifications retrieves a list of notifications from the notification service
func (s *SDK) GetNotifications(ctx context.Context, req *GetNotificationsRequest) (*NotificationListResponse, error) {
return s.service.GetNotifications(ctx, req)
}
// NewBuilder creates a new notification builder for fluent API usage
func (s *SDK) NewBuilder() Builder {
return s.service.(*Service).NewBuilder()
@@ -115,6 +120,35 @@ func (s *SDK) QuickOTP(ctx context.Context, model Model) error {
return err
}
// QuickGetNotifications retrieves notifications with simple parameters
func (s *SDK) QuickGetNotifications(ctx context.Context, userID, status string) (*NotificationListResponse, error) {
req := &GetNotificationsRequest{
UserID: userID,
Status: status,
}
return s.GetNotifications(ctx, req)
}
// GetNotificationsByUser retrieves notifications for a specific user
func (s *SDK) GetNotificationsByUser(ctx context.Context, userID string, page, perPage int) (*NotificationListResponse, error) {
req := &GetNotificationsRequest{
UserID: userID,
Page: page,
PerPage: perPage,
}
return s.GetNotifications(ctx, req)
}
// GetNotificationsByStatus retrieves notifications by status
func (s *SDK) GetNotificationsByStatus(ctx context.Context, status string, page, perPage int) (*NotificationListResponse, error) {
req := &GetNotificationsRequest{
Status: status,
Page: page,
PerPage: perPage,
}
return s.GetNotifications(ctx, req)
}
// Batch operations for sending multiple notifications
// BatchRequest represents a batch notification request
+5
View File
@@ -104,6 +104,11 @@ func (s *Service) SendOTP(ctx context.Context, model Model) (*NotificationRespon
return s.client.SendNotification(ctx, req)
}
// GetNotifications retrieves a list of notifications from the notification service
func (s *Service) GetNotifications(ctx context.Context, req *GetNotificationsRequest) (*NotificationListResponse, error) {
return s.client.GetNotifications(ctx, req)
}
// Health checks if the notification service is available
func (s *Service) Health(ctx context.Context) error {
// Create a simple test request to check service availability