user_service.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. package user
  2. import (
  3. "errors"
  4. logger "eta/eta_mini_ht_api/common/component/log"
  5. "eta/eta_mini_ht_api/common/exception"
  6. permissionService "eta/eta_mini_ht_api/domian/config"
  7. analystService "eta/eta_mini_ht_api/domian/financial_analyst"
  8. userService "eta/eta_mini_ht_api/domian/user"
  9. merchantDao "eta/eta_mini_ht_api/models/merchant"
  10. "eta/eta_mini_ht_api/service/config"
  11. "gorm.io/gorm"
  12. "sort"
  13. "sync"
  14. "time"
  15. )
  16. const (
  17. RiskValid = "valid"
  18. RiskExpired = "expired"
  19. RiskUnTest = "unTest"
  20. SubscribeExpired = "expired"
  21. UnSubscribe = "unSubscribe"
  22. Subscribing = "Subscribing"
  23. )
  24. type User struct {
  25. Id int `json:"id"`
  26. Username string `json:"username"`
  27. AreaCode string `json:"areaCode"`
  28. Mobile string `json:"mobile"`
  29. OpenId string `json:"openId,omitempty"`
  30. }
  31. type AnalystDetail struct {
  32. AnalystName string `json:"AnalystName"`
  33. HeadImgUrl string `json:"HeadImgUrl"`
  34. Introduction string `json:"Introduction"`
  35. Followed string `json:"Followed"`
  36. Position string `json:"Position"`
  37. InvestmentCertificate string `json:"InvestmentCertificate"`
  38. ProfessionalCertificate string `json:"ProfessionalCertificate"`
  39. }
  40. type UserProfile struct {
  41. Mobile string `json:"mobile"`
  42. RiskLevel string `json:"riskLevel"`
  43. RiskLevelStatus string `json:"riskLevelStatus"`
  44. UserName string `json:"userName"`
  45. }
  46. func CheckUserRiskMatchStatus(userId int) (riskLevel string, userRiskLevelStatus string, err error) {
  47. if userId <= 0 {
  48. err = exception.New(exception.IllegalTemplateUserId)
  49. return
  50. }
  51. userProfile, userErr := GetUserProfile(userId)
  52. if userErr != nil {
  53. if errors.Is(userErr, gorm.ErrRecordNotFound) {
  54. err = exception.New(exception.TemplateUserNotFound)
  55. } else {
  56. err = exception.New(exception.TemplateUserFoundFailed)
  57. }
  58. logger.Error("获取临时客户信息失败:%v", err)
  59. return
  60. }
  61. userRiskLevelStatus = userProfile.RiskLevelStatus
  62. //获取产品风险等级
  63. if userProfile.RiskLevelStatus == RiskUnTest {
  64. logger.Warn("客户未做风险等级测评,mobile:%v", userProfile.Mobile)
  65. }
  66. if userProfile.RiskLevelStatus == RiskExpired {
  67. logger.Warn("客户风险等级已过期,mobile:%v", userProfile.Mobile)
  68. }
  69. if userProfile.RiskLevel != "" && userProfile.RiskLevelStatus == RiskValid {
  70. var mapping permissionService.CustomerProductRiskMappingDTO
  71. mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel)
  72. if err != nil {
  73. logger.Error("查询产品风险等级映射失败:%v", err)
  74. return
  75. }
  76. riskLevel = mapping.ProductRiskLevel
  77. }
  78. return
  79. }
  80. // GetRiskLevelPermissionList 删选掉没有配置风险等级的品种,并校验客户的风险等级,riskLevel只有在客户
  81. func GetRiskLevelPermissionList(permissionIds []int, isLogin bool, userId int) (filterPermissionIds []int, riskLevel string, userRiskStatus string, err error) {
  82. if isLogin {
  83. userProfile, userErr := GetUserProfile(userId)
  84. if userErr != nil {
  85. if errors.Is(userErr, gorm.ErrRecordNotFound) {
  86. err = exception.New(exception.TemplateUserNotFound)
  87. } else {
  88. err = exception.New(exception.TemplateUserFoundFailed)
  89. }
  90. logger.Error("获取临时客户信息失败:%v", err)
  91. return
  92. }
  93. var permissionList []permissionService.PermissionDTO
  94. if len(permissionIds) == 0 {
  95. //获取所有设置风险等级的品种
  96. permissionList, err = permissionService.GetPermissionListWithRisk()
  97. } else {
  98. //更具id过滤设置了风险等级的品种
  99. permissionList, err = permissionService.GetPermissionListByIds(permissionIds)
  100. }
  101. if err != nil {
  102. logger.Error("查询有风险等级的品种列表失败:%v", err)
  103. return
  104. }
  105. userRiskStatus = userProfile.RiskLevelStatus
  106. //获取产品风险等级
  107. if userProfile.RiskLevelStatus == RiskUnTest {
  108. logger.Warn("客户未做风险等级测评,mobile:%v", userProfile.Mobile)
  109. //err = exception.New(exception.RiskUnTestError)
  110. }
  111. if userProfile.RiskLevelStatus == RiskExpired {
  112. logger.Warn("客户风险等级已过期,mobile:%v", userProfile.Mobile)
  113. //err = exception.New(exception.RiskExpiredError)
  114. }
  115. if userProfile.RiskLevel != "" && userProfile.RiskLevelStatus == RiskValid {
  116. var mapping permissionService.CustomerProductRiskMappingDTO
  117. mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel)
  118. if err != nil {
  119. logger.Error("查询产品风险等级映射失败:%v", err)
  120. return
  121. }
  122. permissionList = filterPermissionsByRisk(permissionList, mapping.ProductRiskLevel)
  123. riskLevel = mapping.ProductRiskLevel
  124. }
  125. for _, permission := range permissionList {
  126. filterPermissionIds = append(filterPermissionIds, permission.PermissionId)
  127. }
  128. return
  129. } else { //没有登录的时候展示所有设置了风险等级的品种报告,筛选的时候过滤传入ID中没有设置风险等级的品种
  130. var permissionList []permissionService.PermissionDTO
  131. if len(permissionIds) == 0 {
  132. //获取所有设置风险等级的品种
  133. permissionList, err = permissionService.GetPermissionListWithRisk()
  134. } else {
  135. //更具id过滤设置了风险等级的品种
  136. permissionList, err = permissionService.GetPermissionListByIds(permissionIds)
  137. }
  138. if err != nil {
  139. logger.Error("查询有风险等级的品种列表失败:%v", err)
  140. return
  141. }
  142. for _, permission := range permissionList {
  143. filterPermissionIds = append(filterPermissionIds, permission.PermissionId)
  144. }
  145. return
  146. }
  147. }
  148. func filterPermissionsByRisk(permissionList []permissionService.PermissionDTO, riskLevel string) (resultList []permissionService.PermissionDTO) {
  149. if riskLevel != "" {
  150. riskLevelNum, err := config.ParseRiskLevel(riskLevel)
  151. if err != nil {
  152. logger.Error("风险等级解析失败:%v", err)
  153. return
  154. }
  155. for _, permission := range permissionList {
  156. pRiskNum, riskErr := config.ParseRiskLevel(permission.RiskLevel)
  157. if riskErr != nil {
  158. logger.Error("解析品种风险等级失败 permission:%d,risk:%v", permission.PermissionId, permission.RiskLevel)
  159. continue
  160. }
  161. if pRiskNum <= riskLevelNum {
  162. resultList = append(resultList, permission)
  163. }
  164. }
  165. } else {
  166. resultList = permissionList
  167. }
  168. return
  169. }
  170. func convertUserDTOToProfile(dto userService.UserDTO) (profile UserProfile) {
  171. profile = UserProfile{
  172. Mobile: dto.Mobile,
  173. RiskLevel: dto.RiskLevel,
  174. UserName: dto.Username,
  175. }
  176. if profile.UserName == "" {
  177. profile.UserName = dto.Mobile
  178. }
  179. if dto.RiskLevel == "" {
  180. profile.RiskLevelStatus = RiskUnTest
  181. return
  182. }
  183. date, err := time.Parse(time.DateOnly, dto.RiskValidEndDate)
  184. if err != nil {
  185. logger.Error("解析日期失败:%v", err)
  186. profile.RiskLevelStatus = RiskExpired
  187. return
  188. }
  189. currentDate := time.Now().Truncate(24 * time.Hour)
  190. expiryDate := date.Truncate(24 * time.Hour)
  191. if expiryDate.Before(currentDate) {
  192. profile.RiskLevelStatus = RiskExpired
  193. return
  194. }
  195. profile.RiskLevelStatus = RiskValid
  196. return
  197. }
  198. func GetUserProfile(userId int) (userProfile UserProfile, err error) {
  199. userDTO, err := userService.GetUserById(userId)
  200. if err != nil {
  201. if errors.Is(err, gorm.ErrRecordNotFound) {
  202. logger.Error("用户不存在,用户Id:%d", userId)
  203. err = exception.New(exception.TemplateUserNotFound)
  204. } else {
  205. logger.Error("获取用户信息失败:%v", err)
  206. err = exception.New(exception.TemplateUserFoundFailed)
  207. }
  208. return
  209. }
  210. userProfile = convertUserDTOToProfile(userDTO)
  211. return
  212. }
  213. func GetAnalystDetail(userId int, analystId int) (analystDetail AnalystDetail, err error) {
  214. analyst, err := analystService.GetAnalystById(analystId)
  215. if err != nil {
  216. logger.Error("研究员信息不存在:%v", err)
  217. err = exception.New(exception.AnalystNotFound)
  218. }
  219. analystDetail = convertToAnalystDetail(analyst)
  220. //研究员关注状态
  221. analystDetail.Followed = userService.GetFollowed(userId, analystId)
  222. return
  223. }
  224. func convertToAnalystDetail(dto analystService.FinancialAnalystDTO) AnalystDetail {
  225. return AnalystDetail{
  226. AnalystName: dto.Name,
  227. HeadImgUrl: dto.HeadImgUrl,
  228. Introduction: dto.Introduction,
  229. Position: dto.Position,
  230. InvestmentCertificate: dto.InvestmentCertificate,
  231. ProfessionalCertificate: dto.ProfessionalCertificate,
  232. }
  233. }
  234. func FollowAnalystsByName(userId int, analystNames []string, followType string) (err error) {
  235. var followlist []userService.FollowDTO
  236. for _, analystName := range analystNames {
  237. FinancialAnalystDTO, followErr := analystService.GetAnalystByName(analystName)
  238. if followErr != nil {
  239. err = exception.New(exception.AnalystNotFound)
  240. }
  241. if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
  242. continue
  243. }
  244. followDTO := userService.FollowDTO{
  245. UserId: userId,
  246. AnalystId: FinancialAnalystDTO.Id,
  247. AnalystName: FinancialAnalystDTO.Name,
  248. FollowType: followType,
  249. }
  250. followlist = append(followlist, followDTO)
  251. }
  252. err = userService.FollowAnalystsByName(userId, followlist, followType)
  253. if err != nil {
  254. logger.Error("批量关注研究员失败:%v", err)
  255. err = exception.New(exception.BatchFollowingAnalystFailed)
  256. }
  257. return
  258. }
  259. func CheckFollowStatusByNames(userId int, names []string) (list []userService.FollowDTO, err error) {
  260. list, err = userService.CheckFollowStatusByNames(userId, names)
  261. if err != nil {
  262. logger.Error("获取关注状态失败:%v", err)
  263. err = exception.New(exception.CheckFollowStatusByNamesFailed)
  264. }
  265. return
  266. }
  267. func FollowAnalyst(userId int, analystId int, followType string) (err error) {
  268. FinancialAnalystDTO, err := analystService.GetAnalystById(analystId)
  269. if err != nil {
  270. err = exception.New(exception.AnalystNotFound)
  271. }
  272. if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
  273. err = exception.New(exception.AnalystNotFound)
  274. return
  275. }
  276. followDTO := userService.FollowDTO{
  277. UserId: userId,
  278. AnalystId: analystId,
  279. AnalystName: FinancialAnalystDTO.Name,
  280. FollowType: followType,
  281. }
  282. err = userService.FollowAnalyst(followDTO)
  283. if err != nil {
  284. logger.Error("关注研究员失败:%v", err)
  285. err = exception.New(exception.UserFollowAnalystFailed)
  286. }
  287. return
  288. }
  289. func GetFollowingAnalystList(userId int) (analysts []FollowAnalystDTO, err error) {
  290. logger.Info("用户ID:%d", userId)
  291. dtoList, err := userService.GetFollowingAnalystList(userId)
  292. if err != nil {
  293. logger.Error("获取关注列表失败:%v", err)
  294. err = exception.New(exception.GetFollowingAnalystListFailed)
  295. return
  296. }
  297. analysts, err = convertToAnalystList(dtoList)
  298. var wg sync.WaitGroup
  299. wg.Add(len(analysts))
  300. for i := 0; i < len(analysts); i++ {
  301. go func(followDTo *FollowAnalystDTO) {
  302. defer wg.Done()
  303. followDTo.NeedNotice = userService.NeedNotice(userId, followDTo.AnalystId)
  304. var analystsDTO analystService.FinancialAnalystDTO
  305. analystsDTO, err = analystService.GetAnalystById(followDTo.AnalystId)
  306. if err != nil {
  307. logger.Error("获取研究员信息失败")
  308. } else {
  309. followDTo.HeadImgUrl = analystsDTO.HeadImgUrl
  310. }
  311. }(&analysts[i])
  312. }
  313. wg.Wait()
  314. //排序
  315. sort.Slice(analysts, func(i, j int) bool {
  316. // 首先按 NeedNotice 排序
  317. if analysts[i].NeedNotice == analysts[j].NeedNotice {
  318. // 对于 NeedNotice 相同的情况下,进行倒序排列
  319. return analysts[i].FollowedTime.After(analysts[j].FollowedTime)
  320. }
  321. // NeedNotice 为 true 的排在 false 的前面
  322. return analysts[i].NeedNotice
  323. })
  324. //if err != nil {
  325. // logger.Error("转换研究员列表失败:%v", err)
  326. // err = exception.New(exception.TransferFollowingAnalystListFailed)
  327. //}
  328. return
  329. }
  330. func GetUnReadMessageList(userId int) (messages []userService.MyMessage, err error) {
  331. messages, err = userService.GetUnReadMessageList(userId)
  332. if err != nil {
  333. err = exception.New(exception.GetUserUnReadMsgFailed)
  334. }
  335. return
  336. }
  337. func ReadMessage(userId int, messageId int) bool {
  338. return userService.ReadMessage(userId, messageId)
  339. }
  340. func ReadMessages(userId int, analystId int) bool {
  341. return userService.ReadMessages(userId, analystId)
  342. }
  343. type FollowAnalystDTO struct {
  344. AnalystId int `json:"analystId"`
  345. AnalystName string `json:"analystName"`
  346. HeadImgUrl string `json:"headImgUrl"`
  347. FollowedTime time.Time `json:"followedTime"`
  348. NeedNotice bool `json:"needNotice"`
  349. }
  350. func convertToAnalystList(dtoList []userService.FollowDTO) (list []FollowAnalystDTO, err error) {
  351. for _, dto := range dtoList {
  352. analyst := FollowAnalystDTO{
  353. AnalystId: dto.AnalystId,
  354. AnalystName: dto.AnalystName,
  355. FollowedTime: dto.FollowedTime,
  356. NeedNotice: false,
  357. }
  358. list = append(list, analyst)
  359. }
  360. return
  361. }
  362. func FollowAnalystByName(userId int, analystName string, followType string) (err error) {
  363. FinancialAnalystDTO, err := analystService.GetAnalystByName(analystName)
  364. if err != nil {
  365. err = exception.New(exception.AnalystNotFound)
  366. }
  367. if FinancialAnalystDTO.Id == 0 || FinancialAnalystDTO.Name == "" {
  368. err = exception.New(exception.AnalystNotFound)
  369. return
  370. }
  371. followDTO := userService.FollowDTO{
  372. UserId: userId,
  373. AnalystId: FinancialAnalystDTO.Id,
  374. AnalystName: FinancialAnalystDTO.Name,
  375. FollowType: followType,
  376. }
  377. err = userService.FollowAnalyst(followDTO)
  378. if err != nil {
  379. logger.Error("关注研究员失败:%v", err)
  380. err = exception.New(exception.UserFollowAnalystFailed)
  381. }
  382. return
  383. }
  384. func FeedBack(userId int, mobile string, message string) (err error) {
  385. feedback := userService.FeedbackDTO{
  386. UserId: userId,
  387. Mobile: mobile,
  388. Message: message,
  389. }
  390. err = userService.FeedBack(feedback)
  391. if err != nil {
  392. err = exception.New(exception.FeedBackError)
  393. }
  394. return
  395. }
  396. func GetUserByMobile(mobile string) (user User, err error) {
  397. userDTO, err := userService.GetUserByMobile(mobile)
  398. if err != nil {
  399. if errors.Is(err, gorm.ErrRecordNotFound) {
  400. err = exception.New(exception.TemplateUserNotFound)
  401. } else {
  402. err = exception.New(exception.TemplateUserFoundFailed)
  403. }
  404. }
  405. user = convertToUser(userDTO)
  406. return
  407. }
  408. func GetUserByOpenId(openId string) (user User, err error) {
  409. userDTO, err := userService.GetUserByOpenId(openId)
  410. if err != nil {
  411. return
  412. }
  413. user = convertToUser(userDTO)
  414. return
  415. }
  416. func convertToUser(userDTO userService.UserDTO) User {
  417. return User{
  418. Id: userDTO.Id,
  419. Username: userDTO.Username,
  420. OpenId: userDTO.OpenId,
  421. AreaCode: userDTO.AreaCode,
  422. Mobile: userDTO.Mobile,
  423. }
  424. }
  425. func GetUserByTemplateUserId(templateUserId int) (officialUser userService.OfficialUserDTO, err error) {
  426. officialUser, err = userService.GetUserByTemplateUserId(templateUserId)
  427. if err != nil {
  428. if errors.Is(err, gorm.ErrRecordNotFound) {
  429. err = exception.New(exception.OfficialUserNotFound)
  430. logger.Info("用户未开户:%v", templateUserId)
  431. } else {
  432. err = exception.NewWithException(exception.OfficialUserFoundError, err.Error())
  433. logger.Error("获取正式用户信息失败:%v", err)
  434. }
  435. }
  436. return
  437. }
  438. func GetUserScribeStatus(productId int, templateUserId int) (subscribe string) {
  439. userSubscribe, err := userService.GetUserSubscribe([]int{productId}, templateUserId)
  440. if err != nil {
  441. logger.Error("获取用户订阅状态失败:%v", err)
  442. return UnSubscribe
  443. }
  444. if len(userSubscribe) == 0 {
  445. return UnSubscribe
  446. }
  447. if userSubscribe[0].ProductType != merchantDao.Package && userSubscribe[0].Status == merchantDao.SubscribeExpired {
  448. logger.Error("用户订阅状态异常:%v,单品状态为过期,productId:%d", productId)
  449. return UnSubscribe
  450. }
  451. switch userSubscribe[0].Status {
  452. case
  453. merchantDao.SubscribeClose:
  454. return UnSubscribe
  455. case merchantDao.SubscribeExpired:
  456. return SubscribeExpired
  457. case merchantDao.SubscribeValid:
  458. return Subscribing
  459. default:
  460. return UnSubscribe
  461. }
  462. }