Files
tm_back/internal/notification/handler.go
T
Mazyar 8fad771b7a
continuous-integration/drone/push Build is passing
Update notification response message for clarity
- Changed the response message in the `Send` method of the `NotificationHandler` from "Notification sent successfully" to "Notification created successfully" to better reflect the action performed.

This update improves the clarity of the notification response, ensuring users receive accurate feedback on their actions.
2026-06-22 23:46:56 +03:30

382 lines
13 KiB
Go

package notification
import (
"context"
"github.com/asaskevich/govalidator"
"github.com/labstack/echo/v4"
"tm/internal/customer"
"tm/internal/user"
"tm/pkg/response"
)
// NotificationHandler handles HTTP requests for notification operations
type NotificationHandler struct {
service Service
}
// NewNotificationHandler creates a new notification handler
func NewHandler(service Service) *NotificationHandler {
return &NotificationHandler{
service: service,
}
}
// CreateNotification creates a new notification
// @Summary Create a new notification
// @Description Create a new notification with the provided information
// @Tags Admin-Notification
// @Accept json
// @Produce json
// @Param notification body NotificationRequest true "Notification information"
// @Success 201 {object} response.APIResponse "Notification created successfully"
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /admin/v1/notifications [post]
func (h *NotificationHandler) Send(c echo.Context) error {
var req NotificationRequest
if err := c.Bind(&req); err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
// Validate request
if valid, err := govalidator.ValidateStruct(req); !valid {
return response.ValidationError(c, "Validation failed", err.Error())
}
// Send notification
go h.service.Send(context.Background(), &req)
return response.Created(c, nil, "Notification created successfully")
}
// GetNotifications gets notifications
// @Summary Get notifications
// @Description Get notifications
// @Tags Admin-Notification
// @Accept json
// @Produce json
// @Param search query string false "Search query for title and message"
// @Param q query string false "Search query for title and message (alias of search)"
// @Param status query string false "Status filter"
// @Param method query string false "Method filter"
// @Param event_type query string false "Event type filter"
// @Param type query string false "Type filter"
// @Param recipient query string false "Recipient filter"
// @Param seen query bool false "Seen filter"
// @Param priority query string false "Priority filter"
// @Param limit query int false "Limit results"
// @Param offset query int false "Offset results"
// @Param sort_by query string false "Sort field"
// @Param sort_order query string false "Sort order"
// @Success 200 {object} response.APIResponse{data=NotificationListResponse}
// @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /admin/v1/notifications [get]
func (h *NotificationHandler) GetNotifications(c echo.Context) error {
form, err := response.Parse[SearchForm](c)
if err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
// Validate form
if _, err := govalidator.ValidateStruct(form); err != nil {
return response.ValidationError(c, err.Error(), "")
}
pagination, err := response.NewPagination(c)
if err != nil {
return response.PaginationBadRequest(c, err)
}
notifications, err := h.service.GetNotifications(c.Request().Context(), form, pagination)
if err != nil {
if response.IsListPaginationError(err) {
return response.PaginationBadRequest(c, err)
}
return response.InternalServerError(c, "Failed to get notifications")
}
return response.SuccessWithMeta(c, notifications.Notifications, notifications.Meta, "Notifications retrieved successfully")
}
// MyAdminNotifications gets notifications for the admin
// @Summary Get notifications for the admin
// @Description Get notifications for the admin
// @Tags Admin-Notification
// @Accept json
// @Produce json
// @Param status query string false "Status filter"
// @Param method query string false "Method filter"
// @Param event_type query string false "Event type filter"
// @Param type query string false "Type filter"
// @Param recipient query string false "Recipient filter"
// @Param seen query bool false "Seen filter"
// @Param priority query string false "Priority filter"
// @Param limit query int false "Limit results"
// @Param offset query int false "Offset results"
// @Param sort_by query string false "Sort field"
// @Param sort_order query string false "Sort order"
// @Success 200 {object} response.APIResponse{data=NotificationListResponse}
// @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /admin/v1/notifications/my [get]
func (h *NotificationHandler) AdminNotifications(c echo.Context) error {
userID, err := user.GetUserIDFromContext(c)
if err != nil {
return response.BadRequest(c, "User ID required", "User must be associated with a user")
}
form, err := response.Parse[SearchForm](c)
if err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
// Validate form
if _, err := govalidator.ValidateStruct(form); err != nil {
return response.ValidationError(c, err.Error(), "")
}
form.Recipient = []string{userID}
form.Status = "sent"
form.EventType = EventTypeInApp
form.Method = ""
pagination, err := response.NewPagination(c)
if err != nil {
return response.PaginationBadRequest(c, err)
}
notifications, err := h.service.GetNotifications(c.Request().Context(), form, pagination)
if err != nil {
if response.IsListPaginationError(err) {
return response.PaginationBadRequest(c, err)
}
return response.InternalServerError(c, "Failed to get notifications")
}
return response.SuccessWithMeta(c, notifications.Notifications, notifications.Meta, "Notifications retrieved successfully")
}
// MarkSeen marks a notification as seen
// @Summary Mark a notification as seen
// @Description Mark a notification as seen
// @Tags Admin-Notification
// @Accept json
// @Produce json
// @Param id path string true "Notification ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /admin/v1/notifications/mark-seen/{id} [get]
func (h *NotificationHandler) MarkSeen(c echo.Context) error {
notificationID := c.Param("id")
userID, err := user.GetUserIDFromContext(c)
if err != nil {
return response.BadRequest(c, "User ID required", "User must be associated with a user")
}
// Mark notification as seen
err = h.service.MarkSeen(c.Request().Context(), notificationID, userID)
if err != nil {
return response.InternalServerError(c, "Failed to mark notification as seen")
}
return response.Success(c, nil, "Notification marked as seen successfully")
}
// ViewNotification gets a single notification by ID
// @Summary Get notification details
// @Description Get detailed information about a specific notification
// @Tags Admin-Notification
// @Accept json
// @Produce json
// @Param id path string true "Notification ID"
// @Success 200 {object} response.APIResponse{data=NotificationResponse}
// @Failure 400 {object} response.APIResponse
// @Failure 404 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /admin/v1/notifications/view/{id} [get]
func (h *NotificationHandler) ViewNotification(c echo.Context) error {
notificationID := c.Param("id")
if notificationID == "" {
return response.BadRequest(c, "notification ID is required", "Notification ID must be provided")
}
// Get notification details
notification, err := h.service.GetNotification(c.Request().Context(), notificationID)
if err != nil {
return response.InternalServerError(c, "Failed to get notification details")
}
return response.Success(c, notification, "Notification details retrieved successfully")
}
// **************************** PUBLIC ENDPOINTS ****************************
// MyNotifications gets notifications for the user
// @Summary Get notifications for the user
// @Description Get notifications for the user
// @Tags Notification
// @Accept json
// @Produce json
// @Param status query string false "Status filter"
// @Param method query string false "Method filter"
// @Param event_type query string false "Event type filter"
// @Param type query string false "Type filter"
// @Param recipient query string false "Recipient filter"
// @Param seen query bool false "Seen filter"
// @Param priority query string false "Priority filter"
// @Param limit query int false "Limit results"
// @Param offset query int false "Offset results"
// @Param sort_by query string false "Sort field"
// @Param sort_order query string false "Sort order"
// @Success 200 {object} response.APIResponse{data=NotificationListResponse}
// @Failure 401 {object} response.APIResponse
// @Failure 403 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /api/v1/notifications [get]
func (h *NotificationHandler) CustomerNotifications(c echo.Context) error {
userID, err := customer.GetCustomerIDFromContext(c)
if err != nil {
return response.BadRequest(c, "User ID required", "User must be associated with a user")
}
form, err := response.Parse[SearchForm](c)
if err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
// Validate form
if _, err := govalidator.ValidateStruct(form); err != nil {
return response.ValidationError(c, err.Error(), "")
}
form.Recipient = []string{userID}
form.Status = "sent"
form.EventType = EventTypeInApp
form.Method = ""
pagination, err := response.NewPagination(c)
if err != nil {
return response.PaginationBadRequest(c, err)
}
notifications, err := h.service.GetNotifications(c.Request().Context(), form, pagination)
if err != nil {
if response.IsListPaginationError(err) {
return response.PaginationBadRequest(c, err)
}
c.Logger().Error("GetNotifications failed", map[string]interface{}{
"error": err.Error(),
"status": form.Status,
"priority": form.Priority,
"eventType": form.EventType,
"recipient": form.Recipient,
"limit": pagination.Limit,
"offset": pagination.Offset,
"page": (pagination.Offset / pagination.Limit) + 1,
})
return response.InternalServerError(c, "Failed to get notifications")
}
return response.SuccessWithMeta(c, notifications.Notifications, notifications.Meta, "Notifications retrieved successfully")
}
// MarkSeen marks a notification as seen
// @Summary Mark a notification as seen
// @Description Mark a notification as seen
// @Tags Notification
// @Accept json
// @Produce json
// @Param id path string true "Notification ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /api/v1/notifications/mark/{id} [get]
func (h *NotificationHandler) PublicMarkSeen(c echo.Context) error {
notificationID := c.Param("id")
userID, err := customer.GetCustomerIDFromContext(c)
if err != nil {
return response.BadRequest(c, "User ID required", "User must be associated with a user")
}
// Mark notification as seen
err = h.service.MarkSeen(c.Request().Context(), notificationID, userID)
if err != nil {
return response.InternalServerError(c, "Failed to mark notification as seen")
}
return response.Success(c, nil, "Notification marked as seen successfully")
}
// AllMarkSeen marks all notifications as seen for a user
// @Summary Mark all notifications as seen for a user
// @Description Mark all notifications as seen for a user
// @Tags Notification
// @Accept json
// @Produce json
// @Param user_id path string true "User ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /api/v1/notifications/mark [get]
func (h *NotificationHandler) PublicAllMarkSeen(c echo.Context) error {
userID, err := customer.GetCustomerIDFromContext(c)
if err != nil {
return response.BadRequest(c, "user ID is required", "User ID must be provided")
}
// Mark all notifications as seen
err = h.service.AllMarkSeen(c.Request().Context(), userID)
if err != nil {
return response.InternalServerError(c, "Failed to mark all notifications as seen")
}
return response.Success(c, nil, "All notifications marked as seen successfully")
}
// ViewNotification gets a single notification by ID
// @Summary Get notification details
// @Description Get detailed information about a specific notification
// @Tags Notification
// @Accept json
// @Produce json
// @Param id path string true "Notification ID"
// @Success 200 {object} response.APIResponse{data=DetailedNotificationResponse}
// @Failure 400 {object} response.APIResponse
// @Failure 404 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Security BearerAuth
// @Router /api/v1/notifications/view/{id} [get]
func (h *NotificationHandler) PublicViewNotification(c echo.Context) error {
notificationID := c.Param("id")
if notificationID == "" {
return response.BadRequest(c, "notification ID is required", "Notification ID must be provided")
}
// Get notification details
notification, err := h.service.GetNotification(c.Request().Context(), notificationID)
if err != nil {
return response.InternalServerError(c, "Failed to get notification details")
}
return response.Success(c, notification, "Notification details retrieved successfully")
}