feat(conversations): expose inbox assistant
This commit is contained in:
@@ -783,6 +783,34 @@ func (h *ConversationHandler) ListAttachments(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"meta": gin.H{"total_count": total}, "payload": payload})
|
||||
}
|
||||
|
||||
// InboxAssistant returns the Captain assistant connected to the conversation inbox.
|
||||
// GET /api/v1/accounts/:account_id/conversations/:conversation_id/inbox_assistant
|
||||
// Reference: Chatwoot enterprise conversations_controller#inbox_assistant.
|
||||
func (h *ConversationHandler) InboxAssistant(c *gin.Context) {
|
||||
accountID, err := parseUintParam(c, "account_id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id")
|
||||
return
|
||||
}
|
||||
|
||||
conversationID, err := parseUintParam(c, "conversation_id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid conversation_id")
|
||||
return
|
||||
}
|
||||
|
||||
assistant, svcErr := h.conversationSvc.GetInboxAssistant(c.Request.Context(), accountID, conversationID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
if assistant == nil {
|
||||
c.JSON(http.StatusOK, gin.H{"assistant": nil})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"assistant": gin.H{"id": assistant.ID, "name": assistant.Name}})
|
||||
}
|
||||
|
||||
// ToggleTyping toggles the typing status for an agent in a conversation.
|
||||
// POST /api/v1/accounts/:account_id/conversations/:id/toggle_typing_status
|
||||
// Reference: Chatwoot conversations_controller#toggle_typing_status (member route)
|
||||
|
||||
@@ -85,6 +85,8 @@ func (s *ConversationCrudTestSuite) SetupSuite() {
|
||||
&model.SlaPolicy{},
|
||||
&model.AppliedSLA{},
|
||||
&model.SlaEvent{},
|
||||
&model.CaptainAssistant{},
|
||||
&model.CaptainInbox{},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
@@ -127,6 +129,7 @@ func (s *ConversationCrudTestSuite) SetupSuite() {
|
||||
conversations.POST("/filter", handler.Filter)
|
||||
conversations.POST("/:conversation_id/priority", handler.UpdatePriority)
|
||||
conversations.POST("/:conversation_id/assignments", handler.AssignTeam)
|
||||
conversations.GET("/:conversation_id/inbox_assistant", handler.InboxAssistant)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,6 +185,8 @@ func (s *ConversationCrudTestSuite) TearDownTest() {
|
||||
s.db.Exec("DELETE FROM teams")
|
||||
s.db.Exec("DELETE FROM team_members")
|
||||
s.db.Exec("DELETE FROM sla_policies")
|
||||
s.db.Exec("DELETE FROM captain_inboxes")
|
||||
s.db.Exec("DELETE FROM captain_assistants")
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) accountURL() string {
|
||||
@@ -340,6 +345,56 @@ func (s *ConversationCrudTestSuite) TestGet_NotFound() {
|
||||
assert.Equal(s.T(), http.StatusNotFound, w.Code)
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestInboxAssistant_ReturnsBoundAssistant() {
|
||||
assistant := &model.CaptainAssistant{AccountID: s.testAccount.ID, Name: "Inbox Helper", Description: "Helps this inbox", Config: json.RawMessage(`{}`), Status: model.AssistantStatusActive}
|
||||
s.Require().NoError(s.db.Create(assistant).Error)
|
||||
s.Require().NoError(s.db.Create(&model.CaptainInbox{AccountID: s.testAccount.ID, AssistantID: assistant.ID, InboxID: s.testInbox.ID}).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", s.convURL(s.testConv.ID)+"/inbox_assistant", nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
var resp map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
assistantResp, ok := resp["assistant"].(map[string]interface{})
|
||||
s.Require().True(ok)
|
||||
assert.Equal(s.T(), float64(assistant.ID), assistantResp["id"])
|
||||
assert.Equal(s.T(), "Inbox Helper", assistantResp["name"])
|
||||
assert.NotContains(s.T(), assistantResp, "description")
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestInboxAssistant_ReturnsNilWhenUnbound() {
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", s.convURL(s.testConv.ID)+"/inbox_assistant", nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
var resp map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
assert.Contains(s.T(), resp, "assistant")
|
||||
assert.Nil(s.T(), resp["assistant"])
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestInboxAssistant_UsesDisplayIDRoute() {
|
||||
displayID := uint(77)
|
||||
s.testConv.DisplayID = &displayID
|
||||
s.Require().NoError(s.db.Save(s.testConv).Error)
|
||||
assistant := &model.CaptainAssistant{AccountID: s.testAccount.ID, Name: "Display Helper", Description: "Display route", Config: json.RawMessage(`{}`), Status: model.AssistantStatusActive}
|
||||
s.Require().NoError(s.db.Create(assistant).Error)
|
||||
s.Require().NoError(s.db.Create(&model.CaptainInbox{AccountID: s.testAccount.ID, AssistantID: assistant.ID, InboxID: s.testInbox.ID}).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", s.accountURL()+"/conversations/77/inbox_assistant", nil)
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
var resp map[string]interface{}
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
assistantResp := resp["assistant"].(map[string]interface{})
|
||||
assert.Equal(s.T(), float64(assistant.ID), assistantResp["id"])
|
||||
}
|
||||
|
||||
// ========== Update Handler Tests ==========
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestUpdate_Success() {
|
||||
|
||||
Reference in New Issue
Block a user