feat(routes): expand account parity coverage
This commit is contained in:
@@ -151,4 +151,72 @@ func (h *InboxMemberHandler) UpdateMultiple(c *gin.Context) {
|
||||
"members": members,
|
||||
"meta": gin.H{"count": len(members)},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ShowAccountScoped retrieves all agents assigned to an inbox using Chatwoot's account-level route.
|
||||
// GET /api/v1/accounts/:account_id/inbox_members/:inbox_id
|
||||
func (h *InboxMemberHandler) ShowAccountScoped(c *gin.Context) {
|
||||
inboxID, err := parseUintParam(c, "inbox_id")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid inbox id"})
|
||||
return
|
||||
}
|
||||
|
||||
members, svcErr := h.svc.ListByInbox(c.Request.Context(), inboxID)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to list inbox members"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"members": members, "meta": gin.H{"count": len(members)}})
|
||||
}
|
||||
|
||||
// CreateAccountScoped adds or replaces inbox members using Chatwoot's account-level create route.
|
||||
// POST /api/v1/accounts/:account_id/inbox_members
|
||||
func (h *InboxMemberHandler) CreateAccountScoped(c *gin.Context) {
|
||||
h.updateAccountScoped(c)
|
||||
}
|
||||
|
||||
// UpdateAccountScoped replaces all members of an inbox using Chatwoot's account-level update route.
|
||||
// PATCH /api/v1/accounts/:account_id/inbox_members
|
||||
func (h *InboxMemberHandler) UpdateAccountScoped(c *gin.Context) {
|
||||
h.updateAccountScoped(c)
|
||||
}
|
||||
|
||||
func (h *InboxMemberHandler) updateAccountScoped(c *gin.Context) {
|
||||
var req service.UpdateMultipleRequest
|
||||
if bindErr := c.ShouldBindJSON(&req); bindErr != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": bindErr.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
members, svcErr := h.svc.UpdateMultiple(c.Request.Context(), req)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to update members"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"members": members, "meta": gin.H{"count": len(members)}})
|
||||
}
|
||||
|
||||
// DestroyAccountScoped removes selected users from an inbox using Chatwoot's account-level route.
|
||||
// DELETE /api/v1/accounts/:account_id/inbox_members
|
||||
func (h *InboxMemberHandler) DestroyAccountScoped(c *gin.Context) {
|
||||
var req struct {
|
||||
InboxID uint `json:"inbox_id" binding:"required"`
|
||||
UserIDs []uint `json:"user_ids" binding:"required"`
|
||||
}
|
||||
if bindErr := c.ShouldBindJSON(&req); bindErr != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": bindErr.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
for _, userID := range req.UserIDs {
|
||||
if svcErr := h.svc.RemoveMember(c.Request.Context(), req.InboxID, userID); svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to remove member"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (h *NotificationHandler) Get(c *gin.Context) {
|
||||
response.AbortWithStatusError(c, http.StatusServiceUnavailable, response.ErrInternal, "Notification service not available")
|
||||
return
|
||||
}
|
||||
notificationID, err := parseUintParam(c, "notification_id")
|
||||
notificationID, err := parseUintAnyParam(c, "notification_id", "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
@@ -76,7 +76,7 @@ func (h *NotificationHandler) Get(c *gin.Context) {
|
||||
// PUT /api/v1/accounts/:account_id/notifications/:id
|
||||
// Reference: Chatwoot update — @notification.update(read_at: DateTime.now.utc); render json: @notification
|
||||
func (h *NotificationHandler) Update(c *gin.Context) {
|
||||
notificationID, err := parseUintParam(c, "notification_id")
|
||||
notificationID, err := parseUintAnyParam(c, "notification_id", "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
@@ -134,7 +134,7 @@ func (h *NotificationHandler) UnreadCount(c *gin.Context) {
|
||||
// POST /api/v1/accounts/:account_id/notifications/:id/snooze
|
||||
// Reference: Chatwoot snooze — update(snoozed_until: ..., meta: ...)
|
||||
func (h *NotificationHandler) Snooze(c *gin.Context) {
|
||||
notificationID, err := parseUintParam(c, "notification_id")
|
||||
notificationID, err := parseUintAnyParam(c, "notification_id", "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
@@ -170,7 +170,7 @@ func (h *NotificationHandler) Snooze(c *gin.Context) {
|
||||
// POST /api/v1/accounts/:account_id/notifications/:id/unread
|
||||
// Reference: Chatwoot unread — @notification.update(read_at: nil); render json: @notification
|
||||
func (h *NotificationHandler) Unread(c *gin.Context) {
|
||||
notificationID, err := parseUintParam(c, "notification_id")
|
||||
notificationID, err := parseUintAnyParam(c, "notification_id", "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
@@ -192,7 +192,7 @@ func (h *NotificationHandler) Unread(c *gin.Context) {
|
||||
// DELETE /api/v1/accounts/:account_id/notifications/:id
|
||||
// Reference: Chatwoot destroy — @notification.destroy; head :ok
|
||||
func (h *NotificationHandler) Destroy(c *gin.Context) {
|
||||
notificationID, err := parseUintParam(c, "notification_id")
|
||||
notificationID, err := parseUintAnyParam(c, "notification_id", "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid notification id")
|
||||
return
|
||||
@@ -225,4 +225,4 @@ func (h *NotificationHandler) DestroyAll(c *gin.Context) {
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,13 +519,13 @@ func registerV1Routes(g *gin.RouterGroup, h *Handlers) {
|
||||
inboxes.PATCH("/:inbox_id/members/update_multiple", h.InboxMember.UpdateMultiple)
|
||||
inboxes.DELETE("/:inbox_id/members/:user_id", h.InboxMember.RemoveMember)
|
||||
|
||||
// Account-level inbox_members (Chatwoot: resources :inbox_members)
|
||||
// POST /inbox_members (create), DELETE /inbox_members/:id (destroy)
|
||||
// These are account-scoped routes for managing inbox assignments
|
||||
// Account-level inbox_members (Chatwoot: resources :inbox_members, param: :inbox_id)
|
||||
inboxMembers := accountScoped.Group("/inbox_members")
|
||||
{
|
||||
inboxMembers.POST("/", h.InboxMember.AddMember)
|
||||
inboxMembers.DELETE("/:user_id", h.InboxMember.RemoveMember)
|
||||
inboxMembers.POST("/", h.InboxMember.CreateAccountScoped)
|
||||
inboxMembers.PATCH("/", h.InboxMember.UpdateAccountScoped)
|
||||
inboxMembers.DELETE("/", h.InboxMember.DestroyAccountScoped)
|
||||
inboxMembers.GET("/:inbox_id", h.InboxMember.ShowAccountScoped)
|
||||
}
|
||||
|
||||
// CSAT template (ref: Chatwoot resource :csat_template, singular per inbox)
|
||||
@@ -1338,6 +1338,23 @@ func registerV1Routes(g *gin.RouterGroup, h *Handlers) {
|
||||
{
|
||||
notifSettings.GET("/", h.NotificationSetting.Show)
|
||||
notifSettings.PATCH("/", h.NotificationSetting.Update)
|
||||
notifSettings.PUT("/", h.NotificationSetting.Update)
|
||||
}
|
||||
|
||||
// Notifications — account-scoped Chatwoot routes used by the dashboard frontend.
|
||||
notifications := accountScoped.Group("/notifications")
|
||||
{
|
||||
notifications.GET("/", h.Notification.List)
|
||||
notifications.POST("/read_all", h.Notification.MarkAllRead)
|
||||
notifications.GET("/unread_count", h.Notification.UnreadCount)
|
||||
notifications.POST("/destroy_all", h.Notification.DestroyAll)
|
||||
notifications.DELETE("/destroy_all", h.Notification.DestroyAll)
|
||||
notifications.GET("/:notification_id", h.Notification.Get)
|
||||
notifications.PUT("/:notification_id", h.Notification.Update)
|
||||
notifications.PATCH("/:notification_id", h.Notification.Update)
|
||||
notifications.DELETE("/:notification_id", h.Notification.Destroy)
|
||||
notifications.POST("/:notification_id/snooze", h.Notification.Snooze)
|
||||
notifications.POST("/:notification_id/unread", h.Notification.Unread)
|
||||
}
|
||||
|
||||
// Notification subscriptions (account-scoped)
|
||||
|
||||
Reference in New Issue
Block a user