feat(custom-fields): align chatwoot saved view payloads

This commit is contained in:
2026-06-06 00:53:33 +08:00
parent 171cbd16d2
commit 328d16c363
12 changed files with 461 additions and 147 deletions
@@ -2,14 +2,55 @@ package v1
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/gochat/gochat/internal/model"
"github.com/gochat/gochat/internal/service"
"github.com/gochat/gochat/pkg/pagination"
"github.com/gochat/gochat/pkg/response"
)
type chatwootCustomAttributeDefinitionResponse struct {
ID uint `json:"id"`
AttributeDisplayName string `json:"attribute_display_name"`
AttributeDisplayType string `json:"attribute_display_type"`
AttributeDescription string `json:"attribute_description"`
AttributeKey string `json:"attribute_key"`
RegexPattern string `json:"regex_pattern"`
RegexCue string `json:"regex_cue"`
AttributeValues interface{} `json:"attribute_values"`
AttributeModel string `json:"attribute_model"`
DefaultValue interface{} `json:"default_value"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func serializeCustomAttributeDefinition(def *model.CustomAttributeDefinition) chatwootCustomAttributeDefinitionResponse {
return chatwootCustomAttributeDefinitionResponse{
ID: def.ID,
AttributeDisplayName: def.AttributeDisplayName,
AttributeDisplayType: def.AttributeType,
AttributeDescription: def.Description,
AttributeKey: def.AttributeName,
RegexPattern: def.RegexPattern,
RegexCue: def.RegexCue,
AttributeValues: def.AttributeValues,
AttributeModel: def.AttributeModel,
DefaultValue: def.DefaultValue,
CreatedAt: def.CreatedAt,
UpdatedAt: def.UpdatedAt,
}
}
func serializeCustomAttributeDefinitions(defs []model.CustomAttributeDefinition) []chatwootCustomAttributeDefinitionResponse {
items := make([]chatwootCustomAttributeDefinitionResponse, 0, len(defs))
for i := range defs {
items = append(items, serializeCustomAttributeDefinition(&defs[i]))
}
return items
}
// CustomAttributeDefinitionHandler handles CRUD for custom attribute definitions.
// Reference: Chatwoot app/controllers/api/v1/accounts/custom_attribute_definitions_controller.rb
type CustomAttributeDefinitionHandler struct {
@@ -32,15 +73,14 @@ func (h *CustomAttributeDefinitionHandler) List(c *gin.Context) {
}
attributeModel := c.Query("attribute_model")
page := pagination.Parse(c)
defs, total, svcErr := h.svc.List(c.Request.Context(), accountID, attributeModel, page.Offset, page.PerPage)
defs, _, svcErr := h.svc.List(c.Request.Context(), accountID, attributeModel, 0, 0)
if svcErr != nil {
handleServiceError(c, svcErr)
return
}
response.OKWithMeta(c, defs, page.Page, page.PerPage, total)
c.JSON(http.StatusOK, serializeCustomAttributeDefinitions(defs))
}
// Get retrieves a single custom attribute definition by ID.
@@ -64,7 +104,7 @@ func (h *CustomAttributeDefinitionHandler) Get(c *gin.Context) {
return
}
response.OK(c, def)
c.JSON(http.StatusOK, serializeCustomAttributeDefinition(def))
}
// Create creates a new custom attribute definition for an account.
@@ -76,15 +116,11 @@ func (h *CustomAttributeDefinitionHandler) Create(c *gin.Context) {
return
}
// Chatwoot: params.require(:custom_attribute_definition) → {"custom_attribute_definition": {...}}
var wrapper struct {
CustomAttributeDefinition service.CreateCustomAttributeDefinitionRequest `json:"custom_attribute_definition"`
}
if err := c.ShouldBindJSON(&wrapper); err != nil {
var req service.CreateCustomAttributeDefinitionRequest
if err := bindChatwootPayload(c, "custom_attribute_definition", &req); err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
return
}
req := wrapper.CustomAttributeDefinition
def, svcErr := h.svc.Create(c.Request.Context(), accountID, &req)
if svcErr != nil {
@@ -92,7 +128,7 @@ func (h *CustomAttributeDefinitionHandler) Create(c *gin.Context) {
return
}
response.Created(c, def)
c.JSON(http.StatusOK, serializeCustomAttributeDefinition(def))
}
// Update modifies a custom attribute definition.
@@ -110,15 +146,11 @@ func (h *CustomAttributeDefinitionHandler) Update(c *gin.Context) {
return
}
// Chatwoot: params.require(:custom_attribute_definition) → {"custom_attribute_definition": {...}}
var wrapper struct {
CustomAttributeDefinition service.UpdateCustomAttributeDefinitionRequest `json:"custom_attribute_definition"`
}
if err := c.ShouldBindJSON(&wrapper); err != nil {
var req service.UpdateCustomAttributeDefinitionRequest
if err := bindChatwootPayload(c, "custom_attribute_definition", &req); err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
return
}
req := wrapper.CustomAttributeDefinition
def, svcErr := h.svc.Update(c.Request.Context(), accountID, id, &req)
if svcErr != nil {
@@ -126,7 +158,7 @@ func (h *CustomAttributeDefinitionHandler) Update(c *gin.Context) {
return
}
response.OK(c, def)
c.JSON(http.StatusOK, serializeCustomAttributeDefinition(def))
}
// Delete soft-deletes a custom attribute definition.