From 95224faa34a637298252f9a0430dd3cb6c711406 Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 5 Jun 2026 07:03:01 +0800 Subject: [PATCH] feat(sla): align sla policy payloads --- internal/handler/api/v1/sla_policy_handler.go | 36 +++++++++++++--- .../handler/api/v1/sla_policy_handler_test.go | 42 ++++++++++++++++++- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/internal/handler/api/v1/sla_policy_handler.go b/internal/handler/api/v1/sla_policy_handler.go index ae3ab580..c6649a62 100644 --- a/internal/handler/api/v1/sla_policy_handler.go +++ b/internal/handler/api/v1/sla_policy_handler.go @@ -6,6 +6,7 @@ import ( "github.com/gin-gonic/gin" + "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/service" applogger "github.com/gochat/gochat/pkg/logger" "github.com/gochat/gochat/pkg/response" @@ -45,7 +46,7 @@ func (h *SlaPolicyHandler) Create(c *gin.Context) { return } - response.Created(c, policy) + c.JSON(http.StatusOK, gin.H{"payload": serializeSlaPolicy(policy)}) } // Get retrieves a SLA policy by ID. @@ -70,7 +71,7 @@ func (h *SlaPolicyHandler) Get(c *gin.Context) { return } - response.OK(c, policy) + c.JSON(http.StatusOK, gin.H{"payload": serializeSlaPolicy(policy)}) } // List retrieves all SLA policies for an account. @@ -89,7 +90,7 @@ func (h *SlaPolicyHandler) List(c *gin.Context) { return } - response.OK(c, policies) + c.JSON(http.StatusOK, gin.H{"payload": serializeSlaPolicies(policies)}) } // Update updates a SLA policy. @@ -121,7 +122,7 @@ func (h *SlaPolicyHandler) Update(c *gin.Context) { return } - response.OK(c, policy) + c.JSON(http.StatusOK, gin.H{"payload": serializeSlaPolicy(policy)}) } // Delete deletes a SLA policy. @@ -146,8 +147,31 @@ func (h *SlaPolicyHandler) Delete(c *gin.Context) { return } - // Chatwoot returns head :ok (200) on destroy — not 204 NoContent - c.JSON(http.StatusOK, gin.H{"success": true}) + // Chatwoot returns head :ok (200) on destroy. + c.Status(http.StatusOK) +} + +func serializeSlaPolicies(policies []model.SlaPolicy) []map[string]any { + payload := make([]map[string]any, 0, len(policies)) + for i := range policies { + payload = append(payload, serializeSlaPolicy(&policies[i])) + } + return payload +} + +func serializeSlaPolicy(policy *model.SlaPolicy) map[string]any { + if policy == nil { + return map[string]any{} + } + return map[string]any{ + "id": policy.ID, + "name": policy.Name, + "description": policy.Description, + "first_response_time_threshold": policy.FirstResponseTimeThreshold, + "next_response_time_threshold": policy.NextResponseTimeThreshold, + "resolution_time_threshold": policy.ResolutionTimeThreshold, + "only_during_business_hours": policy.OnlyDuringBusinessHours, + } } // GetAppliedSlaMetrics retrieves SLA metrics for a conversation. diff --git a/internal/handler/api/v1/sla_policy_handler_test.go b/internal/handler/api/v1/sla_policy_handler_test.go index d6d073e3..feb269b0 100644 --- a/internal/handler/api/v1/sla_policy_handler_test.go +++ b/internal/handler/api/v1/sla_policy_handler_test.go @@ -117,6 +117,19 @@ func TestSlaPolicyHandler_List_Success(t *testing.T) { router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) + + var got map[string]interface{} + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got)) + assert.NotContains(t, got, "success") + require.IsType(t, []interface{}{}, got["payload"]) + payload := got["payload"].([]interface{}) + require.Len(t, payload, 2) + + first := payload[0].(map[string]interface{}) + assert.Equal(t, "Policy-A", first["name"]) + assert.Equal(t, float64(10), first["first_response_time_threshold"]) + assert.NotContains(t, first, "created_at") + assert.NotContains(t, first, "account_id") } func TestSlaPolicyHandler_List_NoAccountID(t *testing.T) { @@ -156,7 +169,17 @@ func TestSlaPolicyHandler_Create_Success(t *testing.T) { req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) - assert.Equal(t, http.StatusCreated, w.Code) + assert.Equal(t, http.StatusOK, w.Code) + + var got map[string]interface{} + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got)) + assert.NotContains(t, got, "success") + payload := got["payload"].(map[string]interface{}) + assert.Equal(t, "New SLA", payload["name"]) + assert.Equal(t, "desc", payload["description"]) + assert.Equal(t, float64(30), payload["first_response_time_threshold"]) + assert.NotContains(t, payload, "created_at") + assert.NotContains(t, payload, "account_id") } func TestSlaPolicyHandler_Create_ValidationError(t *testing.T) { @@ -226,6 +249,15 @@ func TestSlaPolicyHandler_Get_Success(t *testing.T) { router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) + + var got map[string]interface{} + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got)) + assert.NotContains(t, got, "success") + payload := got["payload"].(map[string]interface{}) + assert.Equal(t, "GetTest", payload["name"]) + assert.Equal(t, float64(10), payload["first_response_time_threshold"]) + assert.NotContains(t, payload, "created_at") + assert.NotContains(t, payload, "account_id") } func TestSlaPolicyHandler_Get_InvalidID(t *testing.T) { @@ -271,6 +303,13 @@ func TestSlaPolicyHandler_Update_Success(t *testing.T) { router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) + + var got map[string]interface{} + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got)) + assert.NotContains(t, got, "success") + payload := got["payload"].(map[string]interface{}) + assert.Equal(t, "Updated Name", payload["name"]) + assert.Equal(t, float64(45), payload["first_response_time_threshold"]) } func TestSlaPolicyHandler_Update_NoAccountID(t *testing.T) { @@ -318,6 +357,7 @@ func TestSlaPolicyHandler_Delete_Success(t *testing.T) { // Chatwoot returns head :ok (200) on destroy, not 204 assert.Equal(t, http.StatusOK, w.Code) + assert.Empty(t, w.Body.String()) } func TestSlaPolicyHandler_Delete_NoAccountID(t *testing.T) {