feat(crm): persist contact data imports
This commit is contained in:
@@ -724,18 +724,18 @@ func (h *ContactHandler) Import(c *gin.Context) {
|
||||
file, _, fileErr = c.Request.FormFile("file")
|
||||
}
|
||||
if fileErr != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "csv file required"})
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to import contacts"})
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
result, svcErr := h.svc.ImportCSV(c.Request.Context(), accountID, file)
|
||||
_, svcErr := h.svc.ImportContacts(c.Request.Context(), accountID, getUserID(c), file)
|
||||
if svcErr != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "failed to import contacts"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
c.Status(http.StatusOK)
|
||||
}
|
||||
|
||||
// ContactableInboxes returns inboxes that a contact can be associated with.
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -51,6 +52,7 @@ func (s *ContactHandlerCRUDTestSuite) SetupSuite() {
|
||||
&model.Contact{},
|
||||
&model.Tag{},
|
||||
&model.ContactLabel{},
|
||||
&model.DataImport{},
|
||||
&model.Conversation{},
|
||||
&model.Message{},
|
||||
&model.ContactInbox{},
|
||||
@@ -82,6 +84,7 @@ func (s *ContactHandlerCRUDTestSuite) SetupSuite() {
|
||||
s.router.Use(gin.Recovery(), s.mockAuthMiddleware())
|
||||
s.router.GET("/api/v1/accounts/:id/contacts", s.handler.List)
|
||||
s.router.GET("/api/v1/accounts/:id/contacts/search", s.handler.Search)
|
||||
s.router.POST("/api/v1/accounts/:id/contacts/import", s.handler.Import)
|
||||
s.router.GET("/api/v1/accounts/:id/contacts/:contact_id", s.handler.Get)
|
||||
s.router.POST("/api/v1/accounts/:id/contacts", s.handler.Create)
|
||||
s.router.PUT("/api/v1/accounts/:id/contacts/:contact_id", s.handler.Update)
|
||||
@@ -120,6 +123,7 @@ func (s *ContactHandlerCRUDTestSuite) SetupTest() {
|
||||
s.db.Exec("DELETE FROM contact_notes")
|
||||
s.db.Exec("DELETE FROM contact_labels")
|
||||
s.db.Exec("DELETE FROM tags")
|
||||
s.db.Exec("DELETE FROM data_imports")
|
||||
s.db.Exec("DELETE FROM messages")
|
||||
s.db.Exec("DELETE FROM notes")
|
||||
s.db.Exec("DELETE FROM contact_inboxes")
|
||||
@@ -597,6 +601,40 @@ func (s *ContactHandlerCRUDTestSuite) TestMerge_ChatwootActionsPathReturnsRawCon
|
||||
s.Equal(int64(1), count)
|
||||
}
|
||||
|
||||
func (s *ContactHandlerCRUDTestSuite) TestImport_CreatesDataImportAndReturnsOK() {
|
||||
var body bytes.Buffer
|
||||
writer := multipart.NewWriter(&body)
|
||||
part, err := writer.CreateFormFile("import_file", "contacts.csv")
|
||||
s.Require().NoError(err)
|
||||
_, err = part.Write([]byte("name,email,labels\nImported,imported@example.com,vip\n"))
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(writer.Close())
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST",
|
||||
fmt.Sprintf("/api/v1/accounts/%d/contacts/import", s.account.ID),
|
||||
&body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
s.router.ServeHTTP(w, req)
|
||||
|
||||
s.Equal(http.StatusOK, w.Code)
|
||||
s.Empty(w.Body.String())
|
||||
|
||||
var dataImport model.DataImport
|
||||
s.Require().NoError(s.db.Where("account_id = ? AND data_type = ?", s.account.ID, "contacts").First(&dataImport).Error)
|
||||
s.Equal(string(model.DataImportStatusCompleted), dataImport.Status)
|
||||
s.Equal(1, dataImport.TotalRecords)
|
||||
s.Equal(1, dataImport.ProcessedRecords)
|
||||
s.Require().NotNil(dataImport.UserID)
|
||||
s.Equal(s.user.ID, *dataImport.UserID)
|
||||
|
||||
var contact model.Contact
|
||||
s.Require().NoError(s.db.Where("account_id = ? AND email = ?", s.account.ID, "imported@example.com").First(&contact).Error)
|
||||
var labelCount int64
|
||||
s.db.Model(&model.ContactLabel{}).Where("account_id = ? AND contact_id = ?", s.account.ID, contact.ID).Count(&labelCount)
|
||||
s.Equal(int64(1), labelCount)
|
||||
}
|
||||
|
||||
func (s *ContactHandlerCRUDTestSuite) TestLabels_UpdateListAndFilter() {
|
||||
bodyBytes, _ := json.Marshal(map[string]interface{}{"labels": []string{"vip", "trial"}})
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ func TestContactImportMissingFile(t *testing.T) {
|
||||
req, _ := http.NewRequest("POST", "/api/v1/accounts/1/contacts/import", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// Without a multipart form, FormFile will error, so we expect 400
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
// Chatwoot returns 422 when import_file is missing.
|
||||
assert.Equal(t, http.StatusUnprocessableEntity, w.Code)
|
||||
var resp map[string]interface{}
|
||||
json.Unmarshal(w.Body.Bytes(), &resp)
|
||||
assert.Contains(t, resp, "error")
|
||||
@@ -138,4 +138,4 @@ func TestDeleteCustomAttributesBadContactID(t *testing.T) {
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user