| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| package controller |
|
|
| import ( |
| "net/http" |
| "strconv" |
| "time" |
| "veloera/common" |
| "veloera/dto" |
| "veloera/model" |
|
|
| "github.com/gin-gonic/gin" |
| ) |
|
|
| |
| func GetUserMessages(c *gin.Context) { |
| userId := c.GetInt("id") |
| p, _ := strconv.Atoi(c.Query("p")) |
| pageSize, _ := strconv.Atoi(c.Query("page_size")) |
| |
| if p < 1 { |
| p = 1 |
| } |
| if pageSize <= 0 { |
| pageSize = common.ItemsPerPage |
| } else if pageSize > 100 { |
| pageSize = 100 |
| } |
|
|
| startIdx := (p - 1) * pageSize |
| userMessages, total, err := model.GetUserMessages(userId, startIdx, pageSize) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": err.Error(), |
| }) |
| return |
| } |
|
|
| |
| var responseData []gin.H |
| for _, userMessage := range userMessages { |
| responseData = append(responseData, gin.H{ |
| "id": userMessage.Message.Id, |
| "title": userMessage.Message.Title, |
| "content": userMessage.Message.Content, |
| "format": userMessage.Message.Format, |
| "created_at": userMessage.Message.CreatedAt, |
| "is_read": userMessage.ReadAt != nil, |
| "read_at": userMessage.ReadAt, |
| }) |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": gin.H{ |
| "items": responseData, |
| "total": total, |
| "page": p, |
| "page_size": pageSize, |
| }, |
| }) |
| } |
|
|
| |
| func MarkMessageAsRead(c *gin.Context) { |
| userId := c.GetInt("id") |
| messageId, err := strconv.Atoi(c.Param("id")) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid message ID", |
| }) |
| return |
| } |
|
|
| |
| userMessage, err := model.GetUserMessageById(userId, messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Message not found or access denied", |
| }) |
| return |
| } |
|
|
| |
| if userMessage.ReadAt == nil { |
| err = model.MarkUserMessageAsRead(userId, messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": err.Error(), |
| }) |
| return |
| } |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "Message marked as read", |
| }) |
| } |
|
|
| |
| func GetUnreadCount(c *gin.Context) { |
| userId := c.GetInt("id") |
| |
| count, err := model.GetUnreadMessageCount(userId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": err.Error(), |
| }) |
| return |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": gin.H{ |
| "unread_count": count, |
| }, |
| }) |
| } |
|
|
| |
|
|
| |
| func GetAllMessages(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| |
| p, _ := strconv.Atoi(c.Query("p")) |
| pageSize, _ := strconv.Atoi(c.Query("page_size")) |
| keyword := c.Query("keyword") |
|
|
| if p < 1 { |
| p = 1 |
| } |
| if pageSize <= 0 { |
| pageSize = common.ItemsPerPage |
| } else if pageSize > 100 { |
| pageSize = 100 |
| } |
|
|
| startIdx := (p - 1) * pageSize |
| messages, total, err := model.GetAllMessages(startIdx, pageSize, keyword) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": err.Error(), |
| }) |
| return |
| } |
|
|
| |
| var responseData []dto.AdminMessageResponse |
| for _, message := range messages { |
| |
| stats, err := model.GetMessageStats(message.Id) |
| if err != nil { |
| |
| stats = map[string]interface{}{ |
| "total_recipients": 0, |
| "read_count": 0, |
| "unread_count": 0, |
| "read_rate": 0.0, |
| } |
| } |
|
|
| responseData = append(responseData, dto.AdminMessageResponse{ |
| Id: message.Id, |
| Title: message.Title, |
| Content: message.Content, |
| Format: message.Format, |
| CreatedAt: message.CreatedAt, |
| UpdatedAt: message.UpdatedAt, |
| CreatedBy: message.CreatedBy, |
| Stats: stats, |
| }) |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": gin.H{ |
| "items": responseData, |
| "total": total, |
| "page": p, |
| "page_size": pageSize, |
| }, |
| }) |
| } |
|
|
| |
| func GetMessage(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| messageId, err := strconv.Atoi(c.Param("id")) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid message ID", |
| }) |
| return |
| } |
|
|
| message, err := model.GetMessageById(messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Message not found", |
| }) |
| return |
| } |
|
|
| |
| stats, err := model.GetMessageStats(messageId) |
| if err != nil { |
| stats = map[string]interface{}{ |
| "total_recipients": 0, |
| "read_count": 0, |
| "unread_count": 0, |
| "read_rate": 0.0, |
| } |
| } |
|
|
| response := dto.AdminMessageResponse{ |
| Id: message.Id, |
| Title: message.Title, |
| Content: message.Content, |
| Format: message.Format, |
| CreatedAt: message.CreatedAt, |
| UpdatedAt: message.UpdatedAt, |
| CreatedBy: message.CreatedBy, |
| Stats: stats, |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": response, |
| }) |
| } |
|
|
| |
| func CreateMessage(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| var req dto.CreateMessageRequest |
| if err := c.ShouldBindJSON(&req); err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid request data: " + err.Error(), |
| }) |
| return |
| } |
|
|
| |
| if req.Format == "" { |
| req.Format = "markdown" |
| } |
| if req.Format != "markdown" && req.Format != "html" { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid format: must be 'markdown' or 'html'", |
| }) |
| return |
| } |
|
|
| |
| if len(req.UserIds) == 0 { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "At least one recipient must be specified", |
| }) |
| return |
| } |
|
|
| |
| message := &model.Message{ |
| Title: req.Title, |
| Content: req.Content, |
| Format: req.Format, |
| CreatedAt: time.Now(), |
| UpdatedAt: time.Now(), |
| CreatedBy: c.GetInt("id"), |
| } |
|
|
| |
| err := model.CreateMessageForUsers(message, req.UserIds) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Failed to create message: " + err.Error(), |
| }) |
| return |
| } |
|
|
| |
| stats, err := model.GetMessageStats(message.Id) |
| if err != nil { |
| stats = map[string]interface{}{ |
| "total_recipients": len(req.UserIds), |
| "read_count": 0, |
| "unread_count": len(req.UserIds), |
| "read_rate": 0.0, |
| } |
| } |
|
|
| response := dto.AdminMessageResponse{ |
| Id: message.Id, |
| Title: message.Title, |
| Content: message.Content, |
| Format: message.Format, |
| CreatedAt: message.CreatedAt, |
| UpdatedAt: message.UpdatedAt, |
| CreatedBy: message.CreatedBy, |
| Stats: stats, |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "Message created and sent successfully", |
| "data": response, |
| }) |
| } |
|
|
| |
| func UpdateMessage(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| messageId, err := strconv.Atoi(c.Param("id")) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid message ID", |
| }) |
| return |
| } |
|
|
| var req dto.UpdateMessageRequest |
| if err := c.ShouldBindJSON(&req); err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid request data: " + err.Error(), |
| }) |
| return |
| } |
|
|
| |
| if req.Format == "" { |
| req.Format = "markdown" |
| } |
| if req.Format != "markdown" && req.Format != "html" { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid format: must be 'markdown' or 'html'", |
| }) |
| return |
| } |
|
|
| |
| message, err := model.GetMessageById(messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Message not found", |
| }) |
| return |
| } |
|
|
| |
| message.Title = req.Title |
| message.Content = req.Content |
| message.Format = req.Format |
| message.UpdatedAt = time.Now() |
|
|
| |
| err = message.Update() |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Failed to update message: " + err.Error(), |
| }) |
| return |
| } |
|
|
| |
| stats, err := model.GetMessageStats(messageId) |
| if err != nil { |
| stats = map[string]interface{}{ |
| "total_recipients": 0, |
| "read_count": 0, |
| "unread_count": 0, |
| "read_rate": 0.0, |
| } |
| } |
|
|
| response := dto.AdminMessageResponse{ |
| Id: message.Id, |
| Title: message.Title, |
| Content: message.Content, |
| Format: message.Format, |
| CreatedAt: message.CreatedAt, |
| UpdatedAt: message.UpdatedAt, |
| CreatedBy: message.CreatedBy, |
| Stats: stats, |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "Message updated successfully", |
| "data": response, |
| }) |
| } |
|
|
| |
| func DeleteMessage(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| messageId, err := strconv.Atoi(c.Param("id")) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid message ID", |
| }) |
| return |
| } |
|
|
| |
| message, err := model.GetMessageById(messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Message not found", |
| }) |
| return |
| } |
|
|
| |
| err = message.Delete() |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Failed to delete message: " + err.Error(), |
| }) |
| return |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "Message deleted successfully", |
| }) |
| } |
|
|
| |
| func SearchMessages(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| |
| p, _ := strconv.Atoi(c.Query("p")) |
| pageSize, _ := strconv.Atoi(c.Query("page_size")) |
| keyword := c.Query("keyword") |
| startDate := c.Query("start_date") |
| endDate := c.Query("end_date") |
|
|
| if p < 1 { |
| p = 1 |
| } |
| if pageSize <= 0 { |
| pageSize = common.ItemsPerPage |
| } else if pageSize > 100 { |
| pageSize = 100 |
| } |
|
|
| startIdx := (p - 1) * pageSize |
| messages, total, err := model.SearchMessages(startIdx, pageSize, keyword, startDate, endDate) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": err.Error(), |
| }) |
| return |
| } |
|
|
| |
| var responseData []dto.AdminMessageResponse |
| for _, message := range messages { |
| |
| stats, err := model.GetMessageStats(message.Id) |
| if err != nil { |
| |
| stats = map[string]interface{}{ |
| "total_recipients": 0, |
| "read_count": 0, |
| "unread_count": 0, |
| "read_rate": 0.0, |
| } |
| } |
|
|
| responseData = append(responseData, dto.AdminMessageResponse{ |
| Id: message.Id, |
| Title: message.Title, |
| Content: message.Content, |
| Format: message.Format, |
| CreatedAt: message.CreatedAt, |
| UpdatedAt: message.UpdatedAt, |
| CreatedBy: message.CreatedBy, |
| Stats: stats, |
| }) |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": gin.H{ |
| "items": responseData, |
| "total": total, |
| "page": p, |
| "page_size": pageSize, |
| }, |
| }) |
| } |
|
|
| |
| func GetMessageRecipients(c *gin.Context) { |
| |
| role := c.GetInt("role") |
| if role < common.RoleAdminUser { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Access denied: admin privileges required", |
| }) |
| return |
| } |
|
|
| messageId, err := strconv.Atoi(c.Param("id")) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Invalid message ID", |
| }) |
| return |
| } |
|
|
| |
| _, err = model.GetMessageById(messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Message not found", |
| }) |
| return |
| } |
|
|
| |
| recipients, err := model.GetMessageRecipients(messageId) |
| if err != nil { |
| c.JSON(http.StatusOK, gin.H{ |
| "success": false, |
| "message": "Failed to retrieve recipients: " + err.Error(), |
| }) |
| return |
| } |
|
|
| c.JSON(http.StatusOK, gin.H{ |
| "success": true, |
| "message": "", |
| "data": recipients, |
| }) |
| } |