package handler import ( "apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/logger" "apskel-pos-be/internal/service" "apskel-pos-be/internal/util" "apskel-pos-be/internal/validator" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type NotificationHandler struct { notificationService service.NotificationService notificationValidator validator.NotificationValidator } func NewNotificationHandler( notificationService service.NotificationService, notificationValidator validator.NotificationValidator, ) *NotificationHandler { return &NotificationHandler{ notificationService: notificationService, notificationValidator: notificationValidator, } } // Send godoc // POST /api/v1/notifications/send // Sends a notification to specific users. func (h *NotificationHandler) Send(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) var req contract.SendNotificationRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::Send -> request binding failed") validationErr := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::Send") return } if validationErr, errCode := h.notificationValidator.ValidateSendRequest(&req); validationErr != nil { respErr := contract.NewResponseError(errCode, constants.RequestEntity, validationErr.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{respErr}), "NotificationHandler::Send") return } resp := h.notificationService.Send(ctx, &req, contextInfo.UserID) if resp.HasErrors() { logger.FromContext(ctx).WithError(resp.GetErrors()[0]).Error("NotificationHandler::Send -> service error") } util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::Send") } // Broadcast godoc // POST /api/v1/notifications/broadcast // Sends a notification to all active users in the caller's organization. func (h *NotificationHandler) Broadcast(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) var req contract.BroadcastNotificationRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::Broadcast -> request binding failed") validationErr := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::Broadcast") return } if validationErr, errCode := h.notificationValidator.ValidateBroadcastRequest(&req); validationErr != nil { respErr := contract.NewResponseError(errCode, constants.RequestEntity, validationErr.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{respErr}), "NotificationHandler::Broadcast") return } resp := h.notificationService.Broadcast(ctx, &req, contextInfo.OrganizationID, contextInfo.UserID) if resp.HasErrors() { logger.FromContext(ctx).WithError(resp.GetErrors()[0]).Error("NotificationHandler::Broadcast -> service error") } util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::Broadcast") } // List godoc // GET /api/v1/notifications // Returns paginated notifications for the authenticated user. func (h *NotificationHandler) List(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) req := contract.ListNotificationsRequest{ Page: 1, Limit: 20, } if err := c.ShouldBindQuery(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::List -> query binding failed") validationErr := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::List") return } if validationErr, errCode := h.notificationValidator.ValidateListRequest(&req); validationErr != nil { respErr := contract.NewResponseError(errCode, constants.RequestEntity, validationErr.Error()) util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{respErr}), "NotificationHandler::List") return } resp := h.notificationService.ListForUser(ctx, &req, contextInfo.UserID) util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::List") } // GetByID godoc // GET /api/v1/notifications/:id func (h *NotificationHandler) GetByID(c *gin.Context) { ctx := c.Request.Context() idStr := c.Param("id") id, err := uuid.Parse(idStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::GetByID -> invalid notification ID") validationErr := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid notification ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::GetByID") return } resp := h.notificationService.GetByID(ctx, id) util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::GetByID") } // MarkAsRead godoc // PUT /api/v1/notifications/:id/read func (h *NotificationHandler) MarkAsRead(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) idStr := c.Param("id") receiverID, err := uuid.Parse(idStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::MarkAsRead -> invalid receiver ID") validationErr := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid notification receiver ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::MarkAsRead") return } resp := h.notificationService.MarkAsRead(ctx, receiverID, contextInfo.UserID) if resp.HasErrors() { logger.FromContext(ctx).WithError(resp.GetErrors()[0]).Error("NotificationHandler::MarkAsRead -> service error") } util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::MarkAsRead") } // MarkAllAsRead godoc // PUT /api/v1/notifications/read-all func (h *NotificationHandler) MarkAllAsRead(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) resp := h.notificationService.MarkAllAsRead(ctx, contextInfo.UserID) util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::MarkAllAsRead") } // Delete godoc // DELETE /api/v1/notifications/:id func (h *NotificationHandler) Delete(c *gin.Context) { ctx := c.Request.Context() contextInfo := appcontext.FromGinContext(ctx) idStr := c.Param("id") receiverID, err := uuid.Parse(idStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("NotificationHandler::Delete -> invalid receiver ID") validationErr := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, "Invalid notification receiver ID") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationErr}), "NotificationHandler::Delete") return } resp := h.notificationService.DeleteForUser(ctx, receiverID, contextInfo.UserID) if resp.HasErrors() { logger.FromContext(ctx).WithError(resp.GetErrors()[0]).Error("NotificationHandler::Delete -> service error") } util.HandleResponse(c.Writer, c.Request, resp, "NotificationHandler::Delete") }