feat(accounts): align account payloads

This commit is contained in:
2026-06-06 00:07:17 +08:00
parent 5efa1955e5
commit 2ab7b582e0
5 changed files with 133 additions and 49 deletions
+52 -6
View File
@@ -1,9 +1,11 @@
package v1
import (
"encoding/json"
"net/http"
"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/pagination"
@@ -78,7 +80,7 @@ func (h *AccountHandler) Get(c *gin.Context) {
return
}
response.OK(c, account)
c.JSON(http.StatusOK, serializeAccount(account))
}
// @Summary Create a new account
@@ -113,7 +115,7 @@ func (h *AccountHandler) Create(c *gin.Context) {
return
}
response.Created(c, account)
c.JSON(http.StatusOK, gin.H{"data": gin.H{"id": userID, "account_id": account.ID}})
}
// @Summary Update an existing account
@@ -149,7 +151,7 @@ func (h *AccountHandler) Update(c *gin.Context) {
return
}
response.OK(c, account)
c.JSON(http.StatusOK, serializeAccount(account))
}
// @Summary Delete an account
@@ -310,7 +312,7 @@ func (h *AccountHandler) UpdateSettings(c *gin.Context) {
return
}
response.OK(c, account)
c.JSON(http.StatusOK, serializeAccount(account))
}
// --- Account extension handlers (G8) ---
@@ -332,7 +334,7 @@ func (h *AccountHandler) UpdateActiveAt(c *gin.Context) {
return
}
response.OK(c, gin.H{"message": "Active timestamp updated"})
c.Status(http.StatusOK)
}
// CacheKeys returns cache key identifiers for frontend cache invalidation.
@@ -352,5 +354,49 @@ func (h *AccountHandler) CacheKeys(c *gin.Context) {
return
}
response.OK(c, keys)
c.JSON(http.StatusOK, gin.H{"cache_keys": keys})
}
func serializeAccount(account *model.Account) map[string]any {
if account == nil {
return map[string]any{}
}
return map[string]any{
"settings": serializeAccountSettings(account),
"created_at": account.CreatedAt,
"domain": account.Domain,
"features": parseAccountFeatures(account.FeatureFlags),
"id": account.ID,
"locale": nonEmpty(account.Locale, "en"),
"name": account.Name,
"support_email": nil,
"status": nonEmpty(account.Status, "active"),
"cache_keys": map[string]string{"label": "0000000000", "inbox": "0000000000", "team": "0000000000"},
"custom_attributes": map[string]any{
"timezone": account.Timezone,
},
}
}
func serializeAccountSettings(account *model.Account) map[string]any {
settings := map[string]any{
"auto_resolve_after": account.AutoResolveDuration,
"auto_resolve_duration": account.AutoResolveDuration,
"auto_resolve_message": "",
"auto_resolve_ignore_waiting": false,
"audio_transcriptions": false,
"auto_resolve_label": "",
}
return settings
}
func parseAccountFeatures(raw string) map[string]any {
features := map[string]any{}
if raw == "" {
return features
}
if err := json.Unmarshal([]byte(raw), &features); err != nil {
return features
}
return features
}
+37 -13
View File
@@ -28,9 +28,9 @@ import (
type AccountHandlerTestSuite struct {
suite.Suite
router *gin.Engine
handler *AccountHandler
db *gorm.DB
router *gin.Engine
handler *AccountHandler
db *gorm.DB
testUserID uint
}
@@ -191,8 +191,11 @@ func (s *AccountHandlerTestSuite) TestGet_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
resp := s.unmarshalResponse(w)
data := resp["data"].(map[string]interface{})
assert.Equal(s.T(), "Get Account", data["name"])
assert.NotContains(s.T(), resp, "success")
assert.Equal(s.T(), "Get Account", resp["name"])
assert.Contains(s.T(), resp, "settings")
assert.Contains(s.T(), resp, "features")
assert.Contains(s.T(), resp, "cache_keys")
}
func (s *AccountHandlerTestSuite) TestGet_NotFound() {
@@ -221,10 +224,24 @@ func (s *AccountHandlerTestSuite) TestCreate_Success() {
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusCreated, w.Code)
assert.Equal(s.T(), http.StatusOK, w.Code)
resp := s.unmarshalResponse(w)
data := resp["data"].(map[string]interface{})
assert.Equal(s.T(), "New Test Account", data["name"])
assert.NotZero(s.T(), data["account_id"])
assert.NotContains(s.T(), resp, "success")
}
func (s *AccountHandlerTestSuite) TestCreate_ChatwootAccountName() {
body := `{"account_name":"Chatwoot Account"}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/v1/accounts", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
resp := s.unmarshalResponse(w)
data := resp["data"].(map[string]interface{})
assert.NotZero(s.T(), data["account_id"])
}
func (s *AccountHandlerTestSuite) TestCreate_MissingName() {
@@ -251,8 +268,8 @@ func (s *AccountHandlerTestSuite) TestUpdate_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
resp := s.unmarshalResponse(w)
data := resp["data"].(map[string]interface{})
assert.Equal(s.T(), "After Update", data["name"])
assert.NotContains(s.T(), resp, "success")
assert.Equal(s.T(), "After Update", resp["name"])
}
// ====== Delete Account ======
@@ -278,8 +295,10 @@ func (s *AccountHandlerTestSuite) TestUpdateSettings() {
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
// Should succeed or return acceptable status
assert.True(s.T(), w.Code == http.StatusOK || w.Code == http.StatusNoContent || w.Code < 500)
assert.Equal(s.T(), http.StatusOK, w.Code)
resp := s.unmarshalResponse(w)
assert.NotContains(s.T(), resp, "success")
assert.Contains(s.T(), resp, "settings")
}
// ====== List Users ======
@@ -429,6 +448,7 @@ func (s *AccountHandlerTestSuite) TestUpdateActiveAt_Success() {
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
assert.Empty(s.T(), w.Body.String())
// Verify active_at was updated in DB
var au model.AccountUser
@@ -456,7 +476,11 @@ func (s *AccountHandlerTestSuite) TestCacheKeys_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
data := s.unmarshalResponse(w)
assert.NotNil(s.T(), data)
keys := data["cache_keys"].(map[string]interface{})
assert.Equal(s.T(), "0000000000", keys["label"])
assert.Equal(s.T(), "0000000000", keys["inbox"])
assert.Equal(s.T(), "0000000000", keys["team"])
assert.NotContains(s.T(), data, "success")
}
func (s *AccountHandlerTestSuite) TestCacheKeys_InvalidID() {
@@ -465,4 +489,4 @@ func (s *AccountHandlerTestSuite) TestCacheKeys_InvalidID() {
s.router.ServeHTTP(w, req)
assert.True(s.T(), w.Code >= 400)
}
}