feat(sla): persist applied sla on conversations
This commit is contained in:
@@ -82,6 +82,9 @@ func (s *ConversationCrudTestSuite) SetupSuite() {
|
||||
&model.AccountUser{},
|
||||
&model.Team{},
|
||||
&model.TeamMember{},
|
||||
&model.SlaPolicy{},
|
||||
&model.AppliedSLA{},
|
||||
&model.SlaEvent{},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
@@ -95,6 +98,8 @@ func (s *ConversationCrudTestSuite) SetupSuite() {
|
||||
teamRepo := repository.NewTeamRepo(db)
|
||||
teamMemberRepo := repository.NewTeamMemberRepo(db)
|
||||
conversationSvc := service.NewConversationService(convRepo, msgRepo, dispatcher, inboxMemberSvc, accountUserRepo, teamRepo, teamMemberRepo)
|
||||
appliedSlaSvc := service.NewAppliedSlaService(repository.NewAppliedSlaRepo(db), repository.NewSlaEventRepo(db), repository.NewSlaPolicyRepo(db), convRepo)
|
||||
conversationSvc.SetAppliedSlaService(appliedSlaSvc)
|
||||
mockLLM := &mockConvCrudLLMProvider{}
|
||||
messageSvc := service.NewMessageService(msgRepo, dispatcher, mockLLM)
|
||||
handler := NewConversationHandler(conversationSvc, messageSvc)
|
||||
@@ -163,6 +168,8 @@ func (s *ConversationCrudTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TearDownTest() {
|
||||
s.db.Exec("DELETE FROM sla_events")
|
||||
s.db.Exec("DELETE FROM applied_slas")
|
||||
s.db.Exec("DELETE FROM conversation_labels")
|
||||
s.db.Exec("DELETE FROM conversations")
|
||||
s.db.Exec("DELETE FROM contact_inboxes")
|
||||
@@ -174,6 +181,7 @@ func (s *ConversationCrudTestSuite) TearDownTest() {
|
||||
s.db.Exec("DELETE FROM accounts")
|
||||
s.db.Exec("DELETE FROM teams")
|
||||
s.db.Exec("DELETE FROM team_members")
|
||||
s.db.Exec("DELETE FROM sla_policies")
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) accountURL() string {
|
||||
@@ -352,6 +360,44 @@ func (s *ConversationCrudTestSuite) TestUpdate_Success() {
|
||||
assert.Equal(s.T(), "resolved", resp["status"])
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestUpdate_WithSlaPolicyCreatesAppliedSlaPayload() {
|
||||
policy := &model.SlaPolicy{
|
||||
AccountID: s.testAccount.ID,
|
||||
Name: "Gold SLA",
|
||||
Description: "Priority customers",
|
||||
FirstResponseTimeThreshold: 15,
|
||||
NextResponseTimeThreshold: 30,
|
||||
ResolutionTimeThreshold: 120,
|
||||
}
|
||||
s.Require().NoError(s.db.Create(policy).Error)
|
||||
|
||||
body, _ := json.Marshal(map[string]interface{}{
|
||||
"sla_policy_id": policy.ID,
|
||||
})
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("PUT", s.convURL(s.testConv.ID), bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(s.T(), http.StatusOK, w.Code)
|
||||
|
||||
var resp map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), float64(policy.ID), resp["sla_policy_id"])
|
||||
|
||||
applied, ok := resp["applied_sla"].(map[string]interface{})
|
||||
s.Require().True(ok)
|
||||
assert.Equal(s.T(), float64(policy.ID), applied["sla_id"])
|
||||
assert.Equal(s.T(), "active", applied["sla_status"])
|
||||
assert.Equal(s.T(), "Gold SLA", applied["sla_name"])
|
||||
assert.Equal(s.T(), float64(15), applied["sla_first_response_time_threshold"])
|
||||
|
||||
var count int64
|
||||
s.Require().NoError(s.db.Model(&model.AppliedSLA{}).Where("conversation_id = ?", s.testConv.ID).Count(&count).Error)
|
||||
assert.Equal(s.T(), int64(1), count)
|
||||
}
|
||||
|
||||
func (s *ConversationCrudTestSuite) TestUpdate_InvalidAccountID() {
|
||||
body, _ := json.Marshal(map[string]interface{}{
|
||||
"status": "resolved",
|
||||
|
||||
@@ -55,6 +55,7 @@ type chatwootConversationPayload struct {
|
||||
Priority string `json:"priority"`
|
||||
WaitingSince int64 `json:"waiting_since"`
|
||||
SlaPolicyID *uint `json:"sla_policy_id"`
|
||||
AppliedSLA map[string]any `json:"applied_sla,omitempty"`
|
||||
}
|
||||
|
||||
type chatwootConversationMeta struct {
|
||||
@@ -135,7 +136,7 @@ func serializeConversation(ctx context.Context, db *gorm.DB, conversation *model
|
||||
}
|
||||
}
|
||||
|
||||
return chatwootConversationPayload{
|
||||
payload := chatwootConversationPayload{
|
||||
Meta: serializeConversationMeta(ctx, db, conversation),
|
||||
ID: conversationDisplayID(conversation),
|
||||
Messages: messages,
|
||||
@@ -163,6 +164,40 @@ func serializeConversation(ctx context.Context, db *gorm.DB, conversation *model
|
||||
WaitingSince: int64Value(conversation.WaitingSince),
|
||||
SlaPolicyID: conversation.SlaPolicyID,
|
||||
}
|
||||
|
||||
if appliedSLA := serializeAppliedSlaForConversation(ctx, db, conversation.ID); appliedSLA != nil {
|
||||
payload.AppliedSLA = appliedSLA
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
func serializeAppliedSlaForConversation(ctx context.Context, db *gorm.DB, conversationID uint) map[string]any {
|
||||
if db == nil || conversationID == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var applied model.AppliedSLA
|
||||
if err := db.WithContext(ctx).
|
||||
Preload("SlaPolicy").
|
||||
Where("conversation_id = ?", conversationID).
|
||||
First(&applied).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"id": applied.ID,
|
||||
"sla_id": applied.SlaPolicyID,
|
||||
"sla_status": applied.SLAStatus,
|
||||
"created_at": applied.CreatedAt.Unix(),
|
||||
"updated_at": applied.UpdatedAt.Unix(),
|
||||
"sla_description": applied.SlaPolicy.Description,
|
||||
"sla_name": applied.SlaPolicy.Name,
|
||||
"sla_first_response_time_threshold": applied.SlaPolicy.FirstResponseTimeThreshold,
|
||||
"sla_next_response_time_threshold": applied.SlaPolicy.NextResponseTimeThreshold,
|
||||
"sla_only_during_business_hours": applied.SlaPolicy.OnlyDuringBusinessHours,
|
||||
"sla_resolution_time_threshold": applied.SlaPolicy.ResolutionTimeThreshold,
|
||||
}
|
||||
}
|
||||
|
||||
func serializeConversationMeta(ctx context.Context, db *gorm.DB, conversation *model.Conversation) chatwootConversationMeta {
|
||||
|
||||
Reference in New Issue
Block a user