feat(crm): align contact company payloads
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/search"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
@@ -68,10 +69,7 @@ func (h *ContactHandler) List(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"contacts": contacts,
|
||||
"meta": gin.H{"count": total, "page": page, "page_size": perPage},
|
||||
})
|
||||
c.JSON(http.StatusOK, contactListResponse(c.Request.Context(), h.svc.DB(), contacts, total, page, includeContactInboxes(c), nil))
|
||||
}
|
||||
|
||||
// @Summary Search contacts
|
||||
@@ -102,6 +100,10 @@ func (h *ContactHandler) Search(c *gin.Context) {
|
||||
}
|
||||
|
||||
query := c.Query("q")
|
||||
if query == "" {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "Specify search string with parameter q"})
|
||||
return
|
||||
}
|
||||
page := getPage(c)
|
||||
perPage := getPageSize(c)
|
||||
offset := (page - 1) * perPage
|
||||
@@ -114,10 +116,8 @@ func (h *ContactHandler) Search(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"contacts": contacts,
|
||||
"meta": gin.H{"count": total, "page": page, "page_size": perPage},
|
||||
})
|
||||
hasMore := int64(len(contacts)) < total
|
||||
c.JSON(http.StatusOK, contactListResponse(c.Request.Context(), h.svc.DB(), contacts, int64(len(contacts)), page, includeContactInboxes(c), &hasMore))
|
||||
}
|
||||
|
||||
// @Summary Get a single contact
|
||||
@@ -155,7 +155,7 @@ func (h *ContactHandler) Get(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contact)
|
||||
c.JSON(http.StatusOK, contactPayloadResponse(c.Request.Context(), h.svc.DB(), contact, includeContactInboxes(c)))
|
||||
}
|
||||
|
||||
// @Summary Create a new contact
|
||||
@@ -194,7 +194,14 @@ func (h *ContactHandler) Create(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, contact)
|
||||
var contactInbox *model.ContactInbox
|
||||
if h.svc.DB() != nil {
|
||||
var ci model.ContactInbox
|
||||
if err := h.svc.DB().WithContext(c.Request.Context()).Preload("Inbox").Where("contact_id = ?", contact.ID).Order("id DESC").First(&ci).Error; err == nil {
|
||||
contactInbox = &ci
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, contactCreateResponse(c.Request.Context(), h.svc.DB(), contact, contactInbox))
|
||||
}
|
||||
|
||||
// @Summary Update a contact
|
||||
@@ -239,7 +246,7 @@ func (h *ContactHandler) Update(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, contact)
|
||||
c.JSON(http.StatusOK, contactPayloadResponse(c.Request.Context(), h.svc.DB(), contact, includeContactInboxes(c)))
|
||||
}
|
||||
|
||||
// @Summary Delete a contact
|
||||
@@ -276,7 +283,7 @@ func (h *ContactHandler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "contact deleted"})
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
// ListContactInboxes retrieves all contact_inboxes for a contact.
|
||||
@@ -295,10 +302,11 @@ func (h *ContactHandler) ListContactInboxes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"contact_inboxes": contactInboxes,
|
||||
"meta": gin.H{"count": len(contactInboxes)},
|
||||
})
|
||||
payload := make([]any, 0, len(contactInboxes))
|
||||
for i := range contactInboxes {
|
||||
payload = append(payload, serializeContactInbox(&contactInboxes[i]))
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"payload": payload, "meta": gin.H{"count": len(payload)}})
|
||||
}
|
||||
|
||||
// ListConversations retrieves recent conversations for a contact.
|
||||
@@ -368,9 +376,7 @@ func (h *ContactHandler) ListNotes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"notes": notes,
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{"payload": notes})
|
||||
}
|
||||
|
||||
// CreateNote creates a note for a contact.
|
||||
@@ -490,6 +496,13 @@ func (h *ContactHandler) DestroyNote(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func includeContactInboxes(c *gin.Context) bool {
|
||||
if raw := c.Query("include_contact_inboxes"); raw != "" {
|
||||
return raw == "true"
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// parseIntOrDefault parses an integer query parameter with a default value.
|
||||
func parseIntOrDefault(c *gin.Context, key string, defaultVal int) int {
|
||||
val := c.Query(key)
|
||||
@@ -636,7 +649,10 @@ func (h *ContactHandler) Import(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
file, _, fileErr := c.Request.FormFile("file")
|
||||
file, _, fileErr := c.Request.FormFile("import_file")
|
||||
if fileErr != nil {
|
||||
file, _, fileErr = c.Request.FormFile("file")
|
||||
}
|
||||
if fileErr != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "csv file required"})
|
||||
return
|
||||
@@ -674,7 +690,11 @@ func (h *ContactHandler) ContactableInboxes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"payload": inboxes})
|
||||
payload := make([]any, 0, len(inboxes))
|
||||
for _, item := range inboxes {
|
||||
payload = append(payload, map[string]any{"inbox": serializeInboxSlim(&item.Inbox), "source_id": item.SourceID})
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"payload": payload})
|
||||
}
|
||||
|
||||
// DeleteCustomAttributes removes all custom attributes from a contact.
|
||||
@@ -698,7 +718,12 @@ func (h *ContactHandler) DeleteCustomAttributes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "custom attributes deleted"})
|
||||
contact, svcErr := h.svc.GetByAccountAndID(c.Request.Context(), accountID, contactID)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to load contact"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, contactPayloadResponse(c.Request.Context(), h.svc.DB(), contact, true))
|
||||
}
|
||||
|
||||
// Merge two contacts into one. The base contact survives, mergee is deleted.
|
||||
@@ -749,7 +774,7 @@ func (h *ContactHandler) Filter(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
response.OKWithMeta(c, contacts, p.Page, p.PerPage, total)
|
||||
c.JSON(http.StatusOK, contactListResponse(c.Request.Context(), h.svc.DB(), contacts, total, p.Page, includeContactInboxes(c), nil))
|
||||
}
|
||||
|
||||
// DestroyCustomAttributes removes all custom attributes from a contact.
|
||||
@@ -769,10 +794,18 @@ func (h *ContactHandler) DestroyCustomAttributes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if svcErr := h.svc.DeleteCustomAttributes(c.Request.Context(), accountID, contactID); svcErr != nil {
|
||||
var req struct {
|
||||
CustomAttributes []string `json:"custom_attributes"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
contact, svcErr := h.svc.DestroyCustomAttributes(c.Request.Context(), accountID, contactID, req.CustomAttributes)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to destroy custom attributes"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "custom attributes destroyed"})
|
||||
c.JSON(http.StatusOK, contactPayloadResponse(c.Request.Context(), h.svc.DB(), contact, true))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user