english_report.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package services
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "hongze/hz_crm_api/models"
  7. "hongze/hz_crm_api/services/alarm_msg"
  8. "hongze/hz_crm_api/utils"
  9. "html"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. // IEnglishEmailSend 英文研报-邮件推送接口
  15. type IEnglishEmailSend interface {
  16. NewClient() (err error)
  17. SendEmail(item *EnglishReportSendEmailRequest) (ok bool, result string, err error)
  18. BatchSendEmail(list []*EnglishReportSendEmailRequest) (results []*EnglishReportSendEmailResult, err error)
  19. }
  20. // EnglishReportSendEmailRequest 英文研报-推送邮件请求体
  21. type EnglishReportSendEmailRequest struct {
  22. ReportId int `description:"英文报告ID"`
  23. EmailId int `description:"邮箱ID"`
  24. Email string `description:"邮箱地址"`
  25. Subject string `description:"邮件主题"`
  26. FromAlias string `description:"发信人昵称"`
  27. ReportTitle string `description:"报告标题"`
  28. ReportAbstract string `description:"报告摘要"`
  29. ReportContent string `description:"报告内容"`
  30. ReportShareLink string `description:"报告分享链接"`
  31. ReportTime string `description:"报告时间"`
  32. HtmlBody string `description:"模板内容主体"`
  33. }
  34. // EnglishReportSendEmailResult 英文研报-推送邮件响应体
  35. type EnglishReportSendEmailResult struct {
  36. ReportId int `description:"英文报告ID"`
  37. EmailId int `description:"邮箱ID"`
  38. Email string `description:"邮箱地址"`
  39. Ok bool `description:"是否推送成功"`
  40. SendData string `description:"请求数据-JSON"`
  41. ResultData string `description:"推送结果-JSON"`
  42. Source int `description:"服务来源:1-阿里云;2-腾讯云"`
  43. }
  44. // BatchSendAliEnglishReportEmail 批量推送英文研报邮件
  45. func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err error) {
  46. defer func() {
  47. if err != nil {
  48. go alarm_msg.SendAlarmMsg("阿里云群发英文研报邮件失败, Err: "+err.Error(), 3)
  49. }
  50. }()
  51. if len(list) == 0 {
  52. return
  53. }
  54. requestMap := make(map[int]*EnglishReportSendEmailRequest, 0)
  55. for i := range list {
  56. requestMap[list[i].EmailId] = list[i]
  57. }
  58. // 请求阿里云接口批量推送
  59. aliEmail := new(AliyunEmail)
  60. resultList, e := aliEmail.BatchSendEmail(list)
  61. if e != nil {
  62. err = e
  63. return
  64. }
  65. // 返回的结果更新日志
  66. resendList := make([]*EnglishReportSendEmailRequest, 0)
  67. failLogIds := make([]int, 0)
  68. updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"}
  69. for i := range resultList {
  70. var cond string
  71. var pars []interface{}
  72. cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?`
  73. pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceAli, models.EnglishReportEmailLogStatusIng)
  74. l, e := models.GetEnglishReportEmailLog(cond, pars)
  75. if e != nil {
  76. continue
  77. }
  78. l.SendData = resultList[i].SendData
  79. l.Result = resultList[i].ResultData
  80. if resultList[i].Ok {
  81. l.SendStatus = models.EnglishReportEmailLogStatusSuccess
  82. } else {
  83. l.SendStatus = models.EnglishReportEmailLogStatusFail
  84. failLogIds = append(failLogIds, l.Id)
  85. if requestMap[resultList[i].EmailId] != nil {
  86. resendList = append(resendList, requestMap[resultList[i].EmailId])
  87. }
  88. // 取出错误信息
  89. r := new(AliyunEmailResult)
  90. if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil {
  91. continue
  92. }
  93. rd := new(AliyunEmailResultData)
  94. res := strings.Replace(r.Data, `\`, ``, -1)
  95. if e = json.Unmarshal([]byte(res), &rd); e != nil {
  96. continue
  97. }
  98. l.ErrMsg = rd.Message
  99. }
  100. if e = l.Update(updateCols); e != nil {
  101. continue
  102. }
  103. }
  104. // 推送失败的重新腾讯云, 若腾讯云也失败将不再自动重推, 用户手动去重推
  105. if len(resendList) > 0 && len(failLogIds) > 0 {
  106. _ = ResendTencentEnglishReportEmail(resendList, failLogIds)
  107. }
  108. return
  109. }
  110. // ResendTencentEnglishReportEmail 腾讯云邮件重新推送
  111. func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest, failLogIds []int) (err error) {
  112. defer func() {
  113. if err != nil {
  114. go alarm_msg.SendAlarmMsg("腾讯云重发英文研报邮件失败, Err: "+err.Error(), 3)
  115. }
  116. }()
  117. if len(resendList) == 0 || len(failLogIds) == 0 {
  118. return
  119. }
  120. // 标记原有日志为已删除
  121. if len(failLogIds) > 0 {
  122. if e := models.DeleteEnglishReportEmailLogByIds(failLogIds); e != nil {
  123. err = errors.New("删除原邮件日志失败, Err: " + e.Error())
  124. return
  125. }
  126. }
  127. // 写入新的日志
  128. nowTime := time.Now().Local()
  129. logData := make([]*models.EnglishReportEmailLog, 0)
  130. for i := range resendList {
  131. sendByte, e := json.Marshal(resendList[i])
  132. if e != nil {
  133. err = errors.New("sendByte json.Marshal Err, Err: " + e.Error())
  134. return
  135. }
  136. logData = append(logData, &models.EnglishReportEmailLog{
  137. ReportId: resendList[i].ReportId,
  138. EmailId: resendList[i].EmailId,
  139. Email: resendList[i].Email,
  140. SendData: string(sendByte),
  141. Source: models.EnglishReportEmailLogSourceTencent,
  142. SendStatus: models.EnglishReportEmailLogStatusIng,
  143. CreateTime: nowTime,
  144. })
  145. }
  146. emailLog := new(models.EnglishReportEmailLog)
  147. if e := emailLog.InsertMulti(logData); e != nil {
  148. err = errors.New("批量写入群发邮件日志失败, Err: " + e.Error())
  149. return
  150. }
  151. // 请求腾讯云
  152. tecentEmail := new(TencentEmail)
  153. resultList, e := tecentEmail.BatchSendEmail(resendList)
  154. if e != nil {
  155. err = e
  156. return
  157. }
  158. updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"}
  159. for i := range resultList {
  160. var cond string
  161. var pars []interface{}
  162. cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?`
  163. pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceTencent, models.EnglishReportEmailLogStatusIng)
  164. l, e := models.GetEnglishReportEmailLog(cond, pars)
  165. if e != nil {
  166. continue
  167. }
  168. l.SendData = resultList[i].SendData
  169. l.Result = resultList[i].ResultData
  170. if resultList[i].Ok {
  171. l.SendStatus = models.EnglishReportEmailLogStatusSuccess
  172. } else {
  173. l.SendStatus = models.EnglishReportEmailLogStatusFail
  174. r := new(TencentEmailResult)
  175. if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil {
  176. continue
  177. }
  178. l.ErrMsg = r.Message
  179. }
  180. if e = l.Update(updateCols); e != nil {
  181. continue
  182. }
  183. }
  184. return
  185. }
  186. // UpdateEnglishVideoEs 更新英文线上路演Es
  187. func UpdateEnglishVideoEs(videoId int, publishState int) (err error) {
  188. if videoId <= 0 {
  189. return
  190. }
  191. videoInfo, err := models.GetEnglishVideoById(videoId)
  192. if err != nil {
  193. return
  194. }
  195. // 新增报告ES
  196. esReport := &models.ElasticEnglishReportDetail{
  197. Id: "v" + strconv.Itoa(videoInfo.Id),
  198. VideoId: videoInfo.Id,
  199. Title: videoInfo.Title,
  200. Abstract: videoInfo.Abstract,
  201. BodyContent: "",
  202. PublishTime: videoInfo.PublishTime,
  203. CreateTime: videoInfo.CreateTime,
  204. ReportCode: videoInfo.VideoCode,
  205. PublishState: publishState,
  206. Author: videoInfo.Author,
  207. Frequency: "",
  208. ClassifyIdFirst: videoInfo.ClassifyIdFirst,
  209. ClassifyNameFirst: videoInfo.ClassifyNameFirst,
  210. ClassifyIdSecond: videoInfo.ClassifyIdSecond,
  211. ClassifyNameSecond: videoInfo.ClassifyNameSecond,
  212. StageStr: "",
  213. Overview: utils.TrimHtml(html.UnescapeString(videoInfo.Overview)),
  214. ContentSub: "",
  215. }
  216. docId := fmt.Sprintf("v%d", videoInfo.Id)
  217. if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil {
  218. return
  219. }
  220. return
  221. }
  222. // UpdateEnglishCompanyEnabledByCompanyId 根据英文客户ID更新状态
  223. func UpdateEnglishCompanyEnabledByCompanyId(companyId int) (err error) {
  224. defer func() {
  225. if err != nil {
  226. alarm_msg.SendAlarmMsg(fmt.Sprintf("更新英文客户状态失败, Err: %s", err.Error()), 3)
  227. }
  228. }()
  229. // 获取客户
  230. comp, e := models.GetEnglishCompanyById(companyId)
  231. if e != nil {
  232. err = fmt.Errorf("英文客户已被删除")
  233. return
  234. }
  235. // 获取联系人
  236. emailCond := ` AND company_id = ?`
  237. emailPars := make([]interface{}, 0)
  238. emailPars = append(emailPars, companyId)
  239. emailList, e := models.GetEnglishReportEmailList(emailCond, emailPars, "")
  240. if e != nil {
  241. err = fmt.Errorf("获取英文联系人列表失败, Err: %s", e.Error())
  242. return
  243. }
  244. // 无联系人, 保持原状态
  245. total := len(emailList)
  246. if total == 0 {
  247. return
  248. }
  249. // 判断状态, 是否部分禁用
  250. status := 0
  251. enabledCount := 0
  252. for _, v := range emailList {
  253. if v.Enabled == 1 {
  254. enabledCount += 1
  255. }
  256. }
  257. if enabledCount == 0 {
  258. status = models.EnglishCompanyDisabled
  259. }
  260. if total == enabledCount {
  261. status = models.EnglishCompanyEnabled
  262. }
  263. if total > enabledCount && enabledCount != 0 {
  264. status = models.EnglishCompanyHalfEnabled
  265. }
  266. // 是否需要更新
  267. if comp.Enabled == status {
  268. return
  269. }
  270. comp.Enabled = status
  271. comp.ModifyTime = time.Now().Local()
  272. if e = comp.Update([]string{"Enabled", "ModifyTime"}); e != nil {
  273. err = fmt.Errorf("更新客户状态失败, Err: %s", e.Error())
  274. return
  275. }
  276. return
  277. }