product_service.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. package product
  2. import (
  3. logger "eta/eta_mini_ht_api/common/component/log"
  4. "eta/eta_mini_ht_api/common/exception"
  5. "eta/eta_mini_ht_api/common/utils/page"
  6. permissionService "eta/eta_mini_ht_api/domian/config"
  7. mediaDomain "eta/eta_mini_ht_api/domian/media"
  8. merchantService "eta/eta_mini_ht_api/domian/merchant"
  9. reportDomain "eta/eta_mini_ht_api/domian/report"
  10. "eta/eta_mini_ht_api/domian/user"
  11. "eta/eta_mini_ht_api/models/config"
  12. "eta/eta_mini_ht_api/models/image"
  13. "eta/eta_mini_ht_api/models/media"
  14. merchantDao "eta/eta_mini_ht_api/models/merchant"
  15. configService "eta/eta_mini_ht_api/service/config"
  16. mediaService "eta/eta_mini_ht_api/service/media"
  17. "eta/eta_mini_ht_api/service/order"
  18. reportService "eta/eta_mini_ht_api/service/report"
  19. "fmt"
  20. "sort"
  21. "sync"
  22. "sync/atomic"
  23. "time"
  24. )
  25. type ProductDTO struct {
  26. Id int `json:"id"`
  27. Title string `json:"title"`
  28. SourceTile string `json:"sourceTile"`
  29. Abstract string `json:"abstract"`
  30. Src string `json:"src"`
  31. PermissionNames []string `json:"permissionNames"`
  32. PermissionIds []int `json:"-"`
  33. Description string `json:"description"`
  34. Price string `json:"price"`
  35. CoverSrc int `json:"coverSrc"`
  36. CoverUrl string `json:"coverUrl"`
  37. RiskLevel string `json:"riskLevel"`
  38. Type string `json:"type"`
  39. BeginDate string `json:"beginDate"`
  40. EndDate string `json:"endDate"`
  41. SourceId int `json:"sourceId"`
  42. IsSubscribe bool `json:"isSubscribe"`
  43. ReportId int `json:"reportId"`
  44. MediaId int `json:"mediaId"`
  45. }
  46. func GetProductRiskLevel(product merchantService.MerchantProductDTO) (riskLevel, sourceTitle, sourceAbsract, coverSrc, sourceSrc string, permissionNames []string, permissionIds []int, err error) {
  47. switch product.Type {
  48. case "package":
  49. permissionRisk, permissionErr := config.PermissionsByPermissionId(product.SourceId)
  50. permissionNames = []string{permissionRisk.Name}
  51. permissionIds = []int{product.SourceId}
  52. if permissionErr != nil {
  53. logger.Error("获取权限信息失败[permissionId:%d]", product.SourceId)
  54. } else {
  55. riskLevel = permissionRisk.RiskLevel
  56. }
  57. coverSrc = product.CoverUrl
  58. case "audio", "video":
  59. mediaInfo, mediaErr := media.GetMediaById(product.Type, product.SourceId)
  60. sourceTitle, coverSrc, sourceSrc = mediaInfo.MediaName, mediaInfo.CoverSrc, mediaInfo.Src
  61. if mediaErr != nil {
  62. logger.Error("获取媒体信息失败[mediaType:%s,mediaId:%d]", product.Type, product.SourceId)
  63. }
  64. permissionIds, mediaErr = media.GetMediaPermissionMappingByMedia(product.Type, product.SourceId)
  65. if mediaErr != nil {
  66. logger.Error("获取媒体权限失败[mediaType:%s,mediaId:%d]", product.Type, product.SourceId)
  67. } else {
  68. permissions, permissionErr := permissionService.GetPermissionListByIds(permissionIds)
  69. if permissionErr != nil {
  70. logger.Error("获取权限信息失败[permissionIds:%v]", permissionIds)
  71. }
  72. permissionNames = mediaService.GetMediaPermissionNames(permissionIds)
  73. riskNum := configService.GetHighestRiskLevel(permissions)
  74. riskLevel = fmt.Sprintf("R%d", riskNum)
  75. }
  76. case "report":
  77. report, reportErr := reportDomain.GetReportById(product.SourceId)
  78. var coverSrcId int
  79. sourceAbsract, sourceTitle, coverSrcId = report.Abstract, report.Title, report.CoverSrc
  80. if coverSrcId > 0 {
  81. var imageSrc string
  82. imageSrc, coverSrcErr := image.GetImageSrc(coverSrcId)
  83. if coverSrcErr != nil {
  84. logger.Error("获取图片资源失败:%v,资源ID:%d", err, coverSrcId)
  85. } else {
  86. coverSrc = imageSrc
  87. }
  88. }
  89. if reportErr != nil {
  90. logger.Error("获取研报信息失败[reportId:%d]", product.SourceId)
  91. } else {
  92. switch report.Source {
  93. case reportDomain.SourceHT:
  94. permission, permissionErr := configService.GetPermissionByName(report.PlateName)
  95. if permissionErr != nil {
  96. logger.Error("获取板块权限失败[plateName:%s]", report.PlateName)
  97. } else {
  98. riskLevel = permission.RiskLevel
  99. permissionIds = []int{permission.PermissionId}
  100. }
  101. case reportDomain.SourceETA:
  102. permissions, permissionErr := configService.GetSecondPermissionsByClassifyId(report.ClassifyId)
  103. if permissionErr != nil {
  104. logger.Error("获取板块权限失败[plateName:%s]", report.PlateName)
  105. } else {
  106. riskNum := configService.GetHighestRiskLevel(permissions)
  107. for _, permission := range permissions {
  108. permissionIds = append(permissionIds, permission.PermissionId)
  109. }
  110. riskLevel = fmt.Sprintf("R%d", riskNum)
  111. }
  112. }
  113. _, permissionNames = reportService.GetReportPermissionNames(report.OrgId, report.Source)
  114. }
  115. default:
  116. logger.Warn("不支持的产品类型[%s]", product.Type)
  117. }
  118. return
  119. }
  120. func GetProductInfoById(productId int) (product ProductDTO, err error) {
  121. merchantProduct, err := merchantService.GetMerchantProductById(productId)
  122. if err != nil {
  123. err = exception.NewWithException(exception.ProductInfoError, err.Error())
  124. return
  125. }
  126. product = convertToProductDTO(merchantProduct)
  127. product.RiskLevel, product.SourceTile, product.Abstract, product.CoverUrl, product.Src, product.PermissionNames, _, err = GetProductRiskLevel(merchantProduct)
  128. if err != nil {
  129. logger.Error("获取风险等级失败[productId:%d]", productId)
  130. }
  131. return
  132. }
  133. func convertToProductDTO(product merchantService.MerchantProductDTO) (productDTO ProductDTO) {
  134. beginDate := time.Now()
  135. endDate := beginDate.Add(time.Duration(product.ValidDays) * 24 * time.Hour)
  136. productDTO = ProductDTO{
  137. Id: product.Id,
  138. Title: product.Title,
  139. Description: product.Description,
  140. Price: product.Price,
  141. RiskLevel: product.RiskLevel,
  142. CoverSrc: product.CoverSrc,
  143. CoverUrl: product.CoverUrl,
  144. Type: product.Type,
  145. BeginDate: beginDate.Format(time.DateOnly),
  146. EndDate: endDate.Format(time.DateOnly),
  147. SourceId: product.SourceId,
  148. }
  149. if product.CoverUrl == "" && product.CoverSrc > 0 {
  150. imageSrc, err := image.GetImageSrc(product.CoverSrc)
  151. if err != nil {
  152. logger.Error("获取图片地址失败:%v,资源Id:%d", err, product.CoverSrc)
  153. } else {
  154. productDTO.CoverUrl = imageSrc
  155. }
  156. }
  157. return
  158. }
  159. // OpenProduct 开通产品
  160. func OpenProduct(templateUserId int, productOrderNo string) (err error) {
  161. proudctOrder, err := order.GetProductOrderByUser(templateUserId, productOrderNo)
  162. if err != nil {
  163. logger.Error("获取产品订单信息失败:%v", err)
  164. return
  165. }
  166. product, err := merchantService.GetMerchantProductById(proudctOrder.ProductID)
  167. if err != nil {
  168. logger.Error("获取产品信息失败:%v", err)
  169. return
  170. }
  171. return merchantService.OpenProduct(templateUserId, productOrderNo, product)
  172. }
  173. // OpenProduct 开通产品
  174. func CloseProduct(templateUserId int, productOrderNo string) (err error) {
  175. productOrder, err := order.GetProductOrderByUser(templateUserId, productOrderNo)
  176. if err != nil {
  177. logger.Error("获取产品订单信息失败:%v", err)
  178. return
  179. }
  180. product, err := merchantService.GetMerchantProductById(productOrder.ProductID)
  181. if err != nil {
  182. logger.Error("获取产品信息失败:%v", err)
  183. return
  184. }
  185. return merchantService.CloseProduct(templateUserId, productOrderNo, product)
  186. }
  187. //过期产品(套餐)
  188. // 退款关闭套餐
  189. func GetRelatePackage(info ProductDTO) (prodList []ProductDTO, err error) {
  190. switch info.Type {
  191. case "audio", "video":
  192. permissionIds, permissionErr := media.GetMediaPermissionMappingByMedia(info.Type, info.SourceId)
  193. if permissionErr != nil {
  194. logger.Error("获取媒体品种信息失败:%v", err)
  195. return
  196. }
  197. merchantProduct, pdErr := merchantService.GetProductListBySourceIds(permissionIds, "package")
  198. if pdErr != nil {
  199. return
  200. }
  201. for _, product := range merchantProduct {
  202. prodList = append(prodList, convertToProductDTO(product))
  203. }
  204. return
  205. case "report":
  206. reportInfo, reportErr := reportDomain.GetReportById(info.SourceId)
  207. if reportErr != nil {
  208. logger.Error("获取报告信息失败:%v", err)
  209. return
  210. }
  211. permissions := reportDomain.GetReportSecondPermissionsById(reportInfo.OrgId, reportInfo.Source)
  212. var permissionIds []int
  213. if len(permissions) > 0 {
  214. for _, permission := range permissions {
  215. permissionIds = append(permissionIds, permission.PermissionId)
  216. }
  217. permissionIds = append(permissionIds, permissions[0].PermissionId)
  218. }
  219. merchantProduct, pdErr := merchantService.GetProductListBySourceIds(permissionIds, "package")
  220. if pdErr != nil {
  221. return
  222. }
  223. for _, product := range merchantProduct {
  224. prodList = append(prodList, convertToProductDTO(product))
  225. }
  226. return
  227. default:
  228. err = exception.New(exception.ProductTypeError)
  229. return
  230. }
  231. }
  232. func GetProductListByProductType(productType string, permissionIds []int, templateUserId int) (total, latestId int64, productIds []int) {
  233. filterPermissionIds, riskLevel, err := reportService.CheckUserRisk(permissionIds, true, templateUserId)
  234. if err != nil {
  235. return
  236. }
  237. var dtoList []*ProductDTO
  238. productList, err := merchantService.GetProductListByProductType(productType)
  239. var wg sync.WaitGroup
  240. wg.Add(len(productList))
  241. for i := 0; i < len(productList); i++ {
  242. go func(merchantProduct merchantService.MerchantProductDTO) {
  243. defer wg.Done()
  244. product := convertToProductDTO(merchantProduct)
  245. product.RiskLevel, product.SourceTile, product.Abstract, product.CoverUrl, product.Src, product.PermissionNames, product.PermissionIds, err = GetProductRiskLevel(merchantProduct)
  246. if !compare(product.RiskLevel, riskLevel) {
  247. return
  248. }
  249. match := false
  250. for _, pdPermissionId := range product.PermissionIds {
  251. for _, permissionId := range filterPermissionIds {
  252. if pdPermissionId == permissionId {
  253. match = true
  254. break
  255. }
  256. }
  257. }
  258. if !match {
  259. return
  260. }
  261. dtoList = append(dtoList, &product)
  262. }(productList[i])
  263. }
  264. wg.Wait()
  265. total = int64(len(dtoList))
  266. var maxId int
  267. for i := 0; i < len(dtoList); i++ {
  268. productIds = append(productIds, dtoList[i].Id)
  269. if dtoList[i].Id > maxId {
  270. maxId = dtoList[i].Id
  271. }
  272. }
  273. latestId = int64(maxId)
  274. return
  275. }
  276. func compare(riskLevel, MatchRiskLevel string) bool {
  277. pRiskNum, riskErr := configService.ParseRiskLevel(riskLevel)
  278. if riskErr != nil {
  279. return false
  280. }
  281. riskLevelNum, riskErr := configService.ParseRiskLevel(MatchRiskLevel)
  282. if riskErr != nil {
  283. return false
  284. }
  285. if pRiskNum <= riskLevelNum {
  286. return true
  287. }
  288. return false
  289. }
  290. func ProductList(productIds []int, templateUserId int, info page.PageInfo) (dtoList []ProductDTO, err error) {
  291. var merchantProductList []merchantService.MerchantProductDTO
  292. merchantProductList, err = merchantService.GetProductPageByProductType(productIds, info)
  293. for _, product := range merchantProductList {
  294. productDTO := convertToProductDTO(product)
  295. productDTO.RiskLevel, productDTO.SourceTile, productDTO.Abstract, productDTO.CoverUrl, productDTO.Src, productDTO.PermissionNames, _, err = GetProductRiskLevel(product)
  296. dtoList = append(dtoList, productDTO)
  297. }
  298. var wg sync.WaitGroup
  299. wg.Add(len(dtoList))
  300. for i := 0; i < len(dtoList); i++ {
  301. go func(productDTO *ProductDTO) {
  302. defer wg.Done()
  303. productDTO.IsSubscribe = isSubscribeSignal(productDTO.Id, templateUserId)
  304. }(&dtoList[i])
  305. }
  306. return
  307. }
  308. func RangeProductList() (productIdMap map[string][]int, err error) {
  309. return merchantService.GetProductByProductType()
  310. }
  311. func ProductSearch(key string, templateUserId int, pageInfo page.PageInfo) (list []ProductDTO, err error) {
  312. var merchantProductList []merchantService.MerchantProductDTO
  313. var sourceIds []int
  314. var maxId int
  315. for _, product := range merchantProductList {
  316. if product.SourceId > maxId {
  317. maxId = product.SourceId
  318. }
  319. sourceIds = append(sourceIds, product.SourceId)
  320. }
  321. //reportList, err := reportDomain.SearchReportList(key, sourceIds, 1, len(sourceIds), int64(maxId))
  322. //mediaList, err := mediaDomain.SearchMediaList(key)
  323. for _, product := range merchantProductList {
  324. productDTO := convertToProductDTO(product)
  325. list = append(list, productDTO)
  326. }
  327. return
  328. }
  329. func convertReportToSearchDTO(report reportDomain.ReportDTO) (dto reportDomain.ProductSearchDTO) {
  330. return reportDomain.ProductSearchDTO{
  331. HighLight: report.Highlight[0],
  332. SourceId: report.ReportID,
  333. SourceType: "report",
  334. Score: report.Score,
  335. }
  336. }
  337. func convertMediaToSearchDTO(media mediaDomain.MediaDTO) (dto reportDomain.ProductSearchDTO) {
  338. return reportDomain.ProductSearchDTO{
  339. HighLight: media.Highlight[0],
  340. SourceId: media.MediaId,
  341. SourceType: media.MediaType,
  342. Score: media.Score,
  343. }
  344. }
  345. func SearchRelateProduct(key string, productIdMap map[string][]int) (list []reportDomain.ProductSearchDTO, err error) {
  346. var wg sync.WaitGroup
  347. wg.Add(2)
  348. go func() {
  349. defer wg.Done()
  350. docIds := productIdMap["report"]
  351. reports, reportErr := reportService.SearchReportProduct(key, docIds)
  352. if reportErr != nil {
  353. logger.Error("搜索相关报告失败:%v,key:%s", reportErr, key)
  354. return
  355. }
  356. for _, report := range reports {
  357. list = append(list, convertReportToSearchDTO(report))
  358. }
  359. }()
  360. go func() {
  361. defer wg.Done()
  362. docIds := append(productIdMap["audio"], productIdMap["video"]...)
  363. medias, mediaErr := mediaService.SearchMediaProduct(key, docIds)
  364. if mediaErr != nil {
  365. logger.Error("搜索相关媒体失败:%v,key:%s", mediaErr, key)
  366. return
  367. }
  368. for _, mediaInfo := range medias {
  369. list = append(list, convertMediaToSearchDTO(mediaInfo))
  370. }
  371. }()
  372. wg.Wait()
  373. sort.Slice(list, func(i, j int) bool {
  374. return list[i].Score > list[j].Score
  375. })
  376. return
  377. }
  378. func LatestId() (latestId int64) {
  379. return merchantService.LatestId()
  380. }
  381. func CountSearchPackageList(list []reportDomain.ProductSearchDTO) (total, latestId int64, permissionTotalMap map[int]*atomic.Int32) {
  382. productIdMap := make(map[string][]int, len(list))
  383. permissionTotalMap = make(map[int]*atomic.Int32)
  384. for _, product := range list {
  385. ids := productIdMap[product.SourceType]
  386. ids = append(ids, product.SourceId)
  387. productIdMap[product.SourceType] = ids
  388. }
  389. var wg sync.WaitGroup
  390. wg.Add(len(productIdMap))
  391. for key, ids := range productIdMap {
  392. go func(k string, ids []int) {
  393. defer wg.Done()
  394. var permissionMap map[int]int
  395. switch k {
  396. case "report":
  397. permissionMap = reportService.CountPermissionWeight(ids)
  398. case "audio", "video":
  399. permissionMap = mediaService.CountPermissionWeight(ids)
  400. }
  401. for permissionId, weight := range permissionMap {
  402. if permissionTotalMap[permissionId] == nil {
  403. permissionTotalMap[permissionId] = new(atomic.Int32)
  404. }
  405. permissionTotalMap[permissionId].Add(int32(weight))
  406. }
  407. }(key, ids)
  408. }
  409. wg.Wait()
  410. total = int64(len(permissionTotalMap))
  411. latestId = merchantService.LatestId()
  412. return
  413. }
  414. func ProductListBySort(isSignal bool, list []reportDomain.ProductSearchDTO, weightMap map[int]*atomic.Int32, templateUserId int, info page.PageInfo) (resultList []ProductDTO, err error) {
  415. var pdDTOS []merchantService.MerchantProductDTO
  416. pdDTOS, err = merchantService.ProductListBySort(isSignal, list, weightMap, info)
  417. var wg sync.WaitGroup
  418. wg.Add(len(pdDTOS))
  419. for _, pd := range pdDTOS {
  420. go func(pd merchantService.MerchantProductDTO) {
  421. defer wg.Done()
  422. productDTO := convertToProductDTO(pd)
  423. productDTO.RiskLevel, productDTO.SourceTile, productDTO.Abstract, productDTO.CoverUrl, productDTO.Src, productDTO.PermissionNames, _, err = GetProductRiskLevel(pd)
  424. productDTO.IsSubscribe = isSubscribeSignal(pd.Id, templateUserId)
  425. resultList = append(resultList, productDTO)
  426. }(pd)
  427. }
  428. wg.Wait()
  429. return
  430. }
  431. func isSubscribeSignal(productId int, templateUserId int) (isSubscribe bool) {
  432. subscribeList, subErr := user.GetUserSubscribe([]int{productId}, templateUserId)
  433. if subErr != nil {
  434. logger.Error("获取用户订阅状态失败:%v", subErr)
  435. return false
  436. } else {
  437. if len(subscribeList) == 0 {
  438. logger.Error("用户未订阅单品,productId:%v", productId)
  439. return false
  440. } else {
  441. return subscribeList[0].Status == merchantDao.SubscribeValid
  442. }
  443. }
  444. }