english_report.go 30 KB

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