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"` IsPackage bool `json:"isPackage"` Price string `json:"price"` IsSubscribe bool `json:"isSubscribe"` Login bool `json:"login"` ProductId int `json:"productId"` } 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"` IsPackage bool `json:"isPackage"` ProductId int `json:"productId"` 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) { var reportInfo reportService.ReportDTO reportInfo, err = reportService.GetReportById(reportId, userId) if err != nil { logger.Error("获取研报失败:%v,研报ID:%d", err, report.ReportID) err = exception.NewWithException(exception.GetReportFailed, err.Error()) return } mappingRiskLevel, userRiskStatus, err := user.CheckUserRiskMatchStatus(userId) if err != nil { logger.Error("获取研报失败:%v,研报ID:%d", err, report.ReportID) err = exception.NewWithException(exception.GetReportFailed, err.Error()) return } report, err = DealReportInfo(&reportInfo, login, userId, mappingRiskLevel, userRiskStatus) if err != nil { logger.Error("获取研报失败:%v,研报ID:%d", err, report.ReportID) err = exception.NewWithException(exception.GetReportFailed, err.Error()) return } err = getReportContent(report, login) if err != nil { logger.Error("获取研报失败:%v,研报ID:%d", err, report.ReportID) if errors.Is(err, gorm.ErrRecordNotFound) { //逻辑删除系统研报 deleteErr := reportService.DeleteReport(report.ReportID) if deleteErr != nil { logger.Error("报告删除失败:%v", deleteErr) } logger.Error("ETA报告删除") err = exception.NewWithException(exception.ReportDeleted, err.Error()) return } err = exception.NewWithException(exception.GetReportFailed, err.Error()) } return } func GetTotalPageCountByPermissionIds(permissionIds []int, isLogin bool, userId int) (total int64, latestId int64, ids map[string][]int, disCardIds []int, mappingRiskLevel, userRiskStatus string) { return getCount(permissionIds, isLogin, userId) } // ParseRiskLevel 解析风险等级字符串,并返回数字部分 func SearchReportList(key string, Ids []int, pageInfo page.PageInfo, isLogin bool, userId int, mappingRiskLevel, userRiskStatus string) (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, mappingRiskLevel, userRiskStatus) if err != nil { err = exception.New(exception.SearchReportPageFailed) } return } func SearchReportBookMark(key string, Ids []int, pageInfo page.PageInfo, isLogin bool, userId int) (list []reportService.ReportDTO, 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 } var mappingRiskLevel, userRiskStatus string userRiskStatus = userProfile.RiskLevelStatus if userProfile.RiskLevel != "" { var mapping permissionService.CustomerProductRiskMappingDTO mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if err != nil { logger.Error("查询产品风险等级映射失败:%v", err) return } mappingRiskLevel = mapping.ProductRiskLevel } offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize) var reports []reportService.ReportDTO reports, err = reportService.SearchReportList(key, Ids, offset, pageInfo.PageSize, -1) list, err = dealReportInfo(reports, isLogin, userId, mappingRiskLevel, userRiskStatus) if err != nil { err = exception.New(exception.SearchReportPageFailed) } return } func SearchReportProduct(key string, docIds []int) (list []reportService.ReportDTO, err error) { list, err = reportService.SearchReportProduct(key, 100, 0, docIds) if err != nil { err = exception.New(exception.SearchReportPageFailed) } return } func RangeSearchByAnalyst(analystName string, userId int) (total int64, latestId int64, ids []int, mappingRiskLevel, userRiskStatus string) { return getCountByAnalyst(nil, true, userId, analystName) } func RangeSearch(key string, isLogin bool, userId int) (total int64, latestId int64, reportIds []int, discardIds []int, mappingRiskLevel, userRiskStatus string, err error) { var orgIds map[string][]int _, latestId, orgIds, discardIds, mappingRiskLevel, userRiskStatus = 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, mappingRiskLevel, userRiskStatus string) (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, err = DealReportInfo(report, isLogin, userId, mappingRiskLevel, userRiskStatus) if err != nil { logger.Error("处理报告信息失败:%v", err) } }(&list[i]) } wg.Wait() resultList = list 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 getReportContent(report *reportService.ReportDTO, login bool) (err error) { var pdfUrl string switch report.Source { case SourceETA: var detail reportService.ETAReportDTO detail, err = getETAReportDetail(report) if err != nil { logger.Error("获取研报详情失败失败:%v", err) return } if !login { detail.Content = "" } else { if report.RiskLevelStatus != RiskLevelMatch { detail.Content = "" } } var jsonStr []byte jsonStr, err = json.Marshal(detail) if err != nil { logger.Error("生成研报详情失败:%v", err) return } 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 = "" } else { if report.RiskLevelStatus == RiskLevelMatch { report.PdfUrl = pdfUrl } } return default: logger.Error("不支持的研报来演:%v") err = exception.New(exception.GetReportFailed) return } } func DealReportInfo(report *reportService.ReportDTO, isLogin bool, userId int, mappingRiskLevel, userRiskStatus string) (resultReport *reportService.ReportDTO, err error) { 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 { resultReport = report 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 } //套餐信息 var packageList []productService.MerchantProductDTO //查询产品信息 product, pdErr := productService.GetProductBySourceId(report.ReportID, productDao.Report) var permissionIds []int if len(permissions) > 0 { for _, permission := range permissions { permissionIds = append(permissionIds, permission.PermissionId) } //单品不存在的话查套餐 packageList, err = productService.GetProductListBySourceIds(permissionIds, "package") if err != nil { logger.Error("获取套餐列表失败:%v", err) } } if pdErr != nil { //单品不存在的话查套餐 if len(packageList) == 0 { logger.Error("获取套餐列表失败:%v", err) report.Price = defaultProductPrice report.IsFree = true report.IsSubscribe = false report.IsPackage = false } else { report.Price = packageList[0].Price report.IsFree = false report.IsSubscribe = false report.IsPackage = true report.ProductId = packageList[0].Id } } else { report.Price = product.Price report.IsFree = false report.ProductId = product.Id report.IsPackage = false } //最热最新的时候使用 productList := append(packageList) if pdErr == nil { productList = append(productList, product) } if len(productList) == 0 { report.Show = true } else { for _, productItem := range productList { if productItem.SaleStatus == "on_sale" { report.Show = true break } } } if isLogin { var productIds []int if len(packageList) > 0 { for _, packageItem := range packageList { productIds = append(productIds, packageItem.Id) } } if product.Id > 0 { productIds = append(productIds, product.Id) } subscribeList, subscribeErr := userService.GetUserSubscribe(productIds, userId) if subscribeErr != nil { report.IsSubscribe = false } else { for _, subscribe := range subscribeList { if subscribe.Status == productDao.SubscribeValid { report.IsSubscribe = true break } } } if userRiskStatus != user.RiskValid { if userRiskStatus == user.RiskUnTest { report.RiskLevelStatus = RiskLevelUnTest } if userRiskStatus == user.RiskExpired { report.RiskLevelStatus = RiskLevelExpired } } else { report.RiskLevelStatus = RiskLevelUnMatch if mappingRiskLevel != "" { mappingRiskNum, parseErr := config.ParseRiskLevel(mappingRiskLevel) if parseErr != nil { return } var rpRiskNum int rpRiskNum, parseErr = config.ParseRiskLevel(report.RiskLevel) if parseErr != nil { return } if rpRiskNum <= mappingRiskNum { report.RiskLevelStatus = RiskLevelMatch } } } } resultReport = report return } // GetReportPage 分页获取报告列表 func GetReportPage(pageInfo page.PageInfo, orgIds map[string][]int, discardIds []int, isLogin bool, userId int, mappingRiskLevel, userRiskStatus string) (reports []reportService.ReportDTO, err error) { var list []reportService.ReportDTO list, err = reportService.GetReportPageByOrgIds(pageInfo, orgIds, discardIds) reports, err = dealReportInfo(list, isLogin, userId, mappingRiskLevel, userRiskStatus) if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } func GetReportListById(userId int, reportIds []int, mappingRiskLevel, userRiskStatus string) (reports []reportService.ReportDTO, err error) { var list []reportService.ReportDTO list, err = reportService.GetReportListById(reportIds) reports, err = dealReportInfo(list, true, userId, mappingRiskLevel, userRiskStatus) if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string, reportIds []int, templateUserId int, mappingRiskLevel, userRiskStatus string) (list []reportService.ReportDTO, err error) { list, err = reportService.GetReportPageByAnalyst(pageInfo, analyst, reportIds) list, err = dealReportInfo(list, true, templateUserId, mappingRiskLevel, userRiskStatus) if err != nil { err = exception.New(exception.QueryReportPageFailed) } return } func CountReport(count RecordCount) (traceId string, err error) { report, err := reportService.GetReportById(count.ReportId, 0) if err != nil { err = exception.New(exception.GetReportFailed) return } dto := convertToRecordCountDTO(count) dto.SourceTitle = report.Title return userService.CountReport(dto) } func GetRandedReportByWeeklyHot(limit int, isLogin bool, userId int, mappingRiskLevel string, userRiskStatus 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, mappingRiskLevel, userRiskStatus) if err != nil { logger.Error("获取本周最热研报列表失败:%v", err) err = exception.New(exception.GetHotRandListFailed) return } var filterList []reportService.ReportDTO if mappingRiskLevel != "" { for _, report := range dtoList { pdRiskNum, paresErr := config.ParseRiskLevel(report.RiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } reRiskNum, paresErr := config.ParseRiskLevel(mappingRiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } if pdRiskNum <= reRiskNum && report.Show { filterList = append(filterList, report) } } } else { for _, report := range dtoList { if report.Show { 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, mappingRiskLevel, userRiskStatus 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, mappingRiskLevel, userRiskStatus) if err != nil { logger.Error("获取最新发布的研报列表失败:%v", err) err = exception.New(exception.GetPublishedRandListFailed) return } if mappingRiskLevel != "" { for _, report := range dtoList { pdRiskNum, paresErr := config.ParseRiskLevel(report.RiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } reRiskNum, paresErr := config.ParseRiskLevel(mappingRiskLevel) if paresErr != nil { logger.Error("解析风险等级失败:%v", err) continue } if pdRiskNum <= reRiskNum && report.Show { filterList = append(filterList, report) } } } else { for _, report := range dtoList { if report.Show { 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, ProductId: dto.ProductId, IsPackage: dto.IsPackage, } 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, ProductId: dto.ProductId, IsPackage: dto.IsPackage, } 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, userRiskStatus string, err error) { return user.GetRiskLevelPermissionList(nil, isLogin, userId) } func getCount(permissionIds []int, isLogin bool, userId int) (total int64, latestId int64, ids map[string][]int, discardIds []int, mappingRiskLevel, userRiskStatus string) { filterPermissionIds, mappingRiskLevel, userRiskStatus, err := user.GetRiskLevelPermissionList(permissionIds, isLogin, userId) if err != nil { logger.Error("获取过滤品种信息失败:%v", err) return } if len(filterPermissionIds) == 0 { logger.Warn("不存在设置风险等级的品种信息") return } total, latestId, ids, discardIds = reportService.GetTotalPageCountByPermissionIds(filterPermissionIds) return } func getCountByAnalyst(permissionIds []int, isLogin bool, userId int, analystName string) (total int64, latestId int64, ids []int, mappingRiskLevel, userRiskStatus string) { filterPermissionIds, mappingRiskLevel, userRiskStatus, err := user.GetRiskLevelPermissionList(permissionIds, isLogin, userId) if err != nil { logger.Error("校验用户风险等级失败:%v", err) return } total, latestId, ids = reportService.GetTotalPageCountByAnalyst(analystName, filterPermissionIds) return } func CountPermissionWeight(ids []int) (permissionMap map[int]int) { list, err := reportService.CountPermissionWeight(ids) permissionMap = make(map[int]int) if err != nil { return } for _, item := range list { permissionMap[item.PermissionId] = item.Weight } return } func FilterReportIds(reportIds []int) (total int64, filterReportIds []int, err error) { return reportService.FilterReportIds(reportIds) }