Ver Fonte

Merge branch 'eta/1.8.3' into debug

Roc há 9 meses atrás
pai
commit
e8aba96120

+ 1 - 1
models/data_manage/base_from_trade_dalian.go

@@ -69,7 +69,7 @@ func GetBaseFromTradeDalianDataList(dateTime string) (items []*BaseFromTradeDali
 
 func UpdateBaseFromTradeDalianIndex(item *BaseFromTradeDalianIndex, dataId int) (err error) {
 	o := orm.NewOrm()
-	sql := `UPDATE base_from_trade_dalian_index SET rank=?,deal_short_name=?,deal_name=?,deal_code=?,deal_value=?,buy_short_name=?,deal_change=?,buy_name=?,buy_code=?,buy_value=?,buy_change=?,sold_short_name=?,sold_name=?,sold_code=?,sold_value=?,sold_change=?,frequency=?,classify_name=?,classify_type=?,modify_time=?,data_time=? WHERE base_from_trade_dalian_index_id=? `
+	sql := "UPDATE base_from_trade_dalian_index SET `rank`=?,deal_short_name=?,deal_name=?,deal_code=?,deal_value=?,buy_short_name=?,deal_change=?,buy_name=?,buy_code=?,buy_value=?,buy_change=?,sold_short_name=?,sold_name=?,sold_code=?,sold_value=?,sold_change=?,frequency=?,classify_name=?,classify_type=?,modify_time=?,data_time=? WHERE base_from_trade_dalian_index_id=? "
 	_, err = o.Raw(sql, item.Rank, item.DealShortName, item.DealName, item.DealCode, item.DealValue, item.BuyShortName, item.DealChange, item.BuyName, item.BuyCode, item.BuyValue, item.BuyChange, item.SoldShortName, item.SoldName, item.SoldCode, item.SoldValue, item.SoldChange, item.Frequency, item.ClassifyName, item.ClassifyType, item.ModifyTime, item.DataTime, dataId).Exec()
 	return
 }

+ 11 - 11
models/data_manage/trade_position_analysis.go

@@ -229,14 +229,14 @@ func GetTradePositionTopByExchangeDataTimeTypeClassify(exchange string, dataTime
 func MultiInsertTradeBaseDataToTop(exchange string, startDate, endDate string) (err error) {
 	o := orm.NewOrm()
 	now := time.Now().Format(utils.FormatDateTime)
-	sql1 := `INSERT INTO trade_position_` + exchange + `_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,rank,create_time,modify_time)
-	SELECT classify_name,classify_type,buy_short_name,buy_value,buy_change,data_time,1,0,rank,?,? FROM base_from_trade_` + exchange + `_index where rank <50 and buy_short_name !="" and buy_short_name !=" " and data_time between ? and ?`
+	sql1 := "INSERT INTO trade_position_" + exchange + "_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,`rank`,create_time,modify_time) " +
+		"SELECT classify_name,classify_type,buy_short_name,buy_value,buy_change,data_time,1,0,`rank`,?,? FROM base_from_trade_" + exchange + "_index where `rank` <50 and buy_short_name !='' and buy_short_name !=' ' and data_time between ? and ?"
 	_, err = o.Raw(sql1, now, now, startDate, endDate).Exec()
 	if err != nil {
 		return
 	}
-	sql2 := `INSERT INTO trade_position_` + exchange + `_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,rank,create_time,modify_time)
-SELECT classify_name,classify_type,sold_short_name,sold_value,sold_change,data_time,2,0,rank,?,? FROM base_from_trade_` + exchange + `_index where rank <50 and sold_short_name !="" and sold_short_name !=" " and data_time between ? and ?`
+	sql2 := "INSERT INTO trade_position_" + exchange + "_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,`rank`,create_time,modify_time) " +
+		"SELECT classify_name,classify_type,sold_short_name,sold_value,sold_change,data_time,2,0,`rank`,?,? FROM base_from_trade_" + exchange + "_index where `rank` <50 and sold_short_name !='' and sold_short_name !=' ' and data_time between ? and ?"
 	_, err = o.Raw(sql2, now, now, startDate, endDate).Exec()
 	return
 }
@@ -244,14 +244,14 @@ SELECT classify_name,classify_type,sold_short_name,sold_value,sold_change,data_t
 func MultiInsertTradeBaseDataToTopByClassify(exchange string, startDate, endDate string, classifyNames, classifyTypes []string) (err error) {
 	o := orm.NewOrm()
 	now := time.Now().Format(utils.FormatDateTime)
-	sql1 := `INSERT INTO trade_position_` + exchange + `_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,rank,create_time,modify_time)
-	SELECT classify_name,classify_type,buy_short_name,buy_value,buy_change,data_time,1,0,rank,?,? FROM base_from_trade_` + exchange + `_index where rank <50 and buy_short_name !="" and buy_short_name !=" " and data_time between ? and ? and classify_name in (` + utils.GetOrmInReplace(len(classifyNames)) + `)  and classify_type in (` + utils.GetOrmInReplace(len(classifyTypes)) + `)`
+	sql1 := "INSERT INTO trade_position_" + exchange + "_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,`rank`,create_time,modify_time)" +
+		"SELECT classify_name,classify_type,buy_short_name,buy_value,buy_change,data_time,1,0,`rank`,?,? FROM base_from_trade_" + exchange + "_index where `rank` <50 and buy_short_name !='' and buy_short_name !=' ' and data_time between ? and ? and classify_name in (" + utils.GetOrmInReplace(len(classifyNames)) + ")  and classify_type in (" + utils.GetOrmInReplace(len(classifyTypes)) + ")"
 	_, err = o.Raw(sql1, now, now, startDate, endDate, classifyNames, classifyTypes).Exec()
 	if err != nil {
 		return
 	}
-	sql2 := `INSERT INTO trade_position_` + exchange + `_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,rank,create_time,modify_time)
-SELECT classify_name,classify_type,sold_short_name,sold_value,sold_change,data_time,2,0,rank,?,? FROM base_from_trade_` + exchange + `_index where rank <50 and sold_short_name !="" and sold_short_name !=" " and data_time between ? and ? and classify_name in (` + utils.GetOrmInReplace(len(classifyNames)) + `)  and classify_type in (` + utils.GetOrmInReplace(len(classifyTypes)) + `)`
+	sql2 := "INSERT INTO trade_position_" + exchange + "_top(classify_name,classify_type,deal_short_name,deal_value,deal_change,data_time,deal_type,source_type,`rank`,create_time,modify_time)" +
+		"SELECT classify_name,classify_type,sold_short_name,sold_value,sold_change,data_time,2,0,`rank`,?,? FROM base_from_trade_" + exchange + "_index where `rank` <50 and sold_short_name !='' and sold_short_name !=' ' and data_time between ? and ? and classify_name in (" + utils.GetOrmInReplace(len(classifyNames)) + ")  and classify_type in (" + utils.GetOrmInReplace(len(classifyTypes)) + ")"
 	_, err = o.Raw(sql2, now, now, startDate, endDate, classifyNames, classifyTypes).Exec()
 	return
 }
@@ -363,7 +363,7 @@ func MultiUpdatePositionTopChangeVal(exchange string, updates []UpdateChangeVal)
 
 func GetTradePositionOriginClassifyCountByExchangeDataTime(exchange string, startDate, endDate string) (count int64, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT COUNT(DISTINCT classify_name, classify_type) FROM base_from_trade_` + exchange + `_index where rank <50 and (buy_short_name !="" or sold_short_name !="" ) and (buy_short_name !=" " or sold_short_name !=" " ) and data_time >= ? and data_time <= ?`
+	sql := "SELECT COUNT(DISTINCT classify_name, classify_type) FROM base_from_trade_" + exchange + "_index where `rank` <50 and (buy_short_name !='' or sold_short_name !='' ) and (buy_short_name !=' ' or sold_short_name !=' ' ) and data_time >= ? and data_time <= ?"
 	err = o.Raw(sql, startDate, endDate).QueryRow(&count)
 	return
 }
@@ -382,7 +382,7 @@ type TradePositionClassifyInfo struct {
 
 func GetTradePositionOriginClassifyByExchangeDataTime(exchange string, startDate, endDate string) (list []TradePositionClassifyInfo, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT DISTINCT classify_name, classify_type FROM base_from_trade_` + exchange + `_index where rank <50 and (buy_short_name !="" or sold_short_name !="" ) and (buy_short_name !=" " or sold_short_name !=" " ) and data_time >= ? and data_time <= ?`
+	sql := "SELECT DISTINCT classify_name, classify_type FROM base_from_trade_" + exchange + "_index where `rank` <50 and (buy_short_name !='' or sold_short_name !='' ) and (buy_short_name !=' ' or sold_short_name !=' ' ) and data_time >= ? and data_time <= ?"
 	_, err = o.Raw(sql, startDate, endDate).QueryRows(&list)
 	return
 }
@@ -408,7 +408,7 @@ type GetFirstBaseFromTradeIndeDate struct {
 
 func GetFirstBaseFromTradeIndexByDate(exchange string) (item *GetFirstBaseFromTradeIndeDate, err error) {
 	o := orm.NewOrm()
-	sql := "SELECT * FROM base_from_trade_" + exchange + "_index where rank < 50 order by data_time asc"
+	sql := "SELECT * FROM base_from_trade_" + exchange + "_index where `rank` < 50 order by data_time asc"
 	err = o.Raw(sql).QueryRow(&item)
 	return
 }

+ 13 - 0
models/db.go

@@ -4,6 +4,7 @@ import (
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/models/data_manage/edb_refresh"
 	"eta/eta_task/models/data_manage/future_good"
+	"eta/eta_task/models/report"
 	"eta/eta_task/utils"
 	_ "github.com/go-sql-driver/mysql"
 	"time"
@@ -78,6 +79,9 @@ func init() {
 	//注册持仓分析 数据表
 	initTradePositionTop()
 
+	// 研报数据表
+	initReport()
+
 	// 智能研报数据表
 	initSmartReport()
 
@@ -154,6 +158,15 @@ func initTradePositionTop() {
 	)
 }
 
+// initReport 注册研报数据表
+func initReport() {
+	orm.RegisterModel(
+		new(Report),
+		new(ReportChapter),
+		new(report.ReportChapterPermissionMapping), // 报告章节的权限关系表
+	)
+}
+
 // initSmartReport 注册智能研报数据表
 func initSmartReport() {
 	orm.RegisterModel(

+ 48 - 45
models/report.go

@@ -35,6 +35,8 @@ type Report struct {
 	PreMsgSend         int       `description:"定时发布成功后是否立即推送模版消息:0否,1是"`
 	AdminId            int
 	AdminName          string `description:"系统用户名称"`
+	ClassifyIdThird    int    `description:"三级分类id"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 }
 
 func GetReportById(reportId int) (item *ReportDetail, err error) {
@@ -137,46 +139,6 @@ func ModifyReportVideo(reportId int, videoUrl, videoName, videoSize string, play
 	return
 }
 
-// ReportChapter 报告章节
-type ReportChapter struct {
-	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
-	ReportId          int       `description:"报告ID"`
-	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
-	ClassifyIdFirst   int       `description:"一级分类id"`
-	ClassifyNameFirst string    `description:"一级分类名称"`
-	TypeId            int       `description:"品种ID"`
-	TypeName          string    `description:"品种名称"`
-	Title             string    `description:"标题"`
-	Abstract          string    `description:"摘要"`
-	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
-	Author            string    `description:"作者"`
-	Content           string    `description:"内容"`
-	ContentSub        string    `description:"内容前两个章节"`
-	Stage             int       `description:"期数"`
-	Trend             string    `description:"趋势观点"`
-	Sort              int       `description:"排序: 数值越小越靠前"`
-	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
-	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
-	PublishTime       time.Time `description:"发布时间"`
-	VideoUrl          string    `description:"音频文件URL"`
-	VideoName         string    `description:"音频文件名称"`
-	VideoPlaySeconds  string    `description:"音频播放时长"`
-	VideoSize         string    `description:"音频文件大小,单位M"`
-	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
-	CreateTime        string    `description:"创建时间"`
-	ModifyTime        time.Time `description:"修改时间"`
-	OriginalVideoUrl  string    `description:"原始音频文件URL"`
-}
-
-// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
-func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
-	o := orm.NewOrmUsingDB("rddp")
-	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
-	_, err = o.Raw(sql, reportId).QueryRows(&list)
-
-	return
-}
-
 type ReportChapterTypePermission struct {
 	Id                    int       `orm:"column(id);pk" description:"主键ID"`
 	ReportChapterTypeId   int       `description:"报告章节类型ID"`
@@ -208,6 +170,8 @@ type ElasticReportDetail struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类ID"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyId         int    `description:"最小单元的分类ID"`
+	ClassifyName       string `description:"最小单元的分类名称"`
 	Categories         string `description:"关联的品种名称(包括品种别名)"`
 	StageStr           string `description:"报告期数"`
 }
@@ -217,11 +181,10 @@ type ChartPermissionMappingIdName struct {
 	PermissionName string
 }
 
-func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (list []*ChartPermissionMappingIdName, err error) {
-	o := orm.NewOrm()
-	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.key_word = ? "
-	_, err = o.Raw(sql, source, keyword).QueryRows(&list)
-
+func GetChartPermissionNameFromMappingByKeyword(source string, classifyId int) (list []*ChartPermissionMappingIdName, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.classify_id = ? "
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&list)
 	return
 }
 
@@ -265,3 +228,43 @@ func ClearReportSaveLog(date string) (err error) {
 	_, err = o.Raw(sql, date).Exec()
 	return
 }
+
+// PublishReportAndChapter 发布报告及章节
+func PublishReportAndChapter(reportInfo *Report, isPublishReport bool, cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	// 更新报告
+	if isPublishReport {
+		_, err = to.Update(reportInfo, cols...)
+		if err != nil {
+			return
+		}
+	}
+
+	// 发布该报告的所有章节
+	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ?  `
+	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id).Exec()
+
+	// 发布章节
+	//if len(publishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(publishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id, publishIds).Exec()
+	//}
+
+	//if len(unPublishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 1, publish_time = NULL, is_edit = 0 WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(unPublishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.Id, unPublishIds).Exec()
+	//}
+
+	return
+}

+ 152 - 0
models/report/report_chapter_permission_mapping.go

@@ -0,0 +1,152 @@
+package report
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapterPermissionMapping
+// @Description: 报告章节的权限关系表
+type ReportChapterPermissionMapping struct {
+	ReportChapterPermissionMappingId int `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int `description:"报告章节的id"` // 报告章节的id
+	ChartPermissionId                int `description:"权限id"`    // 权限id
+	CreateTime                       time.Time
+}
+
+// MultiAddReportChapterPermissionMappingPermission
+// @Description: 批量添加报告品种权限用户
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:36:02
+// @param reportChapterId int
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAddReportChapterPermissionMappingPermission(reportChapterId int, list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := "DELETE from report_chapter_permission_mapping where report_chapter_id=?"
+	_, err = to.Raw(sql, reportChapterId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, tmpErr := to.InsertMulti(500, list)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+	}
+
+	return
+}
+
+// GetPermissionListById
+// @Description: 根据id获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListById(reportChapterId int) (list []*ReportChapterPermissionMapping, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// ReportChapterPermissionItem
+// @Description: 报告章节的权限关系表(带有品种名称)
+type ReportChapterPermissionItem struct {
+	ReportChapterPermissionMappingId int    `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int    `description:"报告章节的id"`
+	ChartPermissionId                int    `description:"权限id"`
+	ChartPermissionName              string `description:"品种名称"`
+	CreateTime                       time.Time
+}
+
+// GetPermissionItemListById
+// @Description: 根据id获取品种权限列表(带有品种名称)
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionItemListById(reportChapterId int) (list []*ReportChapterPermissionItem, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.*,b.chart_permission_name FROM report_chapter_permission_mapping AS a 
+         JOIN chart_permission AS b on a.chart_permission_id=b.chart_permission_id WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// GetPermissionListByIdList
+// @Description: 根据id列表获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterIdList []int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListByIdList(reportChapterIdList []int) (list []*ReportChapterPermissionMapping, err error) {
+	num := len(reportChapterIdList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, reportChapterIdList).QueryRows(&list)
+
+	return
+}
+
+// MultiAdd
+// @Description: 批量添加
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-20 18:04:33
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAdd(list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, err = to.InsertMulti(500, list)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 75 - 0
models/report_chapter.go

@@ -0,0 +1,75 @@
+package models
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapter 报告章节
+type ReportChapter struct {
+	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
+	ReportId          int       `description:"报告ID"`
+	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
+	ClassifyIdFirst   int       `description:"一级分类id"`
+	ClassifyNameFirst string    `description:"一级分类名称"`
+	TypeId            int       `description:"品种ID"`
+	TypeName          string    `description:"品种名称"`
+	Title             string    `description:"标题"`
+	Abstract          string    `description:"摘要"`
+	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
+	Author            string    `description:"作者"`
+	Content           string    `description:"内容"`
+	ContentSub        string    `description:"内容前两个章节"`
+	Stage             int       `description:"期数"`
+	Trend             string    `description:"趋势观点"`
+	Sort              int       `description:"排序: 数值越小越靠前"`
+	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
+	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
+	PublishTime       time.Time `description:"发布时间"`
+	VideoUrl          string    `description:"音频文件URL"`
+	VideoName         string    `description:"音频文件名称"`
+	VideoPlaySeconds  string    `description:"音频播放时长"`
+	VideoSize         string    `description:"音频文件大小,单位M"`
+	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
+	CreateTime        string    `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	OriginalVideoUrl  string    `description:"原始音频文件URL"`
+}
+
+// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
+func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByReportId 根据ReportId获取章节列表
+func GetChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByChapterIds 根据ReportId获取章节列表
+func GetChapterListByChapterIds(chapterIds []int) (list []*ReportChapter, err error) {
+	if len(chapterIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_chapter_id IN (` + utils.GetOrmInReplace(len(chapterIds)) + `) ORDER BY sort ASC`
+	_, err = o.Raw(sql, chapterIds).QueryRows(&list)
+	return
+}
+
+// UpdateChapter 更新报表章节
+func (chapterChapterInfo *ReportChapter) UpdateChapter(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Update(chapterChapterInfo, cols...)
+
+	return
+}

+ 24 - 0
models/wx_template_msg.go

@@ -63,3 +63,27 @@ func GetOpenIdArrByClassifyNameSecond(classifyNameSecond string) (items []string
 	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
 	return
 }
+
+// GetOpenIdArrByClassifyId
+// @Description: 根据分类id获取关联的用户微信openid
+// @author: Roc
+// @datetime 2024-06-28 14:57:27
+// @param classifyId int
+// @return items []string
+// @return err error
+func GetOpenIdArrByClassifyId(classifyId int) (items []string, err error) {
+	sql := ` SELECT DISTINCT ur.open_id FROM wx_user AS wu 
+			INNER JOIN company AS c ON c.company_id = wu.company_id 
+			INNER JOIN company_product AS d ON c.company_id=d.company_id
+			INNER JOIN user_record  AS ur ON wu.user_id=ur.user_id
+			INNER JOIN company_report_permission AS e ON d.company_id=e.company_id
+			INNER JOIN chart_permission AS f ON e.chart_permission_id=f.chart_permission_id
+			INNER JOIN chart_permission_search_key_word_mapping AS g ON f.chart_permission_id=g.chart_permission_id
+			WHERE ur.open_id != "" AND ur.subscribe=1 AND ur.create_platform=1 AND  d.status IN('正式','试用','永续') AND  e.status IN('正式','试用','永续') 
+			AND g.from='rddp'
+			AND g.classify_id=?
+			ORDER BY FIELD(c.company_id, 16) DESC, ur.user_record_id ASC  `
+	o := orm.NewOrmUsingDB("weekly")
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	return
+}

+ 24 - 0
services/data/base_from_pcsg.go

@@ -78,3 +78,27 @@ func RefreshPCSGBloombergMonthly(cont context.Context) (err error) {
 	}
 	return
 }
+
+// RefreshPCSGBloombergDailyRun3 中石油新加坡-刷新彭博日度指标Run3
+func RefreshPCSGBloombergDailyRun3(cont context.Context) (err error) {
+	defer func() {
+		if err != nil {
+			tips := "RefreshPCSGBloombergDailyRun3-中石油新加坡-刷新彭博日度指标V2失败, ErrMsg:\n" + err.Error()
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	param := make(map[string]interface{})
+	uri := "bloomberg/pcsg/refresh_daily_run3"
+	res, e := postRefreshEdbData(param, uri)
+	if e != nil {
+		err = fmt.Errorf("postRefreshEdbData err: %s", e.Error())
+		return
+	}
+	if res != nil && res.Ret != 200 {
+		err = fmt.Errorf("postRefreshEdbData fail")
+		return
+	}
+	return
+}

+ 55 - 0
services/data/edb_info.go

@@ -1345,3 +1345,58 @@ func RefreshDataFromBloomberg(wg *sync.WaitGroup) (err error) {
 	fmt.Println("Bloomberg刷新结束")
 	return err
 }
+
+// RefreshDataFromCCF 刷新CCF化纤信息
+func RefreshDataFromCCF(wg *sync.WaitGroup) (err error) {
+	errMsgList := make([]string, 0)
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("RefreshDataFromCCF err: %v", err)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+		if len(errMsgList) > 0 {
+			tips := fmt.Sprintf("RefreshDataFromCCF ErrMsg: %s", strings.Join(errMsgList, "\n"))
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+		wg.Done()
+	}()
+
+	var condition string
+	var pars []interface{}
+	condition += ` AND source = ? AND no_update = 0 `
+	pars = append(pars, utils.DATA_SOURCE_CCF)
+
+	items, err := data_manage.GetEdbInfoByCondition(condition, pars, 0)
+	if err != nil {
+		return err
+	}
+	for _, v := range items {
+		startDate := ""
+		if v.Frequency == "日度" {
+			startDate = v.EndDate.AddDate(0, 0, -utils.DATA_REFRESH).Format(utils.FormatDate)
+		} else if v.Frequency == "周度" {
+			startDate = v.EndDate.AddDate(0, 0, -(utils.DATA_REFRESH * 7)).Format(utils.FormatDate)
+		} else if v.Frequency == "月度" {
+			startDate = v.EndDate.AddDate(0, -utils.DATA_REFRESH, 0).Format(utils.FormatDate)
+		} else if v.Frequency == "季度" {
+			startDate = v.EndDate.AddDate(0, -utils.DATA_REFRESH*3, 0).Format(utils.FormatDate)
+		} else if v.Frequency == "年度" {
+			startDate = v.EndDate.AddDate(-utils.DATA_REFRESH, 0, 0).Format(utils.FormatDate)
+		} else {
+			startDate = v.EndDate.AddDate(0, 0, -utils.DATA_REFRESH).Format(utils.FormatDate)
+		}
+		resp, err := RefreshEdbData(v.EdbInfoId, v.Source, v.SubSource, v.EdbCode, startDate)
+		if err != nil {
+			errMsgList = append(errMsgList, v.EdbCode+"RefreshEdbData Err:"+err.Error())
+			continue
+		}
+		if resp.Ret != 200 {
+			errMsgList = append(errMsgList, v.EdbCode+";RefreshEdbData Err:"+resp.Msg+";ErrMsg:"+resp.ErrMsg)
+			continue
+		}
+	}
+	fmt.Println("CCF化纤信息刷新结束")
+	return err
+}

+ 1 - 1
services/data/trade_position_analysis.go

@@ -14,7 +14,7 @@ import (
 // InitPositionTask 统计今日交易所的持仓分析数据
 func InitPositionTask(cont context.Context) (err error) {
 	exchanges := []string{"zhengzhou", "dalian", "shanghai", "cffex", "ine", "guangzhou"} //郑商所,大商所,上期所,中金所,上期能源,广期所
-	for i := 1; i >= 0; i-- {
+	for i := 2; i >= 0; i-- {
 		startDate := time.Now().AddDate(0, 0, -i).Format(utils.FormatDate)
 		endDate := startDate
 		for _, v := range exchanges {

+ 227 - 86
services/report.go

@@ -3,6 +3,7 @@ package services
 import (
 	"errors"
 	"eta/eta_task/models"
+	"eta/eta_task/models/report"
 	"eta/eta_task/services/alarm_msg"
 	"eta/eta_task/utils"
 	"fmt"
@@ -30,45 +31,17 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 			return
 		}
 		if len(chapterList) > 0 {
-			for i := 0; i < len(chapterList); i++ {
-				// 章节对应的品种
-				permissionList, tmpErr := models.GetChapterTypePermissionByTypeIdAndResearchType(chapterList[i].TypeId, chapterList[i].ReportType)
-				if tmpErr != nil {
-					return
-				}
-				categoryArr := make([]string, 0)
-				if len(permissionList) > 0 {
-					for ii := 0; ii < len(permissionList); ii++ {
-						categoryArr = append(categoryArr, permissionList[ii].PermissionName)
-					}
-				}
-				aliasArr, _ := addCategoryAliasToArr(categoryArr)
-				chapterCategories := strings.Join(aliasArr, ",")
-
-				esChapter := &models.ElasticReportDetail{
-					ReportId:           chapterList[i].ReportId,
-					ReportChapterId:    chapterList[i].ReportChapterId,
-					Title:              chapterList[i].Title,
-					Abstract:           chapterList[i].Abstract,
-					BodyContent:        utils.TrimHtml(html.UnescapeString(chapterList[i].Content)),
-					PublishTime:        chapterList[i].PublishTime.Format(utils.FormatDateTime),
-					PublishState:       chapterList[i].PublishState,
-					Author:             chapterList[i].Author,
-					ClassifyIdFirst:    chapterList[i].ClassifyIdFirst,
-					ClassifyNameFirst:  chapterList[i].ClassifyNameFirst,
-					ClassifyIdSecond:   0,
-					ClassifyNameSecond: "",
-					Categories:         chapterCategories,
-					StageStr:           strconv.Itoa(chapterList[i].Stage),
-				}
-				chapterDocId := fmt.Sprintf("%d-%d", reportInfo.Id, chapterList[i].ReportChapterId)
-				if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
+			// 更新章节的es数据
+			for _, chapterInfo := range chapterList {
+				err = updateReportChapterEsByChapter(chapterInfo)
+				if err != nil {
 					return
 				}
 			}
 		}
 	} else {
-		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword(reportInfo.ClassifyNameSecond, "rddp")
+		//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
+		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond)
 		if tmpErr != nil {
 			return
 		}
@@ -78,6 +51,13 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		}
 		aliasArr, _ := addCategoryAliasToArr(categoryArr)
 		categories = strings.Join(aliasArr, ",")
+		//}
+	}
+
+	// 最小单位的分类id
+	minClassifyId, minClassifyName, err := getMinClassify(reportInfo)
+	if err != nil {
+		return
 	}
 
 	// 新增报告ES
@@ -94,6 +74,8 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		ClassifyNameFirst:  reportInfo.ClassifyNameFirst,
 		ClassifyIdSecond:   reportInfo.ClassifyIdSecond,
 		ClassifyNameSecond: reportInfo.ClassifyNameSecond,
+		ClassifyId:         minClassifyId,
+		ClassifyName:       minClassifyName,
 		Categories:         categories,
 		StageStr:           strconv.Itoa(reportInfo.Stage),
 	}
@@ -139,8 +121,58 @@ func addCategoryAliasToArr(categoryArr []string) (aliasArr []string, err error)
 	return
 }
 
+// updateReportChapterEsByChapter
+// @Description: 通过章节详情更新报告章节ES
+// @author: Roc
+// @datetime 2024-06-20 13:16:11
+// @param chapterInfo *models.ReportChapter
+// @return err error
+func updateReportChapterEsByChapter(chapterInfo *models.ReportChapter) (err error) {
+	// 章节对应的品种
+	obj := report.ReportChapterPermissionMapping{}
+	permissionList, tmpErr := obj.GetPermissionItemListById(chapterInfo.ReportChapterId)
+	if tmpErr != nil {
+		return
+	}
+	categoryArr := make([]string, 0)
+	if len(permissionList) > 0 {
+		for ii := 0; ii < len(permissionList); ii++ {
+			categoryArr = append(categoryArr, permissionList[ii].ChartPermissionName)
+		}
+	}
+	aliasArr, _ := addCategoryAliasToArr(categoryArr)
+	categories := strings.Join(aliasArr, ",")
+	// 新增/编辑ES
+
+	esChapter := &models.ElasticReportDetail{
+		ReportId:           chapterInfo.ReportId,
+		ReportChapterId:    chapterInfo.ReportChapterId,
+		Title:              chapterInfo.Title,
+		Abstract:           chapterInfo.Abstract,
+		BodyContent:        utils.TrimHtml(html.UnescapeString(chapterInfo.Content)),
+		PublishTime:        chapterInfo.PublishTime.Format(utils.FormatDateTime),
+		PublishState:       chapterInfo.PublishState,
+		Author:             chapterInfo.Author,
+		ClassifyIdFirst:    chapterInfo.ClassifyIdFirst,
+		ClassifyNameFirst:  chapterInfo.ClassifyNameFirst,
+		ClassifyIdSecond:   0,
+		ClassifyNameSecond: "",
+		ClassifyId:         chapterInfo.ClassifyIdFirst,
+		ClassifyName:       chapterInfo.ClassifyNameFirst,
+		Categories:         categories,
+		StageStr:           strconv.Itoa(chapterInfo.Stage),
+	}
+	chapterDocId := fmt.Sprintf("%d-%d", chapterInfo.ReportId, chapterInfo.ReportChapterId)
+	if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
+		return
+	}
+
+	return
+}
+
 // PublishReport 定时发布研报-每秒
 func PublishReport(cont context.Context) (err error) {
+	errMsgList := make([]string, 0)
 	defer func() {
 		if err != nil {
 			go alarm_msg.SendAlarmMsg("PublishReport-定时发布研报失败, ErrMsg:\n"+err.Error(), 3)
@@ -171,41 +203,72 @@ func PublishReport(cont context.Context) (err error) {
 		if item.HasChapter == 1 && (item.ChapterType == utils.REPORT_TYPE_DAY || item.ChapterType == utils.REPORT_TYPE_WEEK) {
 			continue
 		}
-		if err = models.PublishReportById(item.Id, publishTime); err != nil {
-			return
+
+		var tmpErr error
+		if item.HasChapter == 1 { // 章节类型的报告
+			// 发布报告和章节
+			item.State = 2
+			item.PublishTime = publishTime
+			item.ModifyTime = time.Now().Local()
+			updateCols := make([]string, 0)
+			updateCols = append(updateCols, "Title", "State", "ModifyTime")
+			tmpErr = models.PublishReportAndChapter(item, true, updateCols)
+		} else {
+			tmpErr = models.PublishReportById(item.Id, publishTime)
+		}
+		if tmpErr != nil {
+			errMsgList = append(errMsgList, fmt.Sprint("报告发布失败,ID:", item.Id, ",ErrMsg:", tmpErr.Error()))
+		} else {
+			go handleByPublishReport(item)
 		}
+	}
 
-		go func() {
-			// 生成音频
-			if item.VideoUrl == "" {
-				_ = CreateVideo(item)
-			}
-			//// 推送找钢网
-			//if utils.RunMode == "release" && (report.ClassifyNameSecond == "知白守黑日评" || report.ClassifyNameSecond == "股债日评") {
-			//	_ = services.ZhaoGangSend(report)
-			//}
-			// 更新报告Es
-			_ = UpdateReportEs(item.Id, 2)
-
-			// 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
-			if utils.SendWxTemplateEnable == "1" {
-				if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
-					_ = ReportSendTemplateMsg(item.Id)
-				}
-			}
-		}()
-		recordItem := &models.ReportStateRecord{
-			ReportId:   item.Id,
-			ReportType: 1,
-			State:      2,
-			AdminId:    item.AdminId,
-			AdminName:  item.AdminName,
-			CreateTime: time.Now(),
-		}
-		go func() {
-			_, _ = models.AddReportStateRecord(recordItem)
-		}()
+	return
+}
+
+// handleByPublishReport
+// @Description: 报告发布
+// @author: Roc
+// @datetime 2024-06-28 13:26:51
+// @param item *models.Report
+// @param publishTime time.Time
+// @return err error
+func handleByPublishReport(item *models.Report) {
+	recordItem := &models.ReportStateRecord{
+		ReportId:   item.Id,
+		ReportType: 1,
+		State:      2,
+		AdminId:    item.AdminId,
+		AdminName:  item.AdminName,
+		CreateTime: time.Now(),
+	}
+
+	// 添加记录
+	_, _ = models.AddReportStateRecord(recordItem)
+
+	if item.HasChapter == 1 {
+		// 生产报告章节音频
+		_ = UpdateChaptersVideoByReportId(item.Id)
+	} else {
+		// 生成音频
+		if item.VideoUrl == "" {
+			_ = CreateVideo(item)
+		}
 	}
+
+	// 更新报告Es
+	err := UpdateReportEs(item.Id, 2)
+	if err != nil {
+		utils.FileLog.Error("UpdateReportEs, 更新报告Es失败, ReportId:%s, Err:%s", item.Id, err.Error())
+	}
+
+	// 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
+	if utils.SendWxTemplateEnable == "1" {
+		if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
+			_ = ReportSendTemplateMsg(item.Id)
+		}
+	}
+
 	return
 }
 
@@ -239,12 +302,12 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}()
 
-	report, err := models.GetReportById(reportId)
+	reportInfo, err := models.GetReportByReportId(reportId)
 	if err != nil {
 		err = errors.New("查询报告失败 Err:" + err.Error())
 		return
 	}
-	if report.MsgIsSend == 1 {
+	if reportInfo.MsgIsSend == 1 {
 		err = errors.New("模板消息已推送,请勿重复操作")
 		return
 	}
@@ -255,7 +318,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		err = errors.New("修改发布时间失败,Err:" + err.Error())
 		return
 	}
-	if report.HasChapter > 0 {
+	if reportInfo.HasChapter > 0 {
 		err = models.UpdateReportChapterPublishTime(reportId, videoNameDate)
 		if err != nil {
 			err = errors.New("修改发布时间失败,Err:" + err.Error())
@@ -263,7 +326,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}
 
-	err = sendMiniProgramReportWxMsg(report)
+	err = sendMiniProgramReportWxMsg(reportInfo)
 	if err != nil {
 		err = errors.New("发送失败,Err:" + err.Error())
 		return
@@ -277,7 +340,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 }
 
 // sendMiniProgramReportWxMsg 推送报告微信模板消息-小程序链接
-func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
+func sendMiniProgramReportWxMsg(report *models.Report) (err error) {
 	reportId := report.Id
 	var msg string
 	reportIdStr := strconv.Itoa(reportId)
@@ -297,33 +360,36 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	}
 
 	var openIdArr []string
-	if report.ClassifyIdSecond <= 0 {
+	// 如果是弘则,且报告分类是晨报,那么就所有人推送
+	if (utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox || utils.BusinessCode == utils.BusinessCodeDebug) && report.ClassifyNameFirst == "晨报" {
+		// 如果是章节,那就推送所有用户
 		openIdArr, err = models.GetOpenIdArr()
 		if err != nil {
 			msg = "get GetOpenIdArr err:" + err.Error()
 			return
 		}
 	} else {
-		classify, err := models.GetClassifyById(report.ClassifyIdSecond)
+		minClassifyId, _, err := getMinClassify(report)
+		if err != nil {
+			msg = "获取报告的最小分类失败 err:" + err.Error()
+			return err
+		}
+
+		// 判断分类是否存在
+		_, err = models.GetClassifyById(minClassifyId)
 		if err != nil {
 			msg = "获取报告分类失败 err:" + err.Error()
 			return err
 		}
-		if classify.IsMassSend == 1 {
-			openIdArr, err = models.GetOpenIdArr()
-			if err != nil {
-				msg = "get GetOpenIdArr err:" + err.Error()
-				return err
-			}
-		} else {
-			openIdArr, err = models.GetOpenIdArrByClassifyNameSecond(report.ClassifyNameSecond)
-			if err != nil {
-				msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error()
-				return err
-			}
+		// 获取该分类关联的openid列表
+		openIdArr, err = models.GetOpenIdArrByClassifyId(minClassifyId)
+		if err != nil {
+			msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error()
+			return err
 		}
 	}
 
+	// TODO 弘则的文案是不是要去掉
 	title := fmt.Sprintf("弘则%s", report.ClassifyNameFirst)
 	if CheckTwoWeekOrMonthReport(report.ClassifyIdFirst, report.ClassifyNameFirst) {
 		title = fmt.Sprintf("弘则%s", report.ClassifyNameSecond)
@@ -332,7 +398,7 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	first := fmt.Sprintf("Hi,最新一期%s已上线,欢迎查看", report.ClassifyNameFirst)
 	keyword1 := title
 	keyword2 := report.Title
-	keyword3 := report.PublishTime
+	keyword3 := report.PublishTime.Format(utils.FormatDateTime)
 	keyword4 := report.Abstract
 
 	var wxAppPath string
@@ -397,3 +463,78 @@ func ClearReportSaveLog(cont context.Context) (err error) {
 	}
 	return
 }
+
+// UpdateChaptersVideoByReportId
+// @Description: 更新报告章节音频
+// @author: Roc
+// @datetime 2024-06-28 13:52:56
+// @param reportId int
+// @return err error
+func UpdateChaptersVideoByReportId(reportId int) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("UpdateChaptersVideo, reportId:%v, Err:%s", reportId, err.Error())
+			go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新章节音频失败, 报告ID: %v; Err: "+err.Error(), reportId), 3)
+		}
+	}()
+	chapterList, err := models.GetChapterListByReportId(reportId)
+	if err != nil {
+		return
+	}
+	// 生成video
+	nowTime := time.Now()
+	updateCols := make([]string, 0)
+	updateCols = append(updateCols, "VideoUrl", "VideoName", "VideoSize", "VideoPlaySeconds")
+	for i := 0; i < len(chapterList); i++ {
+		item := chapterList[i]
+		// 忽略已有音频的章节
+		if item.VideoUrl != "" && item.VideoName != "" && item.VideoSize != "" && item.VideoPlaySeconds != "" {
+			continue
+		}
+		videoUrl, videoName, videoSize, videoPlaySeconds, e := CreateReportVideo(item.Title, html.UnescapeString(item.Content), nowTime.Format(utils.FormatDateTime))
+		if e != nil {
+			err = e
+			return
+		}
+		item.VideoUrl = videoUrl
+		item.VideoName = videoName
+		item.VideoSize = videoSize
+		item.VideoPlaySeconds = fmt.Sprintf("%.2f", videoPlaySeconds)
+		if e = item.UpdateChapter(updateCols); e != nil {
+			err = e
+		}
+	}
+
+	return
+}
+
+// getMinClassify
+// @Description: 获取最小分类ID
+// @author: Roc
+// @datetime 2024-06-20 09:23:19
+// @param reportInfo *models.Report
+// @return minClassifyId int
+// @return minClassifyName string
+// @return err error
+func getMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyName string, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error())
+		}
+	}()
+	minClassifyId = reportInfo.ClassifyIdThird
+	minClassifyName = reportInfo.ClassifyNameThird
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdSecond
+		minClassifyName = reportInfo.ClassifyNameSecond
+	}
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdFirst
+		minClassifyName = reportInfo.ClassifyNameFirst
+	}
+	if minClassifyId <= 0 {
+		err = errors.New("分类异常")
+	}
+
+	return
+}

+ 11 - 2
services/task.go

@@ -42,7 +42,7 @@ func releaseTask() {
 		task.AddTask("syncRankingFromDalian", syncRankingFromDalian)
 	}
 	// 定时统计交易所的持仓分析数据
-	initPositionTask := task.NewTask("initPositionTask", "0 20,40 16-18 * * *", data.InitPositionTask)
+	initPositionTask := task.NewTask("initPositionTask", "0 20,40 16-19 * * *", data.InitPositionTask)
 	task.AddTask("initPositionTask", initPositionTask)
 
 	//刷新指标数据
@@ -126,10 +126,13 @@ func releaseTask() {
 		refreshPCSGBloombergDaily := task.NewTask("refreshPCSGBloombergDaily", "0 30 9 * * *", data.RefreshPCSGBloombergDaily)
 		task.AddTask("刷新中石油新加坡-Bloomberg日度指标", refreshPCSGBloombergDaily)
 
+		refreshPCSGBloombergDailyRun3 := task.NewTask("refreshPCSGBloombergDailyRun3", "0 32 9 * * *", data.RefreshPCSGBloombergDailyRun3)
+		task.AddTask("刷新中石油新加坡-Bloomberg日度指标Run3", refreshPCSGBloombergDailyRun3)
+
 		//refreshPCSGBloombergWeekly := task.NewTask("refreshPCSGBloombergWeekly", "0 30 9 * * *", data.RefreshPCSGBloombergWeekly)
 		//task.AddTask("刷新中石油新加坡-Bloomberg周度指标", refreshPCSGBloombergWeekly)
 
-		refreshPCSGBloombergMonthly := task.NewTask("refreshPCSGBloombergMonthly", "0 32 9 * * *", data.RefreshPCSGBloombergMonthly)
+		refreshPCSGBloombergMonthly := task.NewTask("refreshPCSGBloombergMonthly", "0 34 9 * * *", data.RefreshPCSGBloombergMonthly)
 		task.AddTask("刷新中石油新加坡-Bloomberg月度指标", refreshPCSGBloombergMonthly)
 	}
 }
@@ -177,6 +180,12 @@ func RefreshData(cont context.Context) (err error) {
 		_ = data.RefreshDataFromBloomberg(&wg)
 	}()
 
+	// CCF化纤信息
+	go func() {
+		wg.Add(1)
+		_ = data.RefreshDataFromCCF(&wg)
+	}()
+
 	wg.Wait()
 	////计算指标
 	data.RefreshDataFromCalculateAll()

+ 3 - 0
utils/constants.go

@@ -105,6 +105,7 @@ const (
 	DATA_SOURCE_ICPI                                 = 79       // ICPI消费价格指数->79
 	DATA_SOURCE_BLOOMBERG                            = 83       // bloomberg彭博数据
 	DATA_SOURCE_BUSINESS                             = 84       // 来源于自有数据
+	DATA_SOURCE_CCF                                  = 86       // CCF化纤信息
 )
 
 // 数据刷新频率
@@ -143,7 +144,9 @@ const (
 
 // 商户号
 const (
+	BusinessCodeSandbox = "E2023080700" // 试用平台
 	BusinessCodeRelease = "E2023080900" // 生产环境
+	BusinessCodeDebug   = "E2023080901" // 测试环境
 	BusinessCodeJiaYue  = "E2023092201" // 嘉悦物产
 	BusinessCodeZhongJi = "E2023110300" // 中基宁波
 )