english_report.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. package services
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_api/models"
  6. "eta/eta_api/models/system"
  7. "eta/eta_api/services/alarm_msg"
  8. "eta/eta_api/utils"
  9. "fmt"
  10. "html"
  11. "strconv"
  12. "strings"
  13. "time"
  14. )
  15. // CreateNewEnglishReport 生成英文研报
  16. func CreateNewEnglishReport(req models.AddEnglishReportReq, adminInfo *system.Admin) (newReportId int64, reportCode string, err error) {
  17. var contentSub string
  18. if req.Content != "" {
  19. content, e := FilterReportContentBr(req.Content)
  20. if e != nil {
  21. err = errors.New("内容去除前后空格失败, Err: " + e.Error())
  22. return
  23. }
  24. req.Content = content
  25. contentSub, e = GetReportContentSub(req.Content)
  26. if e != nil {
  27. go alarm_msg.SendAlarmMsg("ContentSub 失败,Err:"+e.Error(), 3)
  28. err = errors.New("获取报告内容前几段失败, Err: " + e.Error())
  29. return
  30. }
  31. }
  32. maxStage, e := models.GetEnglishReportStage(req.ClassifyIdFirst, req.ClassifyIdSecond)
  33. if e != nil {
  34. err = errors.New("期数获取失败, Err: " + e.Error())
  35. return
  36. }
  37. item := new(models.EnglishReport)
  38. item.AddType = req.AddType
  39. item.ClassifyIdFirst = req.ClassifyIdFirst
  40. item.ClassifyNameFirst = req.ClassifyNameFirst
  41. item.ClassifyIdSecond = req.ClassifyIdSecond
  42. item.ClassifyNameSecond = req.ClassifyNameSecond
  43. item.Title = req.Title
  44. item.Abstract = req.Abstract
  45. item.Author = req.Author
  46. item.Frequency = req.Frequency
  47. item.State = req.State
  48. item.Content = html.EscapeString(req.Content)
  49. item.Stage = maxStage + 1
  50. item.ContentSub = html.EscapeString(contentSub)
  51. item.CreateTime = req.CreateTime
  52. item.ModifyTime = time.Now()
  53. item.AdminId = adminInfo.AdminId
  54. item.AdminRealName = adminInfo.RealName
  55. newReportId, e = models.AddEnglishReport(item)
  56. if e != nil {
  57. err = errors.New("新增报告失败, Err: " + e.Error())
  58. return
  59. }
  60. reportCode = utils.MD5(strconv.Itoa(int(newReportId)))
  61. //修改唯一编码
  62. {
  63. go models.ModifyEnglishReportCode(newReportId, reportCode)
  64. }
  65. return
  66. }
  67. // IEnglishEmailSend 英文研报-邮件推送接口
  68. type IEnglishEmailSend interface {
  69. NewClient() (err error)
  70. SendEmail(item *EnglishReportSendEmailRequest) (ok bool, result string, err error)
  71. BatchSendEmail(list []*EnglishReportSendEmailRequest) (results []*EnglishReportSendEmailResult, err error)
  72. }
  73. // EnglishReportSendEmailRequest 英文研报-推送邮件请求体
  74. type EnglishReportSendEmailRequest struct {
  75. ReportId int `description:"英文报告ID"`
  76. EmailId int `description:"邮箱ID"`
  77. Email string `description:"邮箱地址"`
  78. Subject string `description:"邮件主题"`
  79. FromAlias string `description:"发信人昵称"`
  80. ReportTitle string `description:"报告标题"`
  81. ReportAbstract string `description:"报告摘要"`
  82. ReportContent string `description:"报告内容"`
  83. ReportShareLink string `description:"报告分享链接"`
  84. ReportTime string `description:"报告时间"`
  85. HtmlBody string `description:"模板内容主体"`
  86. EmailLog *models.EnglishReportEmailLog `description:"日志记录"`
  87. }
  88. // EnglishReportSendEmailResult 英文研报-推送邮件响应体
  89. type EnglishReportSendEmailResult struct {
  90. ReportId int `description:"英文报告ID"`
  91. EmailId int `description:"邮箱ID"`
  92. Email string `description:"邮箱地址"`
  93. Ok bool `description:"是否推送成功"`
  94. SendData string `description:"请求数据-JSON"`
  95. ResultData string `description:"推送结果-JSON"`
  96. Source int `description:"服务来源:1-阿里云;2-腾讯云"`
  97. }
  98. // BatchSendAliEnglishReportEmail 批量推送英文研报邮件
  99. func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err error) {
  100. defer func() {
  101. if err != nil {
  102. tips := fmt.Sprintf("阿里云群发英文研报邮件失败 err: %s\n", err.Error())
  103. utils.FileLog.Info(tips)
  104. fmt.Println(tips)
  105. go alarm_msg.SendAlarmMsg(tips, 3)
  106. }
  107. }()
  108. if len(list) == 0 {
  109. return
  110. }
  111. requestMap := make(map[int]*EnglishReportSendEmailRequest, 0)
  112. for _, v := range list {
  113. requestMap[v.EmailId] = v
  114. }
  115. // 请求阿里云接口批量推送
  116. aliEmail := new(AliyunEmail)
  117. resultList, e := aliEmail.BatchSendEmail(list)
  118. if e != nil {
  119. err = e
  120. return
  121. }
  122. // 返回的结果更新日志
  123. resendList := make([]*EnglishReportSendEmailRequest, 0)
  124. failLogIds := make([]int, 0)
  125. updateLogs := make([]*models.EnglishReportEmailLog, 0)
  126. for _, v := range resultList {
  127. req := requestMap[v.EmailId]
  128. if req == nil {
  129. continue
  130. }
  131. l := req.EmailLog
  132. if l == nil {
  133. continue
  134. }
  135. //l.SendData = v.SendData
  136. l.Result = v.ResultData
  137. if v.Ok {
  138. l.SendStatus = models.EnglishReportEmailLogStatusSuccess
  139. } else {
  140. l.SendStatus = models.EnglishReportEmailLogStatusFail
  141. failLogIds = append(failLogIds, l.Id)
  142. if requestMap[v.EmailId] != nil {
  143. resendList = append(resendList, requestMap[v.EmailId])
  144. }
  145. // 取出错误信息
  146. r := new(AliyunEmailResult)
  147. if e = json.Unmarshal([]byte(v.ResultData), &r); e != nil {
  148. continue
  149. }
  150. rd := new(AliyunEmailResultData)
  151. res := strings.Replace(r.Data, `\`, ``, -1)
  152. if e = json.Unmarshal([]byte(res), &rd); e != nil {
  153. continue
  154. }
  155. l.ErrMsg = rd.Message
  156. }
  157. updateLogs = append(updateLogs, l)
  158. }
  159. // 更新日志
  160. logOb := new(models.EnglishReportEmailLog)
  161. if e = logOb.MultiUpdateResult(updateLogs); e != nil {
  162. err = fmt.Errorf("批量更新日志信息失败, Err: " + e.Error())
  163. return
  164. }
  165. // 推送失败的重新腾讯云, 若腾讯云也失败将不再自动重推, 用户手动去重推
  166. if len(resendList) > 0 && len(failLogIds) > 0 {
  167. hasFail, _ := ResendTencentEnglishReportEmail(resendList, failLogIds)
  168. //fmt.Printf("hasFail: %v", hasFail)
  169. // 存在发送失败则更新报告标识
  170. if hasFail {
  171. if e = models.UpdateEnglishReportEmailHasFail(list[0].ReportId); e != nil {
  172. err = fmt.Errorf("UpdateEnglishReportEmailHasFail err: %s", e.Error())
  173. return
  174. }
  175. }
  176. }
  177. return
  178. }
  179. // ResendTencentEnglishReportEmail 腾讯云邮件重新推送
  180. func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest, failLogIds []int) (hasFail bool, err error) {
  181. defer func() {
  182. if err != nil {
  183. hasFail = true
  184. tips := fmt.Sprintf("腾讯云重发英文研报邮件失败 err: %s\n", err.Error())
  185. utils.FileLog.Info(tips)
  186. fmt.Println(tips)
  187. go alarm_msg.SendAlarmMsg(tips, 3)
  188. }
  189. }()
  190. if len(resendList) == 0 || len(failLogIds) == 0 {
  191. return
  192. }
  193. // 标记原有日志为已删除
  194. if len(failLogIds) > 0 {
  195. if e := models.DeleteEnglishReportEmailLogByIds(failLogIds); e != nil {
  196. err = errors.New("删除原邮件日志失败, Err: " + e.Error())
  197. return
  198. }
  199. }
  200. // 写入新的日志
  201. nowTime := time.Now().Local()
  202. logData := make([]*models.EnglishReportEmailLog, 0)
  203. logMap := make(map[int]*models.EnglishReportEmailLog, 0)
  204. for _, v := range resendList {
  205. logItem := &models.EnglishReportEmailLog{
  206. ReportId: v.ReportId,
  207. EmailId: v.EmailId,
  208. Email: v.Email,
  209. Source: models.EnglishReportEmailLogSourceTencent,
  210. SendStatus: models.EnglishReportEmailLogStatusIng,
  211. CreateTime: nowTime,
  212. }
  213. logData = append(logData, logItem)
  214. logMap[v.EmailId] = logItem
  215. }
  216. for _, v := range logData {
  217. if e := v.Create(); e != nil {
  218. err = fmt.Errorf("写入群发邮件日志失败, err: %s", e.Error())
  219. return
  220. }
  221. }
  222. // 请求腾讯云
  223. tencentEmail := new(TencentEmail)
  224. resultList, e := tencentEmail.BatchSendEmail(resendList)
  225. if e != nil {
  226. err = e
  227. return
  228. }
  229. updateLogs := make([]*models.EnglishReportEmailLog, 0)
  230. for _, v := range resultList {
  231. l := logMap[v.EmailId]
  232. if l == nil {
  233. continue
  234. }
  235. l.Result = v.ResultData
  236. if v.Ok {
  237. l.SendStatus = models.EnglishReportEmailLogStatusSuccess
  238. } else {
  239. l.SendStatus = models.EnglishReportEmailLogStatusFail
  240. r := new(TencentEmailResult)
  241. if e = json.Unmarshal([]byte(v.ResultData), &r); e != nil {
  242. continue
  243. }
  244. l.ErrMsg = r.Message
  245. hasFail = true
  246. }
  247. updateLogs = append(updateLogs, l)
  248. }
  249. // 更新日志
  250. logOb := new(models.EnglishReportEmailLog)
  251. if e = logOb.MultiUpdateResult(updateLogs); e != nil {
  252. err = fmt.Errorf("批量更新日志信息失败, Err: " + e.Error())
  253. return
  254. }
  255. return
  256. }
  257. // UpdateEnglishReportEs 更新英文报告/章节Es
  258. func UpdateEnglishReportEs(reportId int, publishState int) (err error) {
  259. if reportId <= 0 {
  260. return
  261. }
  262. reportInfo, err := models.GetEnglishReportById(reportId)
  263. if err != nil {
  264. return
  265. }
  266. // 新增报告ES
  267. esReport := &models.ElasticEnglishReportDetail{
  268. Id: strconv.Itoa(reportInfo.Id),
  269. ReportId: reportInfo.Id,
  270. Title: reportInfo.Title,
  271. Abstract: reportInfo.Abstract,
  272. BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)),
  273. PublishTime: reportInfo.PublishTime,
  274. CreateTime: reportInfo.CreateTime,
  275. ReportCode: reportInfo.ReportCode,
  276. PublishState: publishState,
  277. Author: reportInfo.Author,
  278. Frequency: reportInfo.Frequency,
  279. ClassifyIdFirst: reportInfo.ClassifyIdFirst,
  280. ClassifyNameFirst: reportInfo.ClassifyNameFirst,
  281. ClassifyIdSecond: reportInfo.ClassifyIdSecond,
  282. ClassifyNameSecond: reportInfo.ClassifyNameSecond,
  283. StageStr: strconv.Itoa(reportInfo.Stage),
  284. Overview: utils.TrimHtml(html.UnescapeString(reportInfo.Overview)),
  285. ContentSub: utils.TrimHtml(html.UnescapeString(reportInfo.ContentSub)),
  286. }
  287. docId := fmt.Sprintf("%d", reportInfo.Id)
  288. if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil {
  289. return
  290. }
  291. return
  292. }
  293. // ModifyAllEsEnglishReportVideo 批量修改es里的英文研报信息和线上路演信息
  294. func ModifyAllEsEnglishReportVideo() (err error) {
  295. reportList, err := models.GetEnglishReportByCondition("", []interface{}{})
  296. if err != nil {
  297. return
  298. }
  299. for _, reportInfo := range reportList {
  300. // 新增报告ES
  301. esReport := &models.ElasticEnglishReportDetail{
  302. Id: strconv.Itoa(reportInfo.Id),
  303. ReportId: reportInfo.Id,
  304. Title: reportInfo.Title,
  305. Abstract: reportInfo.Abstract,
  306. BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)),
  307. PublishTime: reportInfo.PublishTime.Format(utils.FormatDateTime),
  308. CreateTime: reportInfo.CreateTime,
  309. ReportCode: reportInfo.ReportCode,
  310. PublishState: reportInfo.State,
  311. Author: reportInfo.Author,
  312. Frequency: reportInfo.Frequency,
  313. ClassifyIdFirst: reportInfo.ClassifyIdFirst,
  314. ClassifyNameFirst: reportInfo.ClassifyNameFirst,
  315. ClassifyIdSecond: reportInfo.ClassifyIdSecond,
  316. ClassifyNameSecond: reportInfo.ClassifyNameSecond,
  317. StageStr: strconv.Itoa(reportInfo.Stage),
  318. Overview: utils.TrimHtml(html.UnescapeString(reportInfo.Overview)),
  319. ContentSub: utils.TrimHtml(html.UnescapeString(reportInfo.ContentSub)),
  320. }
  321. docId := fmt.Sprintf("%d", reportInfo.Id)
  322. if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil {
  323. return
  324. }
  325. }
  326. videoList, err := models.GetEnglishVideoByCondition("", []interface{}{})
  327. if err != nil {
  328. return
  329. }
  330. for _, videoInfo := range videoList {
  331. // 新增报告ES
  332. esReport := &models.ElasticEnglishReportDetail{
  333. Id: "v" + strconv.Itoa(videoInfo.Id),
  334. VideoId: videoInfo.Id,
  335. Title: videoInfo.Title,
  336. Abstract: videoInfo.Abstract,
  337. BodyContent: "",
  338. PublishTime: videoInfo.PublishTime.Format(utils.FormatDateTime),
  339. CreateTime: videoInfo.CreateTime.Format(utils.FormatDateTime),
  340. ReportCode: videoInfo.VideoCode,
  341. PublishState: videoInfo.State,
  342. Author: videoInfo.Author,
  343. Frequency: "",
  344. ClassifyIdFirst: videoInfo.ClassifyIdFirst,
  345. ClassifyNameFirst: videoInfo.ClassifyNameFirst,
  346. ClassifyIdSecond: videoInfo.ClassifyIdSecond,
  347. ClassifyNameSecond: videoInfo.ClassifyNameSecond,
  348. StageStr: "",
  349. Overview: utils.TrimHtml(html.UnescapeString(videoInfo.Overview)),
  350. ContentSub: "",
  351. }
  352. docId := fmt.Sprintf("v%d", videoInfo.Id)
  353. if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil {
  354. return
  355. }
  356. }
  357. return
  358. }
  359. // UpdateEnglishVideoEs 更新英文线上路演Es
  360. func UpdateEnglishVideoEs(videoId int, publishState int) (err error) {
  361. if videoId <= 0 {
  362. return
  363. }
  364. videoInfo, err := models.GetEnglishVideoById(videoId)
  365. if err != nil {
  366. return
  367. }
  368. // 新增报告ES
  369. esReport := &models.ElasticEnglishReportDetail{
  370. Id: "v" + strconv.Itoa(videoInfo.Id),
  371. VideoId: videoInfo.Id,
  372. Title: videoInfo.Title,
  373. Abstract: videoInfo.Abstract,
  374. BodyContent: "",
  375. PublishTime: videoInfo.PublishTime,
  376. CreateTime: videoInfo.CreateTime,
  377. ReportCode: videoInfo.VideoCode,
  378. PublishState: publishState,
  379. Author: videoInfo.Author,
  380. Frequency: "",
  381. ClassifyIdFirst: videoInfo.ClassifyIdFirst,
  382. ClassifyNameFirst: videoInfo.ClassifyNameFirst,
  383. ClassifyIdSecond: videoInfo.ClassifyIdSecond,
  384. ClassifyNameSecond: videoInfo.ClassifyNameSecond,
  385. StageStr: "",
  386. Overview: utils.TrimHtml(html.UnescapeString(videoInfo.Overview)),
  387. ContentSub: "",
  388. }
  389. docId := fmt.Sprintf("v%d", videoInfo.Id)
  390. if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil {
  391. return
  392. }
  393. return
  394. }
  395. func UpdateEnglishReportClassifyId(oldItem, newItem *models.EnglishClassify, classifyId int) (err error) {
  396. defer func() {
  397. if err != nil {
  398. go alarm_msg.SendAlarmMsg("英文报告分类改名-同步更新报告表字段及权限表关键词失败3, Err:"+err.Error(), 3)
  399. }
  400. }()
  401. //如果二级分类变更为一级分类
  402. //如果二级分类更换了父级分类,则更新报告中的父级分类ID
  403. //如果一级分类更换了名称,则更新所有报告中的一级分类名称
  404. //如果二级分类更换了名称,则更新所有报告中的二级分类名称
  405. if oldItem.ParentId > 0 && oldItem.ParentId != newItem.ParentId {
  406. //二级分类下的三级分类如果有报告,则该二级分类不允许改成一级分类
  407. if oldItem.ParentId > 0 && oldItem.ParentId == oldItem.RootId {
  408. if newItem.ParentId == 0 {
  409. // 更新报告表分类字段
  410. var condition string
  411. var pars []interface{}
  412. condition += ` AND classify_id_first = ? `
  413. pars = append(pars, classifyId)
  414. count, e := models.GetEnglishReportCountByCondition(condition, pars)
  415. if e != nil {
  416. err = e
  417. return
  418. }
  419. if count > 0 {
  420. err = fmt.Errorf("该分类有关联的报告,不允许变更为一级分类")
  421. return
  422. }
  423. }
  424. } else if oldItem.ParentId > 0 && oldItem.ParentId != oldItem.RootId {
  425. //三级分类下如果有报告,则该三级分类不允许改成二级或或者一级分类
  426. if (newItem.ParentId > 0 && newItem.ParentId == newItem.RootId) || newItem.ParentId == 0 {
  427. // 更新报告表分类字段
  428. var condition string
  429. var pars []interface{}
  430. condition += ` AND classify_id_second = ? `
  431. pars = append(pars, classifyId)
  432. count, e := models.GetEnglishReportCountByCondition(condition, pars)
  433. if e != nil {
  434. err = e
  435. return
  436. }
  437. if count > 0 {
  438. err = fmt.Errorf("该分类有关联的报告,不允许变更为二级分类或者一级分类")
  439. return
  440. }
  441. }
  442. }
  443. }
  444. return
  445. }
  446. func UpdateEnglishVideoClassifyId(oldItem, newItem *models.EnglishClassify, classifyId int) (err error) {
  447. //一级分类改为二级分类
  448. defer func() {
  449. if err != nil {
  450. go alarm_msg.SendAlarmMsg("英文报告分类改名-同步更新报告表字段及权限表关键词失败3, Err:"+err.Error(), 3)
  451. }
  452. }()
  453. //如果二级分类变更为一级分类
  454. //如果二级分类更换了父级分类,则更新报告中的父级分类ID
  455. //如果一级分类更换了名称,则更新所有报告中的一级分类名称
  456. //如果二级分类更换了名称,则更新所有报告中的二级分类名称
  457. if oldItem.ParentId > 0 && oldItem.ParentId != newItem.ParentId {
  458. //二级分类下的三级分类如果有报告,则该二级分类不允许改成一级分类
  459. if oldItem.ParentId > 0 && oldItem.ParentId == oldItem.RootId {
  460. if newItem.ParentId == 0 {
  461. // 更新报告表分类字段
  462. var condition string
  463. var pars []interface{}
  464. condition += ` AND classify_id_first = ? `
  465. pars = append(pars, classifyId)
  466. count, e := models.GetEnglishVideoListCount(condition, pars)
  467. if e != nil {
  468. err = e
  469. return
  470. }
  471. if count > 0 {
  472. err = fmt.Errorf("该分类有关联的视频,不允许变更为一级分类")
  473. return
  474. }
  475. }
  476. } else if oldItem.ParentId > 0 && oldItem.ParentId != oldItem.RootId {
  477. //三级分类下如果有报告,则该三级分类不允许改成二级或或者一级分类
  478. if (newItem.ParentId > 0 && newItem.ParentId == newItem.RootId) || newItem.ParentId == 0 {
  479. // 更新报告表分类字段
  480. var condition string
  481. var pars []interface{}
  482. condition += ` AND classify_id_second = ? `
  483. pars = append(pars, classifyId)
  484. count, e := models.GetEnglishVideoListCount(condition, pars)
  485. if e != nil {
  486. err = e
  487. return
  488. }
  489. if count > 0 {
  490. err = fmt.Errorf("该分类有关联的视频,不允许变更为二级分类或者一级分类")
  491. return
  492. }
  493. }
  494. }
  495. }
  496. return
  497. }
  498. // UpdateAllPublishedEnglishReportToEs 更新所有已发布的报告ES
  499. func UpdateAllPublishedEnglishReportToEs() (err error) {
  500. // 获取所有已发布的报告
  501. var condition string
  502. var pars []interface{}
  503. condition = ` AND state IN (2, 6) `
  504. reportList, err := models.GetEnglishReportByCondition(condition, pars)
  505. count := 0
  506. failCount := 0
  507. for i := 0; i < len(reportList); i++ {
  508. if err = UpdateEnglishReportEs(reportList[i].Id, 2); err != nil {
  509. fmt.Printf("更新失败, report_id: %d, Err: %s\n", reportList[i].Id, err.Error())
  510. failCount += 1
  511. } else {
  512. count += 1
  513. }
  514. }
  515. fmt.Printf("报告总数:%d, 更新成功数: %d, 更新失败数: %d", len(reportList), count, failCount)
  516. return
  517. }
  518. func CreateEnglishReportIndex() {
  519. indexName := utils.EsEnglishReportIndexName
  520. mappingJson := `{
  521. "mappings": {
  522. "dynamic": true,
  523. "properties": {
  524. "Frequency" : {
  525. "type" : "text"
  526. },
  527. "ReportCode" : {
  528. "type" : "text"
  529. },
  530. "Author" : {
  531. "type" : "text",
  532. "fields" : {
  533. "keyword" : {
  534. "type" : "keyword",
  535. "ignore_above" : 256
  536. }
  537. }
  538. },
  539. "BodyContent" : {
  540. "type" : "text",
  541. "fields" : {
  542. "keyword" : {
  543. "type" : "keyword",
  544. "ignore_above" : 256
  545. }
  546. }
  547. },
  548. "Overview" : {
  549. "type" : "text",
  550. "fields" : {
  551. "keyword" : {
  552. "type" : "keyword",
  553. "ignore_above" : 256
  554. }
  555. }
  556. },
  557. "Abstract" : {
  558. "type" : "text",
  559. "fields" : {
  560. "keyword" : {
  561. "type" : "keyword",
  562. "ignore_above" : 256
  563. }
  564. }
  565. },
  566. "ClassifyIdFirst" : {
  567. "type" : "long"
  568. },
  569. "ClassifyIdSecond" : {
  570. "type" : "long"
  571. },
  572. "ClassifyNameFirst" : {
  573. "type" : "text",
  574. "fields" : {
  575. "keyword" : {
  576. "type" : "keyword",
  577. "ignore_above" : 256
  578. }
  579. }
  580. },
  581. "ClassifyNameSecond" : {
  582. "type" : "text",
  583. "fields" : {
  584. "keyword" : {
  585. "type" : "keyword",
  586. "ignore_above" : 256
  587. }
  588. }
  589. },
  590. "PublishState" : {
  591. "type" : "long"
  592. },
  593. "PublishTime" : {
  594. "type" : "text",
  595. "fields" : {
  596. "keyword" : {
  597. "type" : "keyword",
  598. "ignore_above" : 256
  599. }
  600. }
  601. },
  602. "CreateTime" : {
  603. "type" : "text",
  604. "fields" : {
  605. "keyword" : {
  606. "type" : "keyword",
  607. "ignore_above" : 256
  608. }
  609. }
  610. },
  611. "ReportId" : {
  612. "type" : "long"
  613. },
  614. "StageStr" : {
  615. "type" : "text"
  616. },
  617. "Title" : {
  618. "type" : "text",
  619. "fields" : {
  620. "keyword" : {
  621. "type" : "keyword",
  622. "ignore_above" : 256
  623. }
  624. }
  625. }
  626. }
  627. }
  628. }`
  629. EsCreateIndex(indexName, mappingJson)
  630. }
  631. // UpdateEnReportEditMark 更新英文研报当前更新状态
  632. // status 枚举值 1:编辑中,0:完成编辑, 2:只做查询
  633. func UpdateEnReportEditMark(reportId, nowUserId, status int, nowUserName, lang string) (ret models.MarkReportResp, err error) {
  634. //更新标记key
  635. key := fmt.Sprint(`crm:enReport:edit:`, reportId)
  636. opUserId, e := utils.Rc.RedisInt(key)
  637. var opUser models.MarkReportItem
  638. if e != nil {
  639. opUserInfoStr, tErr := utils.Rc.RedisString(key)
  640. if tErr == nil {
  641. tErr = json.Unmarshal([]byte(opUserInfoStr), &opUser)
  642. if tErr == nil {
  643. opUserId = opUser.AdminId
  644. }
  645. }
  646. }
  647. if opUserId > 0 && opUserId != nowUserId {
  648. editor := opUser.Editor
  649. if editor == "" {
  650. //查询账号的用户姓名
  651. otherInfo, e := system.GetSysAdminById(opUserId)
  652. if e != nil {
  653. err = fmt.Errorf("查询其他编辑者信息失败")
  654. return
  655. }
  656. editor = otherInfo.RealName
  657. }
  658. ret.Status = 1
  659. if lang == utils.EnLangVersion {
  660. ret.Msg = fmt.Sprintf("%s is currently editing the report", editor)
  661. } else {
  662. ret.Msg = fmt.Sprintf("当前%s正在编辑报告", editor)
  663. }
  664. ret.Editor = editor
  665. return
  666. }
  667. if status == 1 {
  668. nowUser := &models.MarkReportItem{AdminId: nowUserId, Editor: nowUserName}
  669. bt, e := json.Marshal(nowUser)
  670. if e != nil {
  671. err = fmt.Errorf("格式化编辑者信息失败")
  672. return
  673. }
  674. if opUserId > 0 {
  675. utils.Rc.Do("SETEX", key, int64(utils.ReportPptEditingWait), string(bt)) //3分钟缓存
  676. } else {
  677. utils.Rc.SetNX(key, string(bt), utils.ReportPptEditingWait*time.Second) //3分钟缓存
  678. }
  679. } else if status == 0 {
  680. //清除编辑缓存
  681. _ = utils.Rc.Delete(key)
  682. }
  683. return
  684. }
  685. // 英文策略报告一键同步功能
  686. func EnglishPolicyReportSync(id int, adminInfo *system.Admin) (err error, errMsg string) {
  687. //查询报告是否存在
  688. policyReport, err := models.GetEnglishPolicyReportById(id)
  689. if err != nil {
  690. if err.Error() == utils.ErrNoRow() {
  691. err = fmt.Errorf("报告不存在!")
  692. return
  693. }
  694. errMsg = "获取报告信息失败,Err:" + err.Error()
  695. err = fmt.Errorf("获取报告信息失败")
  696. return
  697. }
  698. //判断报告是否已同步
  699. if policyReport.State == 2 {
  700. err = fmt.Errorf("报告已同步,无需重复同步")
  701. return
  702. }
  703. //新增英文研报
  704. classifyNameFirst := "Macro"
  705. classifySecondName := "China A-share Daily Check-in"
  706. // 根据分类名称查询分类ID
  707. classifyInfo, err := models.GetEnglishClassifyByClassifyNameAndParentName(classifyNameFirst, classifySecondName)
  708. if err != nil {
  709. if err.Error() == utils.ErrNoRow() {
  710. err = fmt.Errorf("报告分类不存在!")
  711. return
  712. }
  713. errMsg = "获取报告分类失败,Err:" + err.Error()
  714. err = fmt.Errorf("获取报告分类失败")
  715. return
  716. }
  717. // 获取期数
  718. maxStage, err := models.GetEnglishReportStage(classifyInfo.ParentId, classifyInfo.Id)
  719. if err != nil {
  720. errMsg = "期数获取失败,Err:" + err.Error()
  721. err = fmt.Errorf("期数获取失败")
  722. return
  723. }
  724. var contentSub string
  725. if policyReport.Content != "" {
  726. contentSub, err = GetReportContentSub(policyReport.Content)
  727. if err != nil {
  728. go alarm_msg.SendAlarmMsg("策略报告 一键同步 ContentSub 失败,Err:"+err.Error(), 3)
  729. //utils.SendEmail(utils.APPNAME+"失败提醒", "解析 ContentSub 失败,Err:"+err.Error(), utils.EmailSendToUsers)
  730. }
  731. }
  732. item := new(models.EnglishReport)
  733. item.AddType = 1
  734. item.ClassifyIdFirst = classifyInfo.ParentId
  735. item.ClassifyNameFirst = classifyInfo.ParentClassifyName
  736. item.ClassifyIdSecond = classifyInfo.Id
  737. item.ClassifyNameSecond = classifyInfo.ClassifyName
  738. item.Title = "China A-share Daily Check-in"
  739. item.Abstract = "China A-share market and economic data review"
  740. item.Author = "Horizon Insights FICC Team"
  741. item.Frequency = policyReport.Frequency
  742. item.State = 1
  743. item.Content = policyReport.Content
  744. item.Stage = maxStage + 1
  745. item.ContentSub = html.EscapeString(contentSub)
  746. item.CreateTime = time.Now().Format(utils.FormatDateTime)
  747. item.ModifyTime = time.Now()
  748. item.Overview = policyReport.Abstract
  749. item.KeyTakeaways = policyReport.KeyTakeaways
  750. item.FromReportId = policyReport.Id
  751. item.AdminId = adminInfo.AdminId
  752. item.AdminRealName = adminInfo.RealName
  753. newReportId, err := models.AddEnglishReport(item)
  754. if err != nil {
  755. errMsg = "保存研报失败,Err:" + err.Error()
  756. err = fmt.Errorf("保存研报失败")
  757. return
  758. }
  759. reportCode := utils.MD5(strconv.Itoa(int(newReportId)))
  760. //修改唯一编码
  761. {
  762. go models.ModifyEnglishReportCode(newReportId, reportCode)
  763. }
  764. //更新策略报告状态为已同步
  765. if err = models.SyncEnglishPolicyReportById(policyReport.Id, int(newReportId)); err != nil {
  766. errMsg = "更新策略报告失败,Err:" + err.Error()
  767. err = fmt.Errorf("更新策略报告失败")
  768. return
  769. }
  770. return
  771. }
  772. // 英文策略报告批量同步功能
  773. func MultiEnglishPolicyReportSync() (err error, errMsg string) {
  774. //查询发布时间是当天的所有未同步的报告,并更新到英文研报
  775. condition := ""
  776. var pars []interface{}
  777. //startDate := time.Now().Format(utils.FormatDate)
  778. startDate := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate)
  779. condition += ` AND publish_time >= ? AND state = 1 AND (content !="" AND content is not null)`
  780. pars = append(pars, startDate)
  781. policyReports, err := models.GetEnglishPolicyReportByCondition(condition, pars)
  782. if err != nil {
  783. errMsg = "查询英文策略报告列表接口失败"
  784. return
  785. }
  786. if len(policyReports) == 0 {
  787. return
  788. }
  789. //新增英文研报
  790. classifyNameFirst := "Equity"
  791. classifySecondName := "A-share Daily"
  792. // 根据分类名称查询分类ID
  793. classifyInfo, err := models.GetEnglishClassifyByClassifyNameAndParentName(classifyNameFirst, classifySecondName)
  794. if err != nil {
  795. if err.Error() == utils.ErrNoRow() {
  796. err = fmt.Errorf("报告分类不存在!")
  797. return
  798. }
  799. errMsg = "获取报告分类失败,Err:" + err.Error()
  800. err = fmt.Errorf("获取报告分类失败")
  801. return
  802. }
  803. // 获取期数
  804. maxStage, err := models.GetEnglishReportStage(classifyInfo.ParentId, classifyInfo.Id)
  805. if err != nil {
  806. errMsg = "期数获取失败,Err:" + err.Error()
  807. err = fmt.Errorf("期数获取失败")
  808. return
  809. }
  810. for _, policyReport := range policyReports {
  811. contentSub := ""
  812. maxStage += 1
  813. if policyReport.Content != "" {
  814. contentSub, err = GetReportContentSub(policyReport.Content)
  815. if err != nil {
  816. errMsg = "策略报告 批量同步 ContentSub 失败,Err:" + err.Error()
  817. err = fmt.Errorf("截取内容失败")
  818. return
  819. }
  820. }
  821. item := new(models.EnglishReport)
  822. item.AddType = 1
  823. item.ClassifyIdFirst = classifyInfo.ParentId
  824. item.ClassifyNameFirst = classifyInfo.ParentClassifyName
  825. item.ClassifyIdSecond = classifyInfo.Id
  826. item.ClassifyNameSecond = classifyInfo.ClassifyName
  827. item.Title = "China A-share Daily Check-in"
  828. item.Abstract = "China A-share market and economic data review"
  829. item.Author = "Horizon Insights FICC Team"
  830. item.Frequency = policyReport.Frequency
  831. item.State = 1
  832. item.Content = policyReport.Content
  833. item.Stage = maxStage
  834. item.ContentSub = html.EscapeString(contentSub)
  835. item.CreateTime = time.Now().Format(utils.FormatDateTime)
  836. item.ModifyTime = time.Now()
  837. item.Overview = policyReport.Abstract
  838. item.KeyTakeaways = policyReport.KeyTakeaways
  839. item.FromReportId = policyReport.Id
  840. newReportId, e := models.AddEnglishReport(item)
  841. if e != nil {
  842. errMsg = "保存研报失败,Err:" + e.Error()
  843. err = fmt.Errorf("保存研报失败")
  844. return
  845. }
  846. reportCode := utils.MD5(strconv.Itoa(int(newReportId)))
  847. //修改唯一编码
  848. err = models.ModifyEnglishReportCode(newReportId, reportCode)
  849. if err != nil {
  850. errMsg = "更新英文研报失败,Err:" + err.Error()
  851. err = fmt.Errorf("更新英文研报失败")
  852. return
  853. }
  854. //更新策略报告状态为已同步
  855. if err = models.SyncEnglishPolicyReportById(policyReport.Id, int(newReportId)); err != nil {
  856. errMsg = "更新策略报告失败,Err:" + err.Error()
  857. err = fmt.Errorf("更新策略报告失败")
  858. return
  859. }
  860. }
  861. return
  862. }
  863. // 取消英文策略报告一键同步
  864. func EnglishPolicyReportSyncCancel(reportInfo *models.EnglishReportDetail) (err error) {
  865. var policyReport *models.EnglishPolicyReportDetail
  866. if reportInfo.FromReportId > 0 {
  867. //查询报告是否存在
  868. policyReport, err = models.GetEnglishPolicyReportById(reportInfo.FromReportId)
  869. if err != nil {
  870. if err.Error() == utils.ErrNoRow() {
  871. err = fmt.Errorf("报告不存在!")
  872. return
  873. }
  874. err = fmt.Errorf("获取报告信息失败,Err:%v", err)
  875. return
  876. }
  877. //判断报告是否已同步
  878. if policyReport.State == 1 {
  879. err = fmt.Errorf("报告已取消同步,无需重复取消")
  880. return
  881. }
  882. if err = models.SyncCancelEnglishPolicyReport(policyReport.Id); err != nil {
  883. err = fmt.Errorf("报告已取消同步失败 Err %v", err)
  884. return
  885. }
  886. }
  887. return
  888. }
  889. // UpdateEnglishCompanyEnabledByCompanyId 根据英文客户ID更新状态
  890. func UpdateEnglishCompanyEnabledByCompanyId(companyId int) (err error) {
  891. defer func() {
  892. if err != nil {
  893. alarm_msg.SendAlarmMsg(fmt.Sprintf("更新英文客户状态失败, Err: %s", err.Error()), 3)
  894. }
  895. }()
  896. // 获取客户
  897. comp, e := models.GetEnglishCompanyById(companyId)
  898. if e != nil {
  899. err = fmt.Errorf("英文客户已被删除")
  900. return
  901. }
  902. // 获取联系人
  903. emailCond := ` AND company_id = ?`
  904. emailPars := make([]interface{}, 0)
  905. emailPars = append(emailPars, companyId)
  906. emailList, e := models.GetEnglishReportEmailList(emailCond, emailPars, "")
  907. if e != nil {
  908. err = fmt.Errorf("获取英文联系人列表失败, Err: %s", e.Error())
  909. return
  910. }
  911. // 无联系人, 保持原状态
  912. total := len(emailList)
  913. if total == 0 {
  914. return
  915. }
  916. // 判断状态, 是否部分禁用
  917. status := 0
  918. enabledCount := 0
  919. for _, v := range emailList {
  920. if v.Enabled == 1 {
  921. enabledCount += 1
  922. }
  923. }
  924. if enabledCount == 0 {
  925. status = models.EnglishCompanyDisabled
  926. }
  927. if total == enabledCount {
  928. status = models.EnglishCompanyEnabled
  929. }
  930. if total > enabledCount && enabledCount != 0 {
  931. status = models.EnglishCompanyHalfEnabled
  932. }
  933. // 是否需要更新
  934. if comp.Enabled == status {
  935. return
  936. }
  937. comp.Enabled = status
  938. comp.ModifyTime = time.Now().Local()
  939. if e = comp.Update([]string{"Enabled", "ModifyTime"}); e != nil {
  940. err = fmt.Errorf("更新客户状态失败, Err: %s", e.Error())
  941. return
  942. }
  943. return
  944. }