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" productService "eta/eta_mini_ht_api/domian/merchant" reportService "eta/eta_mini_ht_api/domian/report" userService "eta/eta_mini_ht_api/domian/user" productDao "eta/eta_mini_ht_api/models/merchant" "eta/eta_mini_ht_api/service/config" 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" defaultProductPrice = "0" ) 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"` RiskLevel string `json:"riskLevel"` IsFree bool `json:"isFree"` Price string `json:"price"` IsSubscribe bool `json:"isSubscribe"` Login bool `json:"login"` } 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"` RiskLevel string `json:"riskLevel"` IsFree bool `json:"isFree"` Price string `json:"price"` IsSubscribe bool `json:"isSubscribe"` Login bool `json:"login"` } type RecordCount struct { UserId int TraceId string Mobile string ReportId int IpAddress string Location string Referer string Additional string } func matchRiskLevel(userId int, report reportService.ReportDTO) (riskLevelMatch string, riskLevel 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:%v", 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.PermissionId) } permissionDTOs, err := permissionService.GetPermissionListByIds(permissionIds) if err != nil { logger.Error("获取品种风险等级失败:%v", err) return } //能够查看最高等级 matchNum, err := config.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) num := config.GetHighestRiskLevel(permissionDTOs) riskLevel = fmt.Sprintf("R%d", num) if num > matchNum { riskLevelMatch = RiskLevelUnMatch return } else { riskLevelMatch = RiskLevelMatch return } } func GetReportById(reportId int, login bool, userId int) (report reportService.ReportDTO, err error) { report, err = reportService.GetReportById(reportId) if err != nil { logger.Error("获取研报失败:%v", err) err = exception.New(exception.GetReportFailed) return } var status string status, report.RiskLevel, 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 GetTotalPageCountByPermissionIds(permissionIds []int, isLogin bool, userId int) (total int64, latestId int64, ids map[string][]int) { return getCount(permissionIds, isLogin, userId) } func filterPermissionsByRisk(permissionList []permissionService.PermissionDTO, riskLevel string) (resultList []permissionService.PermissionDTO) { if riskLevel != "" { riskLevelNum, err := config.ParseRiskLevel(riskLevel) if err != nil { logger.Error("风险等级解析失败:%v", err) return } for _, permission := range permissionList { pRiskNum, riskErr := config.ParseRiskLevel(permission.RiskLevel) if riskErr != nil { logger.Error("解析品种风险等级失败 permission:%d,risk:%v", permission.PermissionId, permission.RiskLevel) continue } if pRiskNum <= riskLevelNum { resultList = append(resultList, permission) } } } else { resultList = permissionList } return } // ParseRiskLevel 解析风险等级字符串,并返回数字部分 func SearchReportList(key string, Ids []int, pageInfo page.PageInfo, isLogin bool, userId int) (list []reportService.ReportDTO, err error) { offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize) var reports []reportService.ReportDTO reports, err = reportService.SearchReportList(key, Ids, offset, pageInfo.PageSize, pageInfo.LatestId) list, err = dealReportInfo(reports, isLogin, userId) if err != nil { err = exception.New(exception.SearchReportPageFailed) } return } func RangeSearchByAnalyst(analystName string, userId int) (total int64, latestId int64, ids []int) { return getCountByAnalyst(nil, true, userId, analystName) } func RangeSearch(key string, isLogin bool, userId int) (total int64, latestId int64, reportIds []int, err error) { var orgIds map[string][]int _, latestId, orgIds = getCount(nil, isLogin, userId) reportIds, err = GetReportByIdListByOrgIds(orgIds) if err != nil { logger.Error("获取报告ID列表失败:%v", err) err = exception.NewWithException(exception.GetReportSearchRangeFailed, err.Error()) return } total = reportService.SearchMaxReportIdWithRange(key, reportIds) return } func dealReportInfo(list []reportService.ReportDTO, isLogin bool, userId int) (resultList []reportService.ReportDTO, err error) { 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.Permissions, report.PermissionNames = GetReportPermissionNames(report.OrgId, report.Source) var permissions []permissionService.PermissionDTO permissions, report.SecondPermission = getReportSecondPermissions(report.OrgId, report.Source) if len(permissions) == 0 { return } riskNum := config.GetHighestRiskLevel(permissions) report.RiskLevel = strings.Join([]string{"R", strconv.Itoa(riskNum)}, "") var src string src, err = mediaService.GetImageSrc(report.CoverSrc) if err != nil { logger.Error("获取图片地址失败:%v", err) src = "" } else { report.CoverUrl = src } //查询产品信息 product, pdErr := productService.GetProductBySourceId(report.ReportID, productDao.Report) if pdErr != nil { if errors.Is(pdErr, gorm.ErrRecordNotFound) { var permissionIds []int if len(permissions) > 0 { for _, permission := range permissions { permissionIds = append(permissionIds, permission.PermissionId) } //单品不存在的话查套餐 productList, prodErr := productService.GetProductListBySourceIds(permissionIds, "package") if prodErr != nil || len(productList) == 0 { logger.Error("获取套餐列表失败:%v", pdErr) report.Price = defaultProductPrice report.IsFree = true report.IsSubscribe = false report.IsPackage = false } else { report.Price = defaultProductPrice report.IsFree = true report.IsSubscribe = false report.IsPackage = true report.ProductId = productList[0].Id } } else { report.Price = defaultProductPrice report.IsFree = true report.IsSubscribe = false report.IsPackage = false } } else { report.Price = defaultProductPrice report.IsFree = false report.IsSubscribe = false report.IsPackage = false } } else { report.Price = product.Price.String() report.IsFree = false report.ProductId = product.Id report.IsPackage = false if isLogin { subscribe, subscribeErr := userService.GetUserSubscribe(product.Id, userId) if subscribeErr != nil { report.IsSubscribe = false } else { report.IsSubscribe = subscribe.Status == productDao.SubscribeValid } } } }(&list[i]) } wg.Wait() resultList = list return } // GetReportPage 分页获取报告列表 func GetReportPage(pageInfo page.PageInfo, orgIds map[string][]int, searchAll bool, isLogin bool, userId int) (reports []reportService.ReportDTO, err error) { var list []reportService.ReportDTO list, err = reportService.GetReportPageByOrgIds(pageInfo, orgIds, searchAll) reports, err = dealReportInfo(list, isLogin, userId) if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } 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.Permissions, report.PermissionNames = GetReportPermissionNames(report.OrgId, report.Source) }(&list[i]) } wg.Wait() if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } func CountReport(count RecordCount) (traceId string, err error) { dto := convertToRecordCountDTO(count) return userService.CountReport(dto) } func GetRandedReportByWeeklyHot(limit int, isLogin bool, userId int, pdRiskLevel string) (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 } dtoList, err = dealReportInfo(dtoList, isLogin, userId) if err != nil { logger.Error("获取本周最热研报列表失败:%v", err) err = exception.New(exception.GetHotRandListFailed) return } var filterList []reportService.ReportDTO if pdRiskLevel != "" { for _, report := range dtoList { pdRiskNum, paresErr := config.ParseRiskLevel(report.RiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } reRiskNum, paresErr := config.ParseRiskLevel(pdRiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } if pdRiskNum <= reRiskNum { filterList = append(filterList, report) } } } reports = make([]HotRankedReport, len(ids)) for i := 0; i < len(filterList); i++ { report := convertToHotRankedReport(filterList[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, isLogin bool, userId int, pdRiskLevel string) (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 filterList []reportService.ReportDTO dtoList, err = dealReportInfo(dtoList, isLogin, userId) if err != nil { logger.Error("获取最新发布的研报列表失败:%v", err) err = exception.New(exception.GetPublishedRandListFailed) return } if pdRiskLevel != "" { for _, report := range dtoList { pdRiskNum, paresErr := config.ParseRiskLevel(report.RiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } reRiskNum, paresErr := config.ParseRiskLevel(pdRiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } if pdRiskNum <= reRiskNum { filterList = append(filterList, report) } } } reports = convertToPublishRankedReportList(filterList) return } func GetReportPermissionNames(id int, source string) (permissionMap map[int]string, labels []string) { permissions := reportService.GetReportPermissionsById(id, source) permissionMap = make(map[int]string, len(permissions)) if len(permissions) > 0 { for _, permission := range permissions { labels = append(labels, permission.PermissionName) permissionMap[permission.PermissionId] = permission.PermissionName } } 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.PermissionId] = permission.PermissionName } return } func getReportSecondPermissions(id int, source string) (permissionList []permissionService.PermissionDTO, secondPermissionMap map[int]string) { permissionList = reportService.GetReportSecondPermissionsById(id, source) if len(permissionList) > 0 { secondPermissionMap = make(map[int]string, len(permissionList)) for _, permission := range permissionList { secondPermissionMap[permission.PermissionId] = permission.PermissionName } } 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.PermissionId] = permission.PermissionName } return } func GetPermissionList() (root *permissionService.PermissionNode, err error) { return permissionService.GetPermissionList() } func convertToHotRankedReport(dto reportService.ReportDTO) (report HotRankedReport) { 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: dto.CoverUrl, IsSubscribe: dto.IsSubscribe, IsFree: dto.IsFree, Price: dto.Price, RiskLevel: dto.RiskLevel, Login: dto.Login, } return } func convertToPublishRankedReportList(dtoList []reportService.ReportDTO) (reports []PublishRankedReport) { reports = []PublishRankedReport{} for _, dto := range dtoList { risk, err := config.ParseRiskLevel(dto.RiskLevel) if err != nil || risk == 0 { continue } 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, IsSubscribe: dto.IsSubscribe, IsFree: dto.IsFree, Price: dto.Price, RiskLevel: dto.RiskLevel, Login: dto.Login, } reports = append(reports, report) } return } func convertToRecordCountDTO(record RecordCount) (dto userService.RecordCountDTO) { return userService.RecordCountDTO{ UserId: record.UserId, TraceId: record.TraceId, 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, riskLevel string, err error) { return CheckUserRisk(nil, isLogin, userId) } func CheckUserRisk(permissionIds []int, isLogin bool, userId int) (filterPermissionIds []int, riskLevel string, 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.RiskLevelStatus == user.RiskUnTest { logger.Warn("客户未做风险等级测评,mobile:%v", userProfile.Mobile) } if userProfile.RiskLevelStatus == user.RiskExpired { logger.Warn("客户风险等级已过期,mobile:%v", userProfile.Mobile) } var mapping permissionService.CustomerProductRiskMappingDTO if userProfile.RiskLevel != "" { mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if err != nil { logger.Error("查询产品风险等级映射失败:%v", err) 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) riskLevel = mapping.ProductRiskLevel if len(permissionList) == 0 { return } for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } return } 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) } for _, permission := range permissionList { filterPermissionIds = append(filterPermissionIds, permission.PermissionId) } //查询品种 return } } func getCount(permissionIds []int, isLogin bool, userId int) (total int64, latestId int64, ids map[string][]int) { filterPermissionIds, riskLevel, err := CheckUserRisk(permissionIds, isLogin, userId) if err != nil { logger.Error("校验用户风险等级失败:%v", err) return } return reportService.GetTotalPageCountByPermissionIds(filterPermissionIds, riskLevel) } func getCountByAnalyst(permissionIds []int, isLogin bool, userId int, analystName string) (total int64, latestId int64, ids []int) { filterPermissionIds, riskLevel, err := CheckUserRisk(permissionIds, isLogin, userId) if err != nil { logger.Error("校验用户风险等级失败:%v", err) return } return reportService.GetTotalPageCountByAnalyst(analystName, filterPermissionIds, riskLevel) }