package services import ( "encoding/json" "errors" "eta/eta_api/models" "eta/eta_api/models/system" "eta/eta_api/services/alarm_msg" "eta/eta_api/utils" "fmt" "html" "strconv" "strings" "time" ) // CreateNewEnglishReport 生成英文研报 func CreateNewEnglishReport(req models.AddEnglishReportReq, adminInfo *system.Admin) (newReportId int64, reportCode string, err error) { var contentSub string if req.Content != "" { content, e := FilterReportContentBr(req.Content) if e != nil { err = errors.New("内容去除前后空格失败, Err: " + e.Error()) return } req.Content = content contentSub, e = GetReportContentSub(req.Content) if e != nil { go alarm_msg.SendAlarmMsg("ContentSub 失败,Err:"+e.Error(), 3) err = errors.New("获取报告内容前几段失败, Err: " + e.Error()) return } } maxStage, e := models.GetEnglishReportStage(req.ClassifyIdFirst, req.ClassifyIdSecond) if e != nil { err = errors.New("期数获取失败, Err: " + e.Error()) return } item := new(models.EnglishReport) item.AddType = req.AddType item.ClassifyIdFirst = req.ClassifyIdFirst item.ClassifyNameFirst = req.ClassifyNameFirst item.ClassifyIdSecond = req.ClassifyIdSecond item.ClassifyNameSecond = req.ClassifyNameSecond item.Title = req.Title item.Abstract = req.Abstract item.Author = req.Author item.Frequency = req.Frequency item.State = req.State item.Content = html.EscapeString(req.Content) item.Stage = maxStage + 1 item.ContentSub = html.EscapeString(contentSub) item.CreateTime = req.CreateTime item.ModifyTime = time.Now() item.AdminId = adminInfo.AdminId item.AdminRealName = adminInfo.RealName newReportId, e = models.AddEnglishReport(item) if e != nil { err = errors.New("新增报告失败, Err: " + e.Error()) return } reportCode = utils.MD5(strconv.Itoa(int(newReportId))) //修改唯一编码 { go models.ModifyEnglishReportCode(newReportId, reportCode) } return } // IEnglishEmailSend 英文研报-邮件推送接口 type IEnglishEmailSend interface { NewClient() (err error) SendEmail(item *EnglishReportSendEmailRequest) (ok bool, result string, err error) BatchSendEmail(list []*EnglishReportSendEmailRequest) (results []*EnglishReportSendEmailResult, err error) } // EnglishReportSendEmailRequest 英文研报-推送邮件请求体 type EnglishReportSendEmailRequest struct { ReportId int `description:"英文报告ID"` EmailId int `description:"邮箱ID"` Email string `description:"邮箱地址"` Subject string `description:"邮件主题"` FromAlias string `description:"发信人昵称"` ReportTitle string `description:"报告标题"` ReportAbstract string `description:"报告摘要"` ReportContent string `description:"报告内容"` ReportShareLink string `description:"报告分享链接"` ReportTime string `description:"报告时间"` HtmlBody string `description:"模板内容主体"` } // EnglishReportSendEmailResult 英文研报-推送邮件响应体 type EnglishReportSendEmailResult struct { ReportId int `description:"英文报告ID"` EmailId int `description:"邮箱ID"` Email string `description:"邮箱地址"` Ok bool `description:"是否推送成功"` SendData string `description:"请求数据-JSON"` ResultData string `description:"推送结果-JSON"` Source int `description:"服务来源:1-阿里云;2-腾讯云"` } // BatchSendAliEnglishReportEmail 批量推送英文研报邮件 func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err error) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("阿里云群发英文研报邮件失败, Err: "+err.Error(), 3) } }() if len(list) == 0 { return } requestMap := make(map[int]*EnglishReportSendEmailRequest, 0) for i := range list { requestMap[list[i].EmailId] = list[i] } // 请求阿里云接口批量推送 aliEmail := new(AliyunEmail) resultList, e := aliEmail.BatchSendEmail(list) if e != nil { err = e return } // 返回的结果更新日志 resendList := make([]*EnglishReportSendEmailRequest, 0) failLogIds := make([]int, 0) updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"} for i := range resultList { var cond string var pars []interface{} cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?` pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceAli, models.EnglishReportEmailLogStatusIng) l, e := models.GetEnglishReportEmailLog(cond, pars) if e != nil { continue } l.SendData = resultList[i].SendData l.Result = resultList[i].ResultData if resultList[i].Ok { l.SendStatus = models.EnglishReportEmailLogStatusSuccess } else { l.SendStatus = models.EnglishReportEmailLogStatusFail failLogIds = append(failLogIds, l.Id) if requestMap[resultList[i].EmailId] != nil { resendList = append(resendList, requestMap[resultList[i].EmailId]) } // 取出错误信息 r := new(AliyunEmailResult) if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil { continue } rd := new(AliyunEmailResultData) res := strings.Replace(r.Data, `\`, ``, -1) if e = json.Unmarshal([]byte(res), &rd); e != nil { continue } l.ErrMsg = rd.Message } if e = l.Update(updateCols); e != nil { continue } } // 推送失败的重新腾讯云, 若腾讯云也失败将不再自动重推, 用户手动去重推 if len(resendList) > 0 && len(failLogIds) > 0 { _ = ResendTencentEnglishReportEmail(resendList, failLogIds) } return } // ResendTencentEnglishReportEmail 腾讯云邮件重新推送 func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest, failLogIds []int) (err error) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("腾讯云重发英文研报邮件失败, Err: "+err.Error(), 3) } }() if len(resendList) == 0 || len(failLogIds) == 0 { return } // 标记原有日志为已删除 if len(failLogIds) > 0 { if e := models.DeleteEnglishReportEmailLogByIds(failLogIds); e != nil { err = errors.New("删除原邮件日志失败, Err: " + e.Error()) return } } // 写入新的日志 nowTime := time.Now().Local() logData := make([]*models.EnglishReportEmailLog, 0) for i := range resendList { sendByte, e := json.Marshal(resendList[i]) if e != nil { err = errors.New("sendByte json.Marshal Err, Err: " + e.Error()) return } logData = append(logData, &models.EnglishReportEmailLog{ ReportId: resendList[i].ReportId, EmailId: resendList[i].EmailId, Email: resendList[i].Email, SendData: string(sendByte), Source: models.EnglishReportEmailLogSourceTencent, SendStatus: models.EnglishReportEmailLogStatusIng, CreateTime: nowTime, }) } emailLog := new(models.EnglishReportEmailLog) if e := emailLog.InsertMulti(logData); e != nil { err = errors.New("批量写入群发邮件日志失败, Err: " + e.Error()) return } // 请求腾讯云 tecentEmail := new(TencentEmail) resultList, e := tecentEmail.BatchSendEmail(resendList) if e != nil { err = e return } updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"} for i := range resultList { var cond string var pars []interface{} cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?` pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceTencent, models.EnglishReportEmailLogStatusIng) l, e := models.GetEnglishReportEmailLog(cond, pars) if e != nil { continue } l.SendData = resultList[i].SendData l.Result = resultList[i].ResultData if resultList[i].Ok { l.SendStatus = models.EnglishReportEmailLogStatusSuccess } else { l.SendStatus = models.EnglishReportEmailLogStatusFail r := new(TencentEmailResult) if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil { continue } l.ErrMsg = r.Message } if e = l.Update(updateCols); e != nil { continue } } return } // UpdateEnglishReportEs 更新英文报告/章节Es func UpdateEnglishReportEs(reportId int, publishState int) (err error) { if reportId <= 0 { return } reportInfo, err := models.GetEnglishReportById(reportId) if err != nil { return } // 新增报告ES esReport := &models.ElasticEnglishReportDetail{ Id: strconv.Itoa(reportInfo.Id), ReportId: reportInfo.Id, Title: reportInfo.Title, Abstract: reportInfo.Abstract, BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)), PublishTime: reportInfo.PublishTime, CreateTime: reportInfo.CreateTime, ReportCode: reportInfo.ReportCode, PublishState: publishState, Author: reportInfo.Author, Frequency: reportInfo.Frequency, ClassifyIdFirst: reportInfo.ClassifyIdFirst, ClassifyNameFirst: reportInfo.ClassifyNameFirst, ClassifyIdSecond: reportInfo.ClassifyIdSecond, ClassifyNameSecond: reportInfo.ClassifyNameSecond, StageStr: strconv.Itoa(reportInfo.Stage), Overview: utils.TrimHtml(html.UnescapeString(reportInfo.Overview)), ContentSub: utils.TrimHtml(html.UnescapeString(reportInfo.ContentSub)), } docId := fmt.Sprintf("%d", reportInfo.Id) if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil { return } return } // ModifyAllEsEnglishReportVideo 批量修改es里的英文研报信息和线上路演信息 func ModifyAllEsEnglishReportVideo() (err error) { reportList, err := models.GetEnglishReportByCondition("", []interface{}{}) if err != nil { return } for _, reportInfo := range reportList { // 新增报告ES esReport := &models.ElasticEnglishReportDetail{ Id: strconv.Itoa(reportInfo.Id), ReportId: reportInfo.Id, Title: reportInfo.Title, Abstract: reportInfo.Abstract, BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)), PublishTime: reportInfo.PublishTime.Format(utils.FormatDateTime), CreateTime: reportInfo.CreateTime, ReportCode: reportInfo.ReportCode, PublishState: reportInfo.State, Author: reportInfo.Author, Frequency: reportInfo.Frequency, ClassifyIdFirst: reportInfo.ClassifyIdFirst, ClassifyNameFirst: reportInfo.ClassifyNameFirst, ClassifyIdSecond: reportInfo.ClassifyIdSecond, ClassifyNameSecond: reportInfo.ClassifyNameSecond, StageStr: strconv.Itoa(reportInfo.Stage), Overview: utils.TrimHtml(html.UnescapeString(reportInfo.Overview)), ContentSub: utils.TrimHtml(html.UnescapeString(reportInfo.ContentSub)), } docId := fmt.Sprintf("%d", reportInfo.Id) if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil { return } } videoList, err := models.GetEnglishVideoByCondition("", []interface{}{}) if err != nil { return } for _, videoInfo := range videoList { // 新增报告ES esReport := &models.ElasticEnglishReportDetail{ Id: "v" + strconv.Itoa(videoInfo.Id), VideoId: videoInfo.Id, Title: videoInfo.Title, Abstract: videoInfo.Abstract, BodyContent: "", PublishTime: videoInfo.PublishTime.Format(utils.FormatDateTime), CreateTime: videoInfo.CreateTime.Format(utils.FormatDateTime), ReportCode: videoInfo.VideoCode, PublishState: videoInfo.State, Author: videoInfo.Author, Frequency: "", ClassifyIdFirst: videoInfo.ClassifyIdFirst, ClassifyNameFirst: videoInfo.ClassifyNameFirst, ClassifyIdSecond: videoInfo.ClassifyIdSecond, ClassifyNameSecond: videoInfo.ClassifyNameSecond, StageStr: "", Overview: utils.TrimHtml(html.UnescapeString(videoInfo.Overview)), ContentSub: "", } docId := fmt.Sprintf("v%d", videoInfo.Id) if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil { return } } return } // UpdateEnglishVideoEs 更新英文线上路演Es func UpdateEnglishVideoEs(videoId int, publishState int) (err error) { if videoId <= 0 { return } videoInfo, err := models.GetEnglishVideoById(videoId) if err != nil { return } // 新增报告ES esReport := &models.ElasticEnglishReportDetail{ Id: "v" + strconv.Itoa(videoInfo.Id), VideoId: videoInfo.Id, Title: videoInfo.Title, Abstract: videoInfo.Abstract, BodyContent: "", PublishTime: videoInfo.PublishTime, CreateTime: videoInfo.CreateTime, ReportCode: videoInfo.VideoCode, PublishState: publishState, Author: videoInfo.Author, Frequency: "", ClassifyIdFirst: videoInfo.ClassifyIdFirst, ClassifyNameFirst: videoInfo.ClassifyNameFirst, ClassifyIdSecond: videoInfo.ClassifyIdSecond, ClassifyNameSecond: videoInfo.ClassifyNameSecond, StageStr: "", Overview: utils.TrimHtml(html.UnescapeString(videoInfo.Overview)), ContentSub: "", } docId := fmt.Sprintf("v%d", videoInfo.Id) if err = EsAddOrEditEnglishReport(utils.EsEnglishReportIndexName, docId, esReport); err != nil { return } return } func UpdateEnglishReportClassifyId(oldItem, newItem *models.EnglishClassify, classifyId int) (err error) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("英文报告分类改名-同步更新报告表字段及权限表关键词失败3, Err:"+err.Error(), 3) } }() //如果二级分类变更为一级分类 //如果二级分类更换了父级分类,则更新报告中的父级分类ID //如果一级分类更换了名称,则更新所有报告中的一级分类名称 //如果二级分类更换了名称,则更新所有报告中的二级分类名称 if oldItem.ParentId > 0 && oldItem.ParentId != newItem.ParentId { //二级分类下的三级分类如果有报告,则该二级分类不允许改成一级分类 if oldItem.ParentId > 0 && oldItem.ParentId == oldItem.RootId { if newItem.ParentId == 0 { // 更新报告表分类字段 var condition string var pars []interface{} condition += ` AND classify_id_first = ? ` pars = append(pars, classifyId) count, e := models.GetEnglishReportCountByCondition(condition, pars) if e != nil { err = e return } if count > 0 { err = fmt.Errorf("该分类有关联的报告,不允许变更为一级分类") return } } } else if oldItem.ParentId > 0 && oldItem.ParentId != oldItem.RootId { //三级分类下如果有报告,则该三级分类不允许改成二级或或者一级分类 if (newItem.ParentId > 0 && newItem.ParentId == newItem.RootId) || newItem.ParentId == 0 { // 更新报告表分类字段 var condition string var pars []interface{} condition += ` AND classify_id_second = ? ` pars = append(pars, classifyId) count, e := models.GetEnglishReportCountByCondition(condition, pars) if e != nil { err = e return } if count > 0 { err = fmt.Errorf("该分类有关联的报告,不允许变更为二级分类或者一级分类") return } } } } return } func UpdateEnglishVideoClassifyId(oldItem, newItem *models.EnglishClassify, classifyId int) (err error) { //一级分类改为二级分类 defer func() { if err != nil { go alarm_msg.SendAlarmMsg("英文报告分类改名-同步更新报告表字段及权限表关键词失败3, Err:"+err.Error(), 3) } }() //如果二级分类变更为一级分类 //如果二级分类更换了父级分类,则更新报告中的父级分类ID //如果一级分类更换了名称,则更新所有报告中的一级分类名称 //如果二级分类更换了名称,则更新所有报告中的二级分类名称 if oldItem.ParentId > 0 && oldItem.ParentId != newItem.ParentId { //二级分类下的三级分类如果有报告,则该二级分类不允许改成一级分类 if oldItem.ParentId > 0 && oldItem.ParentId == oldItem.RootId { if newItem.ParentId == 0 { // 更新报告表分类字段 var condition string var pars []interface{} condition += ` AND classify_id_first = ? ` pars = append(pars, classifyId) count, e := models.GetEnglishVideoListCount(condition, pars) if e != nil { err = e return } if count > 0 { err = fmt.Errorf("该分类有关联的视频,不允许变更为一级分类") return } } } else if oldItem.ParentId > 0 && oldItem.ParentId != oldItem.RootId { //三级分类下如果有报告,则该三级分类不允许改成二级或或者一级分类 if (newItem.ParentId > 0 && newItem.ParentId == newItem.RootId) || newItem.ParentId == 0 { // 更新报告表分类字段 var condition string var pars []interface{} condition += ` AND classify_id_second = ? ` pars = append(pars, classifyId) count, e := models.GetEnglishVideoListCount(condition, pars) if e != nil { err = e return } if count > 0 { err = fmt.Errorf("该分类有关联的视频,不允许变更为二级分类或者一级分类") return } } } } return } // UpdateAllPublishedEnglishReportToEs 更新所有已发布的报告ES func UpdateAllPublishedEnglishReportToEs() (err error) { // 获取所有已发布的报告 var condition string var pars []interface{} condition = ` AND state IN (2, 6) ` reportList, err := models.GetEnglishReportByCondition(condition, pars) count := 0 failCount := 0 for i := 0; i < len(reportList); i++ { if err = UpdateEnglishReportEs(reportList[i].Id, 2); err != nil { fmt.Printf("更新失败, report_id: %d, Err: %s\n", reportList[i].Id, err.Error()) failCount += 1 } else { count += 1 } } fmt.Printf("报告总数:%d, 更新成功数: %d, 更新失败数: %d", len(reportList), count, failCount) return } func CreateEnglishReportIndex() { indexName := utils.EsEnglishReportIndexName mappingJson := `{ "mappings": { "dynamic": true, "properties": { "Frequency" : { "type" : "text" }, "ReportCode" : { "type" : "text" }, "Author" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "BodyContent" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "Overview" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "Abstract" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "ClassifyIdFirst" : { "type" : "long" }, "ClassifyIdSecond" : { "type" : "long" }, "ClassifyNameFirst" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "ClassifyNameSecond" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "PublishState" : { "type" : "long" }, "PublishTime" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "CreateTime" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "ReportId" : { "type" : "long" }, "StageStr" : { "type" : "text" }, "Title" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } }` EsCreateIndex(indexName, mappingJson) } // UpdateEnReportEditMark 更新英文研报当前更新状态 // status 枚举值 1:编辑中,0:完成编辑, 2:只做查询 func UpdateEnReportEditMark(reportId, nowUserId, status int, nowUserName string) (ret models.MarkReportResp, err error) { //更新标记key key := fmt.Sprint(`crm:enReport:edit:`, reportId) opUserId, e := utils.Rc.RedisInt(key) var opUser models.MarkReportItem if e != nil { opUserInfoStr, tErr := utils.Rc.RedisString(key) if tErr == nil { tErr = json.Unmarshal([]byte(opUserInfoStr), &opUser) if tErr == nil { opUserId = opUser.AdminId } } } if opUserId > 0 && opUserId != nowUserId { editor := opUser.Editor if editor == "" { //查询账号的用户姓名 otherInfo, e := system.GetSysAdminById(opUserId) if e != nil { err = fmt.Errorf("查询其他编辑者信息失败") return } editor = otherInfo.RealName } ret.Status = 1 ret.Msg = fmt.Sprintf("当前%s正在编辑报告", editor) ret.Editor = editor return } if status == 1 { nowUser := &models.MarkReportItem{AdminId: nowUserId, Editor: nowUserName} bt, e := json.Marshal(nowUser) if e != nil { err = fmt.Errorf("格式化编辑者信息失败") return } if opUserId > 0 { utils.Rc.Do("SETEX", key, int64(180), string(bt)) //3分钟缓存 } else { utils.Rc.SetNX(key, string(bt), time.Second*60*3) //3分钟缓存 } } else if status == 0 { //清除编辑缓存 _ = utils.Rc.Delete(key) } return } // 英文策略报告一键同步功能 func EnglishPolicyReportSync(id int, adminInfo *system.Admin) (err error, errMsg string) { //查询报告是否存在 policyReport, err := models.GetEnglishPolicyReportById(id) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告不存在!") return } errMsg = "获取报告信息失败,Err:" + err.Error() err = fmt.Errorf("获取报告信息失败") return } //判断报告是否已同步 if policyReport.State == 2 { err = fmt.Errorf("报告已同步,无需重复同步") return } //新增英文研报 classifyNameFirst := "Macro" classifySecondName := "China A-share Daily Check-in" // 根据分类名称查询分类ID classifyInfo, err := models.GetEnglishClassifyByClassifyNameAndParentName(classifyNameFirst, classifySecondName) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告分类不存在!") return } errMsg = "获取报告分类失败,Err:" + err.Error() err = fmt.Errorf("获取报告分类失败") return } // 获取期数 maxStage, err := models.GetEnglishReportStage(classifyInfo.ParentId, classifyInfo.Id) if err != nil { errMsg = "期数获取失败,Err:" + err.Error() err = fmt.Errorf("期数获取失败") return } var contentSub string if policyReport.Content != "" { contentSub, err = GetReportContentSub(policyReport.Content) if err != nil { go alarm_msg.SendAlarmMsg("策略报告 一键同步 ContentSub 失败,Err:"+err.Error(), 3) //utils.SendEmail(utils.APPNAME+"失败提醒", "解析 ContentSub 失败,Err:"+err.Error(), utils.EmailSendToUsers) } } item := new(models.EnglishReport) item.AddType = 1 item.ClassifyIdFirst = classifyInfo.ParentId item.ClassifyNameFirst = classifyInfo.ParentClassifyName item.ClassifyIdSecond = classifyInfo.Id item.ClassifyNameSecond = classifyInfo.ClassifyName item.Title = "China A-share Daily Check-in" item.Abstract = "China A-share market and economic data review" item.Author = "Horizon Insights FICC Team" item.Frequency = policyReport.Frequency item.State = 1 item.Content = policyReport.Content item.Stage = maxStage + 1 item.ContentSub = html.EscapeString(contentSub) item.CreateTime = time.Now().Format(utils.FormatDateTime) item.ModifyTime = time.Now() item.Overview = policyReport.Abstract item.KeyTakeaways = policyReport.KeyTakeaways item.FromReportId = policyReport.Id item.AdminId = adminInfo.AdminId item.AdminRealName = adminInfo.RealName newReportId, err := models.AddEnglishReport(item) if err != nil { errMsg = "保存研报失败,Err:" + err.Error() err = fmt.Errorf("保存研报失败") return } reportCode := utils.MD5(strconv.Itoa(int(newReportId))) //修改唯一编码 { go models.ModifyEnglishReportCode(newReportId, reportCode) } //更新策略报告状态为已同步 if err = models.SyncEnglishPolicyReportById(policyReport.Id, int(newReportId)); err != nil { errMsg = "更新策略报告失败,Err:" + err.Error() err = fmt.Errorf("更新策略报告失败") return } return } // 英文策略报告批量同步功能 func MultiEnglishPolicyReportSync() (err error, errMsg string) { //查询发布时间是当天的所有未同步的报告,并更新到英文研报 condition := "" var pars []interface{} //startDate := time.Now().Format(utils.FormatDate) startDate := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate) condition += ` AND publish_time >= ? AND state = 1 AND (content !="" AND content is not null)` pars = append(pars, startDate) policyReports, err := models.GetEnglishPolicyReportByCondition(condition, pars) if err != nil { errMsg = "查询英文策略报告列表接口失败" return } if len(policyReports) == 0 { return } //新增英文研报 classifyNameFirst := "Equity" classifySecondName := "A-share Daily" // 根据分类名称查询分类ID classifyInfo, err := models.GetEnglishClassifyByClassifyNameAndParentName(classifyNameFirst, classifySecondName) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告分类不存在!") return } errMsg = "获取报告分类失败,Err:" + err.Error() err = fmt.Errorf("获取报告分类失败") return } // 获取期数 maxStage, err := models.GetEnglishReportStage(classifyInfo.ParentId, classifyInfo.Id) if err != nil { errMsg = "期数获取失败,Err:" + err.Error() err = fmt.Errorf("期数获取失败") return } for _, policyReport := range policyReports { contentSub := "" maxStage += 1 if policyReport.Content != "" { contentSub, err = GetReportContentSub(policyReport.Content) if err != nil { errMsg = "策略报告 批量同步 ContentSub 失败,Err:" + err.Error() err = fmt.Errorf("截取内容失败") return } } item := new(models.EnglishReport) item.AddType = 1 item.ClassifyIdFirst = classifyInfo.ParentId item.ClassifyNameFirst = classifyInfo.ParentClassifyName item.ClassifyIdSecond = classifyInfo.Id item.ClassifyNameSecond = classifyInfo.ClassifyName item.Title = "China A-share Daily Check-in" item.Abstract = "China A-share market and economic data review" item.Author = "Horizon Insights FICC Team" item.Frequency = policyReport.Frequency item.State = 1 item.Content = policyReport.Content item.Stage = maxStage item.ContentSub = html.EscapeString(contentSub) item.CreateTime = time.Now().Format(utils.FormatDateTime) item.ModifyTime = time.Now() item.Overview = policyReport.Abstract item.KeyTakeaways = policyReport.KeyTakeaways item.FromReportId = policyReport.Id newReportId, e := models.AddEnglishReport(item) if e != nil { errMsg = "保存研报失败,Err:" + e.Error() err = fmt.Errorf("保存研报失败") return } reportCode := utils.MD5(strconv.Itoa(int(newReportId))) //修改唯一编码 err = models.ModifyEnglishReportCode(newReportId, reportCode) if err != nil { errMsg = "更新英文研报失败,Err:" + err.Error() err = fmt.Errorf("更新英文研报失败") return } //更新策略报告状态为已同步 if err = models.SyncEnglishPolicyReportById(policyReport.Id, int(newReportId)); err != nil { errMsg = "更新策略报告失败,Err:" + err.Error() err = fmt.Errorf("更新策略报告失败") return } } return } // 取消英文策略报告一键同步 func EnglishPolicyReportSyncCancel(reportInfo *models.EnglishReportDetail) (err error) { var policyReport *models.EnglishPolicyReportDetail if reportInfo.FromReportId > 0 { //查询报告是否存在 policyReport, err = models.GetEnglishPolicyReportById(reportInfo.FromReportId) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告不存在!") return } err = fmt.Errorf("获取报告信息失败,Err:%v", err) return } //判断报告是否已同步 if policyReport.State == 1 { err = fmt.Errorf("报告已取消同步,无需重复取消") return } if err = models.SyncCancelEnglishPolicyReport(policyReport.Id); err != nil { err = fmt.Errorf("报告已取消同步失败 Err %v", err) return } } return } // UpdateEnglishCompanyEnabledByCompanyId 根据英文客户ID更新状态 func UpdateEnglishCompanyEnabledByCompanyId(companyId int) (err error) { defer func() { if err != nil { alarm_msg.SendAlarmMsg(fmt.Sprintf("更新英文客户状态失败, Err: %s", err.Error()), 3) } }() // 获取客户 comp, e := models.GetEnglishCompanyById(companyId) if e != nil { err = fmt.Errorf("英文客户已被删除") return } // 获取联系人 emailCond := ` AND company_id = ?` emailPars := make([]interface{}, 0) emailPars = append(emailPars, companyId) emailList, e := models.GetEnglishReportEmailList(emailCond, emailPars, "") if e != nil { err = fmt.Errorf("获取英文联系人列表失败, Err: %s", e.Error()) return } // 无联系人, 保持原状态 total := len(emailList) if total == 0 { return } // 判断状态, 是否部分禁用 status := 0 enabledCount := 0 for _, v := range emailList { if v.Enabled == 1 { enabledCount += 1 } } if enabledCount == 0 { status = models.EnglishCompanyDisabled } if total == enabledCount { status = models.EnglishCompanyEnabled } if total > enabledCount && enabledCount != 0 { status = models.EnglishCompanyHalfEnabled } // 是否需要更新 if comp.Enabled == status { return } comp.Enabled = status comp.ModifyTime = time.Now().Local() if e = comp.Update([]string{"Enabled", "ModifyTime"}); e != nil { err = fmt.Errorf("更新客户状态失败, Err: %s", e.Error()) return } return }