chore: 提交剩余开发改动
包含商务通消息映射、会话时间与未读状态、前端消息展示、数据库修复迁移、测试覆盖备份及 Captain 设计文档。
This commit is contained in:
@@ -1019,7 +1019,12 @@ func (h *ConversationHandler) UpdateLastSeen(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
updatedConversation, svcErr := h.conversationSvc.GetByAccountAndID(c.Request.Context(), accountID, conversation.ID)
|
||||
if svcErr != nil {
|
||||
handleServiceError(c, svcErr)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, serializeConversation(h.requestContext(c), h.conversationSvc.DB(), updatedConversation))
|
||||
}
|
||||
|
||||
// @Summary Assign a team to a conversation
|
||||
|
||||
@@ -90,6 +90,7 @@ func (s *ConversationCrudTestSuite) SetupSuite() {
|
||||
&model.CaptainAssistant{},
|
||||
&model.CaptainInbox{},
|
||||
&model.AgentBot{},
|
||||
&model.Notification{},
|
||||
&model.CustomAttributeDefinition{},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
@@ -135,6 +136,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.POST("/:conversation_id/update_last_seen", handler.UpdateLastSeen)
|
||||
conversations.GET("/:conversation_id/inbox_assistant", handler.InboxAssistant)
|
||||
}
|
||||
}
|
||||
@@ -205,6 +207,30 @@ func (s *ConversationCrudTestSuite) convURL(id uint) string {
|
||||
return s.accountURL() + "/conversations/" + strconv.FormatUint(uint64(id), 10)
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestUpdateLastSeen_ReturnsUpdatedConversation() {
|
||||
message := &model.Message{
|
||||
AccountID: s.testAccount.ID,
|
||||
InboxID: s.testInbox.ID,
|
||||
ConversationID: s.testConv.ID,
|
||||
MessageType: "incoming",
|
||||
ContentType: "text",
|
||||
Content: "unread message",
|
||||
Status: "sent",
|
||||
}
|
||||
s.Require().NoError(s.db.Create(message).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", s.convURL(s.testConv.ID)+"/update_last_seen", nil)
|
||||
req.Header.Set("X-User-ID", "1")
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
s.Require().Equal(http.StatusOK, w.Code, w.Body.String())
|
||||
var payload map[string]any
|
||||
s.Require().NoError(json.Unmarshal(w.Body.Bytes(), &payload))
|
||||
s.NotZero(payload["agent_last_seen_at"])
|
||||
s.Equal(float64(0), payload["unread_count"])
|
||||
}
|
||||
|
||||
// ========== List Handler Tests ==========
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestList_Success() {
|
||||
|
||||
@@ -892,7 +892,7 @@ func unreadCount(ctx context.Context, db *gorm.DB, conversation *model.Conversat
|
||||
query := db.WithContext(ctx).Model(&model.Message{}).
|
||||
Where("account_id = ? AND conversation_id = ? AND message_type = ?", conversation.AccountID, conversation.ID, "incoming")
|
||||
if conversation.AgentLastSeenAt != nil {
|
||||
query = query.Where("created_at > ?", time.Unix(*conversation.AgentLastSeenAt, 0))
|
||||
query = query.Where("created_at >= ?", time.Unix(*conversation.AgentLastSeenAt+1, 0))
|
||||
}
|
||||
var count int64
|
||||
_ = query.Count(&count).Error
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1393,14 +1393,15 @@ func widgetContactFullPayload(contact *model.Contact) gin.H {
|
||||
|
||||
func bindPublicContactRequest(c *gin.Context) (service.PublicContactRequest, error) {
|
||||
var body struct {
|
||||
SourceID string `json:"source_id"`
|
||||
Identifier string `json:"identifier"`
|
||||
IdentifierHash string `json:"identifier_hash"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
CustomAttributes map[string]any `json:"custom_attributes"`
|
||||
SourceID string `json:"source_id"`
|
||||
Identifier string `json:"identifier"`
|
||||
IdentifierHash string `json:"identifier_hash"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
CustomAttributes map[string]any `json:"custom_attributes"`
|
||||
AdditionalAttributes map[string]any `json:"additional_attributes"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil && c.Request.ContentLength != 0 {
|
||||
return service.PublicContactRequest{}, err
|
||||
@@ -1415,14 +1416,15 @@ func bindPublicContactRequest(c *gin.Context) (service.PublicContactRequest, err
|
||||
body.IdentifierHash = c.Query("identifier_hash")
|
||||
}
|
||||
return service.PublicContactRequest{
|
||||
SourceID: body.SourceID,
|
||||
Identifier: body.Identifier,
|
||||
IdentifierHash: body.IdentifierHash,
|
||||
Email: body.Email,
|
||||
Name: body.Name,
|
||||
AvatarURL: body.AvatarURL,
|
||||
PhoneNumber: body.PhoneNumber,
|
||||
CustomAttributes: body.CustomAttributes,
|
||||
SourceID: body.SourceID,
|
||||
Identifier: body.Identifier,
|
||||
IdentifierHash: body.IdentifierHash,
|
||||
Email: body.Email,
|
||||
Name: body.Name,
|
||||
AvatarURL: body.AvatarURL,
|
||||
PhoneNumber: body.PhoneNumber,
|
||||
CustomAttributes: body.CustomAttributes,
|
||||
AdditionalAttributes: body.AdditionalAttributes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user