package report import ( "encoding/json" "errors" logger "eta/eta_mini_ht_api/common/component/log" "eta/eta_mini_ht_api/common/exception" "eta/eta_mini_ht_api/common/utils/date" "eta/eta_mini_ht_api/common/utils/page" permissionService "eta/eta_mini_ht_api/domian/config" mediaService "eta/eta_mini_ht_api/domian/media" reportService "eta/eta_mini_ht_api/domian/report" userService "eta/eta_mini_ht_api/domian/user" user "eta/eta_mini_ht_api/service/user" "fmt" "gorm.io/gorm" "strconv" "strings" "sync" "time" ) const ( SourceETA = "ETA" SourceHT = "HT" RiskLevelUnMatch = "unMatch" RiskLevelUnTest = "unTest" RiskLevelExpired = "expired" RiskLevelMatch = "match" ) type PublishRankedReport struct { Id int `json:"reportId"` OrgId int `json:"orgId"` Title string `json:"title"` Abstract string `json:"abstract"` SecondPermissions map[int]string `json:"-"` Permissions map[int]string `json:"-"` PermissionNames interface{} `json:"permissionNames,omitempty"` PublishedTime string `json:"publishedTime"` CoverUrl string `json:"coverUrl"` } type HotRankedReport struct { Id int `json:"reportId"` OrgId int `json:"orgId"` Abstract string `json:"abstract"` Count int `json:"count"` Title string `json:"title"` PublishedTime string `json:"publishedTime"` SecondPermissions map[int]string `json:"-"` Permissions map[int]string `json:"-"` PermissionNames interface{} `json:"permissionNames,omitempty"` CoverUrl string `json:"coverUrl"` } //type PermissionNode struct { // ID int `json:"id"` // Name string `json:"name"` // ParentID int `json:"parentId"` // Children []*PermissionNode `json:"children,omitempty"` //} type RecordCount struct { UserId int Mobile string ReportId int IpAddress string Location string Referer string Additional string } func matchRiskLevel(userId int, report reportService.ReportDTO) (riskLevelMatch string, err error) { userProfile, userErr := user.GetUserProfile(userId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { logger.Error("用户信息不存在,mobile:%d", userProfile.Mobile) err = exception.New(exception.TemplateUserNotFound) return } else { logger.Error("获取用户信息失败:%v", userErr) err = exception.New(exception.TemplateUserFoundFailed) return } } //比较风险等级 if userProfile.RiskLevelStatus == user.RiskUnTest { logger.Info("客户风险等级未测试,mobile:%d", userProfile.Mobile) riskLevelMatch = RiskLevelUnTest return } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Info("客户风险等级已过期,mobile:%d", userProfile.Mobile) riskLevelMatch = RiskLevelExpired return } level, err := permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if err != nil { logger.Error("获取eta报告风险等级失败:%v", err) return } permissions := reportService.GetReportSecondPermissionsById(report.OrgId, report.Source) if len(permissions) == 0 { logger.Error("获取eta报告分类失败:%v", err) riskLevelMatch = RiskLevelUnMatch return } var permissionIds []int for _, permission := range permissions { permissionIds = append(permissionIds, permission.ID) } permissionDTOs, err := permissionService.GetPermissionListByIds(permissionIds) if err != nil { logger.Error("获取品种风险等级失败:%v", err) return } //能够查看最高等级 matchNum, err := parseRiskLevel(level.ProductRiskLevel) if err != nil { logger.Error("解析风险等级失败:%v", err) return } if len(permissionDTOs) == 0 { logger.Error("当前报告对应品种未设置风险等级") err = exception.New(exception.ReportRiskLevelUnSet) return } //能够查看需要的最小等级 num := getLowestRiskLevel(permissionDTOs) if num > matchNum { riskLevelMatch = RiskLevelUnMatch return } else { riskLevelMatch = RiskLevelMatch return } } func getLowestRiskLevel(permissions []permissionService.PermissionDTO) (riskLevelNum int) { for _, permission := range permissions { pRiskNum, err := parseRiskLevel(permission.RiskLevel) if err != nil { logger.Error("解析风险等级失败:%v", err) continue } if riskLevelNum == 0 { riskLevelNum = pRiskNum } else { if riskLevelNum > pRiskNum { riskLevelNum = pRiskNum } } } return } func GetReportById(reportId int, login bool, userId int) (report reportService.ReportDTO, err error) { report, err = reportService.GetGetReportById(reportId) if err != nil { logger.Error("获取研报失败:%v", err) err = exception.New(exception.GetReportFailed) return } var status string status, err = matchRiskLevel(userId, report) if err != nil { logger.Error("匹配风险等级失败:%v", err) err = exception.New(exception.ReportRiskLevelUnSet) return } var pdfUrl string switch report.Source { case SourceETA: var detail reportService.ETAReportDTO detail, err = getETAReportDetail(&report) if err != nil { logger.Error("获取研报详情失败失败:%v", err) err = exception.New(exception.GetReportFailed) return } if !login { detail.Content = "" report.RiskLevelStatus = RiskLevelUnMatch report.Login = false } else { if status != RiskLevelMatch { detail.Content = "" } report.RiskLevelStatus = status report.Login = true } var jsonStr []byte jsonStr, err = json.Marshal(detail) if err != nil { logger.Error("生成研报详情失败:%v", err) err = exception.New(exception.GetReportFailed) } report.Detail = jsonStr return case SourceHT: pdfUrl, err = getHTReportDetail(&report) if err != nil { logger.Error("获取研报详情失败失败:%v") err = exception.New(exception.GetReportFailed) return } if !login { report.PdfUrl = "" report.RiskLevelStatus = RiskLevelUnMatch report.Login = false } else { if status == RiskLevelMatch { report.PdfUrl = pdfUrl } report.RiskLevelStatus = status report.Login = true } return default: logger.Error("不支持的研报来演:%v") err = exception.New(exception.GetReportFailed) return } } func getETAReportDetail(report *reportService.ReportDTO) (etaReport reportService.ETAReportDTO, err error) { return reportService.GetETAReport(report.OrgId) } func getHTReportDetail(report *reportService.ReportDTO) (url string, err error) { return reportService.GetHtReport(report.OrgId) } func GetTotalPageCount() (total int64, latestId int64, err error) { return reportService.GetTotalPageCount() } func GetTotalPageCountByPermissionIds(permissionIds []int, isLogin bool, userId int) (total int64, latestId int64, ids map[string][]int) { var err error //登录了需要校验风险等级,如果风险等级没做或者过期直接返回空,做了就筛选风险等级 if isLogin { userProfile, userErr := user.GetUserProfile(userId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { err = exception.New(exception.TemplateUserNotFound) } else { err = exception.New(exception.TemplateUserFoundFailed) } logger.Error("分页查询报告列表失败:%v", err) return } //获取产品风险等级 if userProfile.RiskLevel == user.RiskUnTest { logger.Error("客户未做风险等级测评,mobile:%d", userProfile.Mobile) return } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Error("客户风险等级已过期,mobile:%d", userProfile.Mobile) return } mapping, mappingErr := permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if mappingErr != nil { logger.Error("查询产品风险等级映射失败:%v", mappingErr) return } var permissionList []permissionService.PermissionDTO if len(permissionIds) == 0 { //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() } else { //更具id过滤设置了风险等级的品种 permissionList, err = permissionService.GetPermissionListByIds(permissionIds) } permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel) if len(permissionList) == 0 { return } var filterPermissionIds []int for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } return reportService.GetTotalPageCountByPermissionIds(filterPermissionIds) } else { //没有登录的时候展示所有设置了风险等级的品种报告,筛选的时候过滤传入ID中没有设置风险等级的品种 var permissionList []permissionService.PermissionDTO if len(permissionIds) == 0 { //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() } else { //更具id过滤设置了风险等级的品种 permissionList, err = permissionService.GetPermissionListByIds(permissionIds) } if err != nil { logger.Error("根据ID查询品种列表失败:%v", err) } var filterPermissionIds []int for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } //查询品种 return reportService.GetTotalPageCountByPermissionIds(filterPermissionIds) } } func filterPermissionsByRisk(permissionList []permissionService.PermissionDTO, riskLevel string) (resultList []permissionService.PermissionDTO) { riskLevelNum, err := parseRiskLevel(riskLevel) if err != nil { logger.Error("风险等级解析失败:%v", err) return } for _, permission := range permissionList { pRiskNum, riskErr := parseRiskLevel(permission.RiskLevel) if riskErr != nil { logger.Error("解析品种风险等级失败 permission:%d,risk:%v", permission.PermissionId, permission.RiskLevel) continue } if pRiskNum <= riskLevelNum { resultList = append(resultList, permission) } } return } // ParseRiskLevel 解析风险等级字符串,并返回数字部分 func parseRiskLevel(level string) (int, error) { parts := strings.Split(level, "R") if len(parts) < 2 { return 0, fmt.Errorf("无效的风险等级: %s", level) } numberStr := parts[1] number, err := strconv.Atoi(numberStr) if err != nil { return 0, fmt.Errorf("无法将风险等级转换为数字: %s", err) } return number, nil } func SearchReportList(key string, Ids []int, pageInfo page.PageInfo) (reports []reportService.ReportDTO, err error) { offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize) reports, err = reportService.SearchReportList(key, Ids, offset, pageInfo.PageSize, pageInfo.LatestId) var wg sync.WaitGroup wg.Add(len(reports)) for i := 0; i < len(reports); i++ { go func(report *reportService.ReportDTO) { defer wg.Done() report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source) var src string src, err = mediaService.GetImageSrc(report.CoverSrc) if err != nil { logger.Error("获取图片地址失败:%v", err) src = "" } else { report.CoverUrl = src } }(&reports[i]) } wg.Wait() if err != nil { err = exception.New(exception.SearchReportPageFailed) } return } func SearchMaxReportId(key string) (total int64, id int64) { return reportService.SearchMaxReportId(key) } func RangeSearchByAnalyst(analystName string, userId int) (total int64, latestId int64, ids []int) { var err error //登录了需要校验风险等级,如果风险等级没做或者过期直接返回空,做了就筛选风险等级 userProfile, userErr := user.GetUserProfile(userId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { err = exception.New(exception.TemplateUserNotFound) } else { err = exception.New(exception.TemplateUserFoundFailed) } logger.Error("分页查询报告列表失败:%v", err) return } //获取产品风险等级 if userProfile.RiskLevel == user.RiskUnTest { logger.Error("客户未做风险等级测评,mobile:%d", userProfile.Mobile) return } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Error("客户风险等级已过期,mobile:%d", userProfile.Mobile) return } mapping, mappingErr := permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if mappingErr != nil { logger.Error("查询产品风险等级映射失败:%v", mappingErr) return } var permissionList []permissionService.PermissionDTO //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel) if len(permissionList) == 0 { return } var filterPermissionIds []int for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } return reportService.GetTotalPageCountByAnalyst(analystName, filterPermissionIds) } func RangeSearch(isLogin bool, userId int) (total int64, latestId int64, orgIds map[string][]int) { var err error //登录了需要校验风险等级,如果风险等级没做或者过期直接返回空,做了就筛选风险等级 if isLogin { userProfile, userErr := user.GetUserProfile(userId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { err = exception.New(exception.TemplateUserNotFound) } else { err = exception.New(exception.TemplateUserFoundFailed) } logger.Error("分页查询报告列表失败:%v", err) return } //获取产品风险等级 if userProfile.RiskLevel == user.RiskUnTest { logger.Error("客户未做风险等级测评,mobile:%d", userProfile.Mobile) return } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Error("客户风险等级已过期,mobile:%d", userProfile.Mobile) return } mapping, mappingErr := permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if mappingErr != nil { logger.Error("查询产品风险等级映射失败:%v", mappingErr) return } var permissionList []permissionService.PermissionDTO //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel) if len(permissionList) == 0 { return } var filterPermissionIds []int for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } return reportService.GetTotalPageCountByPermissionIds(filterPermissionIds) } else { //没有登录的时候展示所有设置了风险等级的品种报告,筛选的时候过滤传入ID中没有设置风险等级的品种 var permissionList []permissionService.PermissionDTO //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() if err != nil { logger.Error("根据ID查询品种列表失败:%v", err) } var filterPermissionIds []int for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } //查询品种 return reportService.GetTotalPageCountByPermissionIds(filterPermissionIds) } } // GetReportPage 分页获取报告列表 func GetReportPage(pageInfo page.PageInfo, orgIds map[string][]int, searchAll bool, isLogin bool) (list []reportService.ReportDTO, err error) { list, err = reportService.GetReportPageByOrgIds(pageInfo, orgIds, searchAll) //并发获取研报的标签 var wg sync.WaitGroup wg.Add(len(list)) for i := 0; i < len(list); i++ { go func(report *reportService.ReportDTO) { defer wg.Done() report.Login = isLogin report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source) var src string src, err = mediaService.GetImageSrc(report.CoverSrc) if err != nil { logger.Error("获取图片地址失败:%v", err) src = "" } else { report.CoverUrl = src } }(&list[i]) } wg.Wait() if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } // func GetTotalPageCountByAnalyst(analyst string) (total int64, latestId int64) { // return reportService.GetTotalPageCountByAnalyst(analyst) // } func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string, reportIds []int) (list []reportService.ReportDTO, err error) { list, err = reportService.GetReportPageByAnalyst(pageInfo, analyst, reportIds) //并发获取研报的标签 var wg sync.WaitGroup wg.Add(len(list)) for i := 0; i < len(list); i++ { go func(report *reportService.ReportDTO) { defer wg.Done() report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source) }(&list[i]) } wg.Wait() if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } func CountReport(count RecordCount) error { dto := convertToRecordCountDTO(count) return userService.CountReport(dto) } func GetRandedReportByWeeklyHot(limit int) (reports []HotRankedReport, err error) { end := time.Now() begin := date.GetBeginOfTheWeek(end, time.Monday) hotReports := userService.GetHotReports(begin.Format(time.DateOnly), end.Format(time.DateOnly), limit) if len(hotReports) > 0 { var dtoList []reportService.ReportDTO var ids []int for i := 0; i < len(hotReports); i++ { ids = append(ids, hotReports[i].ReportId) } dtoList, err = reportService.GetListByCondition("id", ids) if err != nil { logger.Error("获取本周最热研报列表失败:%v", err) err = exception.New(exception.GetHotRandListFailed) return } var wg sync.WaitGroup wg.Add(len(dtoList)) for i := 0; i < len(dtoList); i++ { go func(report *reportService.ReportDTO) { defer wg.Done() report.Permissions = getReportPermissionsMap(report.OrgId, report.Source) report.SecondPermission = getReportSecondPermissionsMap(report.OrgId, report.Source) var label []string for _, permission := range report.Permissions { label = append(label, permission) } report.PermissionNames = label }(&dtoList[i]) } wg.Wait() reports = make([]HotRankedReport, len(ids)) for i := 0; i < len(dtoList); i++ { report := convertToHotRankedReport(dtoList[i]) for j := 0; j < len(hotReports); j++ { if hotReports[j].ReportId == report.Id { report.Count = hotReports[j].Count reports[j] = report break } } } } else { reports = []HotRankedReport{} } return } func GetRandedReportByPublishTimeWeekly(limit int, week bool) (reports []PublishRankedReport, err error) { dtoList, err := reportService.GetListOrderByConditionWeekly(week, "published_time", limit, reportService.DESC) if err != nil { logger.Error("获取最新发布的研报列表失败:%v", err) err = exception.New(exception.GetPublishedRandListFailed) return } //并发获取研报的标签 var wg sync.WaitGroup wg.Add(len(dtoList)) for i := 0; i < len(dtoList); i++ { go func(report *reportService.ReportDTO) { defer wg.Done() report.Permissions = getReportPermissionsMap(report.OrgId, report.Source) report.SecondPermission = getReportSecondPermissionsMap(report.OrgId, report.Source) report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source) }(&dtoList[i]) } wg.Wait() reports = convertToPublishRankedReportList(dtoList) return } func getReportPermissionNames(id int, source string) (labels []string) { permissions := reportService.GetReportPermissionsById(id, source) for _, permission := range permissions { labels = append(labels, permission.Name) } return } func getReportSecondPermissionsMap(id int, source string) (permissionMap map[int]string) { permissionMap = make(map[int]string) permissions := reportService.GetReportSecondPermissionsById(id, source) for _, permission := range permissions { permissionMap[permission.ID] = permission.Name } return } func getReportPermissionsMap(id int, source string) (permissionMap map[int]string) { permissionMap = make(map[int]string) permissions := reportService.GetReportPermissionsById(id, source) for _, permission := range permissions { permissionMap[permission.ID] = permission.Name } return } func GetPermissionList() (root *permissionService.PermissionNode, err error) { return permissionService.GetPermissionList() //if err != nil { // logger.Error("获取品种列表失败:%v", err) // err = exception.New(exception.GetPermissionListFailed) // return //} ////root = &PermissionNode{ //// ID: 0, //// ParentID: 0, ////} ////assemblePermissionNode(list, root, 0, 2) //return } // func assemblePermissionNode(list []reportService.PermissionDTO, node *PermissionNode, current int, level int) { // if node != nil && current < level { // for _, permission := range list { // if permission.ParentID == node.ID { // childNode := &PermissionNode{ // ID: permission.ID, // Name: permission.Name, // ParentID: permission.ParentID, // } // node.Children = append(node.Children, childNode) // assemblePermissionNode(list, childNode, current+1, level) // } // } // } // } func convertToHotRankedReport(dto reportService.ReportDTO) (report HotRankedReport) { src, err := mediaService.GetImageSrc(dto.CoverSrc) if err != nil { logger.Error("获取封面图片失败:%v", err) src = "" } report = HotRankedReport{ Id: dto.ReportID, OrgId: dto.OrgId, Abstract: dto.Abstract, PublishedTime: dto.PublishedTime, Title: dto.Title, SecondPermissions: dto.SecondPermission, Permissions: dto.Permissions, PermissionNames: dto.PermissionNames, CoverUrl: src, } return } func convertToPublishRankedReportList(dtoList []reportService.ReportDTO) (reports []PublishRankedReport) { reports = []PublishRankedReport{} for _, dto := range dtoList { src, err := mediaService.GetImageSrc(dto.CoverSrc) if err != nil { logger.Error("获取封面图片失败:%v", err) src = "" } report := PublishRankedReport{ Id: dto.ReportID, OrgId: dto.OrgId, PublishedTime: dto.PublishedTime, Abstract: dto.Abstract, Title: dto.Title, Permissions: dto.Permissions, SecondPermissions: dto.SecondPermission, PermissionNames: dto.PermissionNames, CoverUrl: src, } reports = append(reports, report) } return } func convertToRecordCountDTO(record RecordCount) (dto userService.RecordCountDTO) { return userService.RecordCountDTO{ UserId: record.UserId, Mobile: record.Mobile, SourceId: record.ReportId, IpAddress: record.IpAddress, Location: record.Location, Referer: record.Referer, Additional: record.Additional, } } func GetReportByIdListByOrgIds(orgIds map[string][]int) (ids []int, err error) { ids, err = reportService.GetReportByIdListByOrgIds(orgIds) if err != nil { logger.Error("获取报告ID列表失败:%v", err) err = exception.New(exception.GetReportSearchRangeFailed) } return } func RangePermissionIds(isLogin bool, userId int) (filterPermissionIds []int, err error) { if isLogin { userProfile, userErr := user.GetUserProfile(userId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { err = exception.New(exception.TemplateUserNotFound) } else { err = exception.New(exception.TemplateUserFoundFailed) } logger.Error("获取有权限的品种列表失败:%v", err) return } //获取产品风险等级 if userProfile.RiskLevel == user.RiskUnTest { logger.Error("客户未做风险等级测评,mobile:%d", userProfile.Mobile) return } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Error("客户风险等级已过期,mobile:%d", userProfile.Mobile) return } mapping, mappingErr := permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if mappingErr != nil { logger.Error("查询产品风险等级映射失败:%v", mappingErr) return } var permissionList []permissionService.PermissionDTO //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel) if len(permissionList) == 0 { return } for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } return } else { //没有登录的时候展示所有设置了风险等级的品种报告,筛选的时候过滤传入ID中没有设置风险等级的品种 var permissionList []permissionService.PermissionDTO //获取所有设置风险等级的品种 permissionList, err = permissionService.GetPermissionListWithRisk() if err != nil { logger.Error("根据ID查询品种列表失败:%v", err) } for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } //查询品种 return } }