product_service.go 16 KB

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