From 1614490390718b3b085db8cf9d7fbc3ca856c3eb Mon Sep 17 00:00:00 2001 From: Patrick Peng Sun Date: Fri, 30 Jun 2017 13:42:07 +1000 Subject: [PATCH] crmSearchLead -> crmdSearchLead data structure start with crm-d- entity search find by ID tested. --- crmEntity.go | 110 +++++++- crmEntity_test.go | 24 ++ crmLead.go | 4 +- crmLead_test.go | 4 +- sample_data/sample_crm_lead_query.json | 340 +++++++++++++++++++++++++ upload.go | 8 + 6 files changed, 483 insertions(+), 7 deletions(-) diff --git a/crmEntity.go b/crmEntity.go index 87dc983..16f5097 100644 --- a/crmEntity.go +++ b/crmEntity.go @@ -1,8 +1,13 @@ package main -import "log" -import "encoding/json" -import "strings" +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "strings" +) //abstract CRUD operation for espoCRM Entity @@ -103,3 +108,102 @@ func isErrIndicateDuplicate(e error) (yes bool) { yes = strings.ToLower(reason.Reason) == "duplicate" return } + +type crmdSearchFilter struct { + Attribute string + CompareMethod string //startWith, equals, contains, endsWith, like, isNull, isNotNull , notEquals + ExpectValue string +} + +type crmdSearchResult struct { + Total int `json:"total"` + List *json.RawMessage `json:"list"` +} + +func crmSearchEntity(entityType string, filters []crmdSearchFilter) (result crmdSearchResult, err error) { + + url := CRMConfig.BaseURL + "api/v1/" + entityType + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Println("crmGetRecord: cannot form good http Request") + log.Print(err) + return + } + + //auth header + req.Header.Set("Authorization", crmAuthHeader()) + req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01") + req.Header.Set("Content-Type", "application/json") + + //query string + q := req.URL.Query() + q.Add("maxSize", "20") + q.Add("maxSize", "0") + q.Add("sortBy", "createdAt") + q.Add("asc", "false") + + for k, v := range filters { + switch v.CompareMethod { + case "startWith", "equals", "contains", "endsWith", "like", "notEquals": + q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod) + q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute) + q.Add(fmt.Sprintf("where[%d][value]", k), v.ExpectValue) + case "isNull", "isNotNull": + q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod) + q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute) + default: + log.Printf("Unknown Compare Method %s", v.CompareMethod) + } + } + + req.URL.RawQuery = q.Encode() + + debugDumpHTTPRequest(req) + + client := &http.Client{} + r, err := client.Do(req) + + debugDumpHTTPResponse(r) + + if err != nil { + return + } + defer r.Body.Close() + + jsonB, err := ioutil.ReadAll(r.Body) + + if err != nil { + return + } + + err = json.Unmarshal(jsonB, &result) + return +} + +func crmFindEntityByID(entityType string, id string) (entity interface{}, err error) { + filters := []crmdSearchFilter{ + {"id", "equals", id}, + } + cs, err := crmSearchEntity(entityType, filters) + if err != nil || cs.Total < 1 { + return + } + + if cs.Total > 1 { + log.Printf("ERROR: more than one(%d) %s associated with %s", cs.Total, entityType, id) + } + + switch entityType { + case "Lead": + e := []crmdLead{} + err = json.Unmarshal(*cs.List, &e) + if (err != nil) || (len(e) != cs.Total) { + return + } + entity = e[0] + case "Account": + return + + } + return +} diff --git a/crmEntity_test.go b/crmEntity_test.go index be3180d..406916c 100644 --- a/crmEntity_test.go +++ b/crmEntity_test.go @@ -126,3 +126,27 @@ func TestCrmReplaceEntity(t *testing.T) { deleted, _ := crmDeleteEntity("Lead", id) AssertEqual(t, deleted, true, "test record should have been deleted.") } + +func TestSearchEntityByID(t *testing.T) { + + e := crmdLead{} + e.FirstName = "ff1" + time.Now().Format("2006-Jan-02 03:04:05") + e.LastName = "ll1" + e.Password = "pp" + e.Status = "New" + //e.EmailAddress = "abc@gmail.com" + e.WechatHitxyID = "someopenid" + b, _ := json.Marshal(e) + entity, err := crmCreateEntity("Lead", b) + if err != nil { + log.Println("--------------") + log.Println(err) + log.Println("--------------") + } + AssertEqual(t, err, nil, "create record should be successful") + AssertEqual(t, isErrIndicateDuplicate(err), false, "this should not be a duplicate error") + + id := entity.(crmdLead).ID + obj, err := crmFindEntityByID("Lead", id) + AssertEqual(t, obj.(crmdLead).ID, id, "we should found the right id") +} diff --git a/crmLead.go b/crmLead.go index de390c1..abb15db 100644 --- a/crmLead.go +++ b/crmLead.go @@ -62,7 +62,7 @@ type crmdLead struct { CreatedOpportunityID string `json:"createdOpportunityId,omitempty"` } -type crmSearchLead struct { +type crmdSearchLead struct { Total int `json:"total"` List []crmdLead `json:"list"` } @@ -135,7 +135,7 @@ func crmFindOpenID(openID string) (info crmdLead, found bool, err error) { defer r.Body.Close() b, _ := ioutil.ReadAll(r.Body) - search := crmSearchLead{} + search := crmdSearchLead{} err = json.Unmarshal(b, &search) if err != nil || search.Total <= 0 { diff --git a/crmLead_test.go b/crmLead_test.go index 7dc7a21..8271aa6 100644 --- a/crmLead_test.go +++ b/crmLead_test.go @@ -371,7 +371,7 @@ func TestSearchResult(t *testing.T) { } ] }` - r := crmSearchLead{} + r := crmdSearchLead{} err := json.Unmarshal([]byte(msg), &r) AssertEqual(t, err, nil, "") AssertEqual(t, r.Total, 2, "") @@ -383,7 +383,7 @@ func TestSearchResult(t *testing.T) { func TestSearchResultZero(t *testing.T) { msg := `{"total":0,"list":[]}` - r := crmSearchLead{} + r := crmdSearchLead{} err := json.Unmarshal([]byte(msg), &r) AssertEqual(t, err, nil, "") AssertEqual(t, r.Total, 0, "") diff --git a/sample_data/sample_crm_lead_query.json b/sample_data/sample_crm_lead_query.json index 0818cef..c33ef66 100644 --- a/sample_data/sample_crm_lead_query.json +++ b/sample_data/sample_crm_lead_query.json @@ -51,3 +51,343 @@ } + + +{ + "total": 8, + "list": [ + { + "id": "5955c2a5b87b2c0b6", + "name": "ff12017-Jun-30 01:16:53 ll1", + "deleted": false, + "salutationName": null, + "firstName": "ff12017-Jun-30 01:16:53", + "lastName": "ll1", + "title": null, + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": null, + "addressStreet": null, + "addressCity": null, + "addressState": null, + "addressCountry": null, + "addressPostalCode": null, + "emailAddress": null, + "phoneNumber": null, + "doNotCall": false, + "description": null, + "createdAt": "2017-06-30 03:16:53", + "modifiedAt": "2017-06-30 03:16:53", + "accountName": null, + "password": "pp", + "wechat_hitxy_id": "someopenid", + "verifier": null, + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "58ef420cac3cf6c95", + "createdByName": "wechat robot", + "modifiedById": null, + "modifiedByName": null, + "assignedUserId": null, + "assignedUserName": null, + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "5955c17173b9ccd0c", + "name": "ff12017-jan-30 01:11:45 ll1", + "deleted": false, + "salutationName": null, + "firstName": "ff12017-jan-30 01:11:45", + "lastName": "ll1", + "title": null, + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": null, + "addressStreet": null, + "addressCity": null, + "addressState": null, + "addressCountry": null, + "addressPostalCode": null, + "emailAddress": "abc@gmail.com", + "phoneNumber": null, + "doNotCall": false, + "description": null, + "createdAt": "2017-06-30 03:11:45", + "modifiedAt": "2017-06-30 03:11:45", + "accountName": null, + "password": "pp", + "wechat_hitxy_id": "someopenid", + "verifier": null, + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "58ef420cac3cf6c95", + "createdByName": "wechat robot", + "modifiedById": null, + "modifiedByName": null, + "assignedUserId": null, + "assignedUserName": null, + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "595071f8450974b72", + "name": " \u5218\u5efa\u660e", + "deleted": false, + "salutationName": null, + "firstName": " ", + "lastName": "\u5218\u5efa\u660e", + "title": null, + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": null, + "addressStreet": null, + "addressCity": null, + "addressState": null, + "addressCountry": null, + "addressPostalCode": null, + "emailAddress": null, + "phoneNumber": "dd", + "doNotCall": false, + "description": null, + "createdAt": "2017-06-26 02:31:20", + "modifiedAt": "2017-06-28 11:38:20", + "accountName": null, + "password": "password", + "wechat_hitxy_id": "oUN420Wj78vnkNeAJY7RMPXA28oc", + "verifier": null, + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "58ef420cac3cf6c95", + "createdByName": "wechat robot", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "594e41d005b46776f", + "name": "fisrt last", + "deleted": false, + "salutationName": "", + "firstName": "fisrt", + "lastName": "last", + "title": "", + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": "", + "addressStreet": "", + "addressCity": "", + "addressState": "", + "addressCountry": "", + "addressPostalCode": "", + "emailAddress": null, + "phoneNumber": null, + "doNotCall": false, + "description": "", + "createdAt": "2017-06-24 10:41:20", + "modifiedAt": "2017-06-26 02:32:11", + "accountName": "", + "password": "dir", + "wechat_hitxy_id": "dir", + "verifier": [], + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "1", + "createdByName": "Admin", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "5931a78193909a205", + "name": "name last", + "deleted": false, + "salutationName": "", + "firstName": "name", + "lastName": "last", + "title": "", + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": "", + "addressStreet": "", + "addressCity": "", + "addressState": "", + "addressCountry": "", + "addressPostalCode": "", + "emailAddress": null, + "phoneNumber": null, + "doNotCall": false, + "description": "", + "createdAt": "2017-06-02 17:59:29", + "modifiedAt": "2017-06-26 02:32:11", + "accountName": "", + "password": "123", + "wechat_hitxy_id": "weid", + "verifier": [], + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "58ef420cac3cf6c95", + "createdByName": "wechat robot", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "58f4aa0682ea74bb8", + "name": "same email", + "deleted": false, + "salutationName": "", + "firstName": "same", + "lastName": "email", + "title": "", + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": 120, + "website": "", + "addressStreet": "", + "addressCity": "", + "addressState": "", + "addressCountry": "", + "addressPostalCode": "", + "emailAddress": "test@gmail.com", + "phoneNumber": "456", + "doNotCall": true, + "description": "", + "createdAt": "2017-04-17 11:41:58", + "modifiedAt": "2017-06-26 02:32:11", + "accountName": "", + "password": "abcdefg", + "wechat_hitxy_id": "the user id obtained from wechat public account", + "verifier": [ + "231823091", + "adkdaifaskfsafsa", + "394kfdjafdsa", + "39410498321041" + ], + "opportunityAmountCurrency": "AUD", + "opportunityAmountConverted": 120, + "createdById": "1", + "createdByName": "Admin", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "58f4a849502da6f33", + "name": "not searchable", + "deleted": false, + "salutationName": "Mr.", + "firstName": "not", + "lastName": "searchable", + "title": "", + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": "", + "addressStreet": "", + "addressCity": "", + "addressState": "", + "addressCountry": "", + "addressPostalCode": "", + "emailAddress": null, + "phoneNumber": null, + "doNotCall": false, + "description": "", + "createdAt": "2017-04-17 11:34:33", + "modifiedAt": "2017-06-26 02:32:11", + "accountName": "", + "password": null, + "wechat_hitxy_id": "the user id obtained from wechat public account", + "verifier": [], + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "1", + "createdByName": "Admin", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + }, + { + "id": "58f08ccfe9692c29f", + "name": "test updated", + "deleted": false, + "salutationName": "Mr.", + "firstName": "test", + "lastName": "updated", + "title": "", + "status": "New", + "source": "", + "industry": "", + "opportunityAmount": null, + "website": "", + "addressStreet": "", + "addressCity": "", + "addressState": "", + "addressCountry": "", + "addressPostalCode": "", + "emailAddress": "test@gmail.com", + "phoneNumber": null, + "doNotCall": false, + "description": "", + "createdAt": "2017-04-14 08:48:15", + "modifiedAt": "2017-06-26 02:32:11", + "accountName": "", + "password": null, + "wechat_hitxy_id": "abce667598", + "verifier": null, + "opportunityAmountCurrency": null, + "opportunityAmountConverted": null, + "createdById": "58ef420cac3cf6c95", + "createdByName": "wechat robot", + "modifiedById": "1", + "modifiedByName": "Admin", + "assignedUserId": "1", + "assignedUserName": "Admin", + "campaignId": null, + "createdAccountId": null, + "createdContactId": null, + "createdOpportunityId": null + } + ] +} \ No newline at end of file diff --git a/upload.go b/upload.go index e967364..dbd0377 100644 --- a/upload.go +++ b/upload.go @@ -121,3 +121,11 @@ func debugDumpHTTPResponse(r *http.Response) { } fmt.Printf("dump http Response \n : %s", dump) } + +func debugDumpHTTPRequest(r *http.Request) { + dump, err := httputil.DumpRequest(r, true) + if err != nil { + log.Fatal(err) + } + fmt.Printf("dump http request : %q", dump) +}