您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

236 行
5.5KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "strings"
  9. )
  10. //abstract CRUD operation for espoCRM Entity
  11. func crmCreateEntity(entityType string, jsonB []byte) (entity interface{}, err error) {
  12. url := CRMConfig.apiURL(entityType)
  13. jsonStr, err := postRAW(jsonB, url, crmBuildCommonAPIHeader())
  14. if err != nil {
  15. entity, _ = crmRescueDuplicateCreate(err, entityType)
  16. return
  17. }
  18. return crmJSON2Entity(entityType, jsonStr)
  19. }
  20. func crmUpdateEntity(entityType string, id string, jsonB []byte) (entity interface{}, err error) {
  21. url := CRMConfig.apiEntityURL(entityType, id)
  22. jsonStr, err := patchRAW(jsonB, url, crmBuildCommonAPIHeader())
  23. if err != nil {
  24. log.Println(err)
  25. return
  26. }
  27. return crmJSON2Entity(entityType, jsonStr)
  28. }
  29. func crmReplaceEntity(entityType string, id string, jsonB []byte) (entity interface{}, err error) {
  30. url := CRMConfig.apiEntityURL(entityType, id)
  31. jsonStr, err := putRAW(jsonB, url, crmBuildCommonAPIHeader())
  32. if err != nil {
  33. log.Println(err)
  34. return
  35. }
  36. return crmJSON2Entity(entityType, jsonStr)
  37. }
  38. func crmDeleteEntity(entityType string, id string) (deleted bool, err error) {
  39. url := CRMConfig.apiEntityURL(entityType, id)
  40. resp, err := deleteRAW(url, crmBuildCommonAPIHeader())
  41. if err != nil {
  42. log.Println(err)
  43. return
  44. }
  45. deleted = strings.ToLower(resp) == "true"
  46. return
  47. }
  48. //give an id, return json
  49. func crmGetEntity(entityType string, id string) (entity interface{}, err error) {
  50. url := CRMConfig.apiEntityURL(entityType, id)
  51. jsonStr, err := getRAW(url, crmBuildCommonAPIHeader())
  52. if err != nil {
  53. log.Println(err)
  54. return
  55. }
  56. return crmJSON2Entity(entityType, jsonStr)
  57. }
  58. func crmBuildCommonAPIHeader() (headers map[string]string) {
  59. headers = map[string]string{}
  60. headers["Authorization"] = crmAuthHeader()
  61. headers["Accept"] = "application/json"
  62. headers["Content-Type"] = "application/json"
  63. return headers
  64. }
  65. //given a json string, convert it to Typed structure
  66. func crmJSON2Entity(entityType string, data string) (r interface{}, err error) {
  67. switch entityType {
  68. case "Lead":
  69. e := crmdLead{}
  70. err = json.Unmarshal([]byte(data), &e)
  71. r = e
  72. case "Account":
  73. //r = crmdAccount{}
  74. case "Contact":
  75. e := crmdContact{}
  76. err = json.Unmarshal([]byte(data), &e)
  77. r = e
  78. default:
  79. log.Fatalf("crmJSON2Entity: Unknown EntityType %s", entityType)
  80. }
  81. if err != nil {
  82. log.Println(err)
  83. }
  84. return
  85. }
  86. func crmRescueDuplicateCreate(e error, entityType string) (entity interface{}, success bool) {
  87. if !isErrIndicateDuplicate(e) {
  88. return
  89. }
  90. entity, err := e.(errorHTTPResponse).XStatusReason().Data2Entity(entityType)
  91. success = err == nil
  92. return
  93. }
  94. func isErrIndicateDuplicate(e error) (yes bool) {
  95. err, isOurError := e.(errorHTTPResponse)
  96. if !isOurError {
  97. return
  98. }
  99. reason := err.XStatusReason()
  100. yes = strings.ToLower(reason.Reason) == "duplicate"
  101. return
  102. }
  103. type crmdSearchFilter struct {
  104. Attribute string
  105. CompareMethod string //startWith, equals, contains, endsWith, like, isNull, isNotNull , notEquals
  106. ExpectValue string
  107. }
  108. type crmdSearchResult struct {
  109. Total int `json:"total"`
  110. List *json.RawMessage `json:"list"`
  111. }
  112. func crmSearchEntity(entityType string, filters []crmdSearchFilter) (result crmdSearchResult, err error) {
  113. url := CRMConfig.apiURL(entityType)
  114. req, err := http.NewRequest("GET", url, nil)
  115. if err != nil {
  116. log.Println("crmGetRecord: cannot form good http Request")
  117. log.Print(err)
  118. return
  119. }
  120. //auth header
  121. req.Header.Set("Authorization", crmAuthHeader())
  122. req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01")
  123. req.Header.Set("Content-Type", "application/json")
  124. //query string
  125. q := req.URL.Query()
  126. q.Add("maxSize", "20")
  127. q.Add("maxSize", "0")
  128. q.Add("sortBy", "createdAt")
  129. q.Add("asc", "false")
  130. for k, v := range filters {
  131. switch v.CompareMethod {
  132. case "startWith", "equals", "contains", "endsWith", "like", "notEquals":
  133. q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod)
  134. q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute)
  135. q.Add(fmt.Sprintf("where[%d][value]", k), v.ExpectValue)
  136. case "isNull", "isNotNull":
  137. q.Add(fmt.Sprintf("where[%d][type]", k), v.CompareMethod)
  138. q.Add(fmt.Sprintf("where[%d][attribute]", k), v.Attribute)
  139. default:
  140. log.Printf("Unknown Compare Method %s", v.CompareMethod)
  141. }
  142. }
  143. req.URL.RawQuery = q.Encode()
  144. //debugDumpHTTPRequest(req)
  145. client := &http.Client{}
  146. r, err := client.Do(req)
  147. //debugDumpHTTPResponse(r)
  148. if err != nil {
  149. return
  150. }
  151. defer r.Body.Close()
  152. jsonB, err := ioutil.ReadAll(r.Body)
  153. if err != nil {
  154. return
  155. }
  156. err = json.Unmarshal(jsonB, &result)
  157. return
  158. }
  159. func crmFindEntityByID(entityType string, id string) (entity interface{}, err error) {
  160. filters := []crmdSearchFilter{
  161. {"id", "equals", id},
  162. }
  163. cs, err := crmSearchEntity(entityType, filters)
  164. if err != nil || cs.Total < 1 {
  165. return
  166. }
  167. if cs.Total > 1 {
  168. log.Printf("ERROR: more than one(%d) %s associated with %s", cs.Total, entityType, id)
  169. }
  170. switch entityType {
  171. case "Lead":
  172. e := []crmdLead{}
  173. err = json.Unmarshal(*cs.List, &e)
  174. if (err != nil) || (len(e) != cs.Total) {
  175. return
  176. }
  177. entity = e[0]
  178. case "Account":
  179. return
  180. }
  181. return
  182. }
  183. func crmFindEntityByAttr(entityType, attribute, value string) (total int, list interface{}, err error) {
  184. filters := []crmdSearchFilter{
  185. {attribute, "equals", value},
  186. }
  187. cs, err := crmSearchEntity(entityType, filters)
  188. if err != nil || cs.Total < 1 {
  189. return
  190. }
  191. total = cs.Total
  192. switch entityType {
  193. case "Lead":
  194. e := []crmdLead{}
  195. err = json.Unmarshal(*cs.List, &e)
  196. list = e
  197. case "Account":
  198. return
  199. }
  200. return
  201. }