蛋蛋星球-制度模式
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
17 KiB

  1. package egg_energy
  2. import (
  3. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  4. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  5. "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
  6. "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
  7. "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule"
  8. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  9. "code.fnuoos.com/EggPlanet/egg_system_rules.git/svc/sys_cfg"
  10. egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils"
  11. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache"
  12. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/es"
  13. zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx"
  14. es2 "code.fnuoos.com/go_rely_warehouse/zyos_go_es.git/es"
  15. "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
  16. "encoding/json"
  17. "errors"
  18. "fmt"
  19. "github.com/olivere/elastic/v7"
  20. "github.com/shopspring/decimal"
  21. "strings"
  22. "time"
  23. "xorm.io/xorm"
  24. )
  25. // SettlementGiveActivityCoin 结算观看激励广告得到蛋蛋积分
  26. func SettlementGiveActivityCoin(engine *xorm.Engine, user model.User, ecpm string, ch *rabbit.Channel) (rewardValue float64, err error) {
  27. egg_system_rules.FilePutContents("SettlementGiveActivityCoin", egg_system_rules.SerializeStr(user))
  28. uid := user.Id
  29. now := time.Now()
  30. //1、查找 `egg_energy_basic_setting` 基础设置
  31. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  32. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  33. "key": "is_open",
  34. "value": 1,
  35. })
  36. if err != nil {
  37. return
  38. }
  39. if eggEnergyBasicSetting == nil {
  40. err = errors.New("蛋蛋能量设置未开启!")
  41. return
  42. }
  43. var videoRewardSystem *md2.VideoRewardSystemStruct
  44. err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem)
  45. if err != nil {
  46. return
  47. }
  48. if eggEnergyBasicSetting.VideoRewardIsOpen == 1 {
  49. if videoRewardSystem.RewardTotalNum == "" || videoRewardSystem.IntervalMinutes == "" || videoRewardSystem.EachRoundHour == "" {
  50. err = errors.New("视屏奖励机制设置未完全!")
  51. return
  52. }
  53. var rewardSystem []*md2.RewardSystemStruct
  54. err = json.Unmarshal([]byte(eggEnergyBasicSetting.RewardSystem), &rewardSystem)
  55. if err != nil {
  56. return
  57. }
  58. if len(rewardSystem) == 0 {
  59. err = errors.New("未设置奖励机制!")
  60. return
  61. }
  62. go dealEcpm(user, ecpm, ch) //TODO::协程处理ecpm的变化
  63. //TODO::奖励多少个活跃积分(根据ecpm, 新用户机制, 蛋蛋分机制)
  64. sysCfgDb := sys_cfg.NewSysCfgDb(engine)
  65. videoRewardUnitPrice := sysCfgDb.SysCfgGetWithDb(enum.VideoRewardUnitPrice)
  66. if videoRewardUnitPrice != "" { //处理ecpm
  67. var coin model.VirtualCoin
  68. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  69. if err != nil {
  70. return rewardValue, err
  71. }
  72. activePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  73. videoRewardUnitPriceValue, _ := decimal.NewFromString(videoRewardUnitPrice)
  74. rewardValue, _ = videoRewardUnitPriceValue.Mul(activePointsCoinExchangeRatioValue).Float64()
  75. } else {
  76. rewardValue = egg_system_rules.StrToFloat64(videoRewardSystem.RewardValue)
  77. }
  78. var newUserRewardRules *md2.NewUserRewardRules
  79. err = json.Unmarshal([]byte(eggEnergyBasicSetting.NewUserIncentiveRules), &newUserRewardRules)
  80. if err != nil {
  81. return
  82. }
  83. userCreateAt := egg_system_rules.String2Time(user.CreateAt)
  84. if int(now.Sub(userCreateAt).Hours()/24) <= newUserRewardRules.ContinueDays { //处理新用户机制
  85. rewardValue *= newUserRewardRules.RewardCoefficient
  86. }
  87. score := 60.00
  88. esIndex := es.GetLatestEffectiveIndexFromAlias(now)
  89. esIndexName := md.EggEnergyUserEggScoreEsAlias + "_" + esIndex
  90. results, err1 := es2.FirstDoc(esIndexName, esIndex+"_"+egg_system_rules.Int64ToStr(user.Id))
  91. if err1 != nil {
  92. if !elastic.IsNotFound(err1) {
  93. return rewardValue, err1
  94. }
  95. }
  96. if !elastic.IsNotFound(err1) {
  97. var doc md.EggEnergyUserEggScoreEs
  98. err = json.Unmarshal(results.Source, &doc)
  99. if err != nil {
  100. return
  101. }
  102. score = doc.ScoreValue
  103. }
  104. eggPointPartitionCoefficientManagementDb := implement.NewEggPointPartitionCoefficientManagementDb(engine)
  105. eggPointPartitionCoefficientManagements, err1 := eggPointPartitionCoefficientManagementDb.EggPointPartitionCoefficientManagementGetAll()
  106. if err1 != nil {
  107. return rewardValue, err1
  108. }
  109. for _, v := range *eggPointPartitionCoefficientManagements { //处理蛋蛋分机制
  110. if egg_system_rules.StrToFloat64(v.StartScore) <= score && egg_system_rules.StrToFloat64(v.EndScore) > score {
  111. rewardValue *= egg_system_rules.StrToFloat64(v.Coefficient)
  112. }
  113. }
  114. //处理圈层奖励
  115. var rewardSystemMap = map[int]*md2.RewardSystemStruct{}
  116. for _, v := range rewardSystem {
  117. rewardSystemMap[v.Level] = v
  118. }
  119. publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine)
  120. publicPlatoonUserRelation, err1 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{
  121. "key": "uid",
  122. "value": uid,
  123. })
  124. if err1 != nil {
  125. return rewardValue, err1
  126. }
  127. var rewardFather []struct {
  128. Uid int64 `json:"uid"` //用户id
  129. RewardValue float64 `json:"reward_value"` //奖励值
  130. }
  131. var fatherUids []string
  132. if publicPlatoonUserRelation != nil {
  133. fatherUids = strings.Split(publicPlatoonUserRelation.FatherUid, "-")
  134. }
  135. for k, id := range fatherUids {
  136. tmpOneCirclesPublicPlatoonUserRelation, err11 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{
  137. "key": "id",
  138. "value": id,
  139. })
  140. if err11 != nil {
  141. return rewardValue, err11
  142. }
  143. if tmpOneCirclesPublicPlatoonUserRelation == nil {
  144. continue
  145. }
  146. if tmpOneCirclesPublicPlatoonUserRelation.Uid <= 0 {
  147. //待填充位
  148. continue
  149. }
  150. fatherUid := egg_system_rules.Int64ToStr(tmpOneCirclesPublicPlatoonUserRelation.Uid)
  151. fatherReward := rewardSystemMap[k+1]
  152. //TODO::判断是否活跃
  153. var m model.EggSignIn
  154. has, err33 := engine.Where("uid =?", fatherUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m)
  155. if err33 != nil {
  156. return rewardValue, err33
  157. }
  158. if !has {
  159. //不活跃不需要奖励
  160. continue
  161. }
  162. //判断是否满足奖励条件
  163. userRelateDb := implement.NewUserRelateDb(engine)
  164. userCount, _, err2 := userRelateDb.SumUserRelateByParentUid(fatherUid)
  165. if err2 != nil {
  166. return rewardValue, err2
  167. }
  168. if fatherReward != nil && userCount >= egg_system_rules.StrToInt64(fatherReward.RewardCondition) {
  169. fatherRewardValue := rewardValue * (egg_system_rules.StrToFloat64(fatherReward.RewardValue) / 100)
  170. rewardFather = append(rewardFather, struct {
  171. Uid int64 `json:"uid"` //用户id
  172. RewardValue float64 `json:"reward_value"` //奖励值
  173. }{
  174. Uid: egg_system_rules.StrToInt64(fatherUid),
  175. RewardValue: fatherRewardValue,
  176. })
  177. }
  178. }
  179. //处理直推奖励
  180. var directPushRewardSetting *md2.DirectPushRewardSettingStruct
  181. err = json.Unmarshal([]byte(eggEnergyBasicSetting.DirectPushReward), &directPushRewardSetting)
  182. if err != nil {
  183. return
  184. }
  185. fatherRewardValue := rewardValue * (egg_system_rules.StrToFloat64(directPushRewardSetting.RewardRateValue) / 100)
  186. if directPushRewardSetting.MemberSelfIsOpenGetTeamReward == "1" {
  187. fmt.Println("user:::::::::::::", user)
  188. var m model.EggSignIn
  189. has, err44 := engine.Where("uid =?", user.ParentUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m)
  190. if err44 != nil {
  191. return rewardValue, err44
  192. }
  193. if !has {
  194. //不活跃不需要奖励
  195. fatherRewardValue = 0
  196. }
  197. }
  198. session := engine.NewSession()
  199. defer func() {
  200. session.Close()
  201. if err := recover(); err != nil {
  202. _ = zhios_order_relate_logx.Error(err)
  203. }
  204. }()
  205. session.Begin()
  206. //给相应的用户加上"个人"活跃积分
  207. err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{
  208. Kind: "add",
  209. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardPersonalActiveCoin),
  210. TransferType: int(enum.EggEnergyWatchAdRewardPersonalActiveCoin),
  211. CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId,
  212. Uid: uid,
  213. Amount: rewardValue,
  214. })
  215. if err != nil {
  216. _ = session.Rollback()
  217. fmt.Println("err:::::2222", err)
  218. return rewardValue, err
  219. }
  220. //给相应的用户上级加上"团队"活跃积分
  221. if fatherRewardValue > 0 {
  222. err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{
  223. Kind: "add",
  224. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardFansActiveCoin),
  225. TransferType: int(enum.EggEnergyWatchAdRewardFansActiveCoin),
  226. CoinId: eggEnergyBasicSetting.TeamEggPointsCoinId,
  227. Uid: user.ParentUid,
  228. Amount: fatherRewardValue,
  229. })
  230. if err != nil {
  231. _ = session.Rollback()
  232. fmt.Println("err:::::2222", err)
  233. return rewardValue, err
  234. }
  235. }
  236. //给相应的用户加上"团队"活跃积分
  237. for _, vv := range rewardFather {
  238. if vv.RewardValue > 0 {
  239. //TODO::推入rabbitmq 异步处理
  240. ch.Publish(md2.EggEnergyExchange, md.DealUserVirtualCoinReq{
  241. Kind: "add",
  242. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardTeamActiveCoin),
  243. TransferType: int(enum.EggEnergyWatchAdRewardTeamActiveCoin),
  244. CoinId: eggEnergyBasicSetting.TeamEggPointsCoinId,
  245. Uid: vv.Uid,
  246. Amount: vv.RewardValue,
  247. }, md2.EggEnergyRoutKeyForSettlementPublicGiveActivityCoin)
  248. }
  249. }
  250. err = session.Commit()
  251. if err != nil {
  252. _ = session.Rollback()
  253. return rewardValue, errors.New("事务提交失败")
  254. }
  255. }
  256. //增加 egg_user_watch_records 记录
  257. eggEnergyUserWatchRecordsDb := implement.NewEggEnergyUserWatchRecordsDb(engine)
  258. eggEnergyUserWatchRecords, err1 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsGetOneByParams(map[string]interface{}{
  259. "key": "uid",
  260. "value": uid,
  261. })
  262. if err1 != nil {
  263. return rewardValue, err1
  264. }
  265. if eggEnergyUserWatchRecords == nil {
  266. residueWatchAdNum := egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1
  267. if residueWatchAdNum < 0 {
  268. residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)
  269. }
  270. eggEnergyUserWatchRecords = &model.EggEnergyUserWatchRecords{
  271. Uid: uid,
  272. NextWatchAdDate: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))),
  273. ResidueWatchAdNum: egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1,
  274. CreateAt: now.Format("2006-01-02 15:04:05"),
  275. UpdateAt: now.Format("2006-01-02 15:04:05"),
  276. }
  277. _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsInsert(eggEnergyUserWatchRecords)
  278. if err2 != nil {
  279. return rewardValue, err2
  280. }
  281. } else {
  282. residueWatchAdNum := eggEnergyUserWatchRecords.ResidueWatchAdNum - 1
  283. nextWatchAdDate := eggEnergyUserWatchRecords.NextWatchAdDate
  284. if residueWatchAdNum == 0 { //最后一条广告
  285. residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)
  286. }
  287. if residueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)-1 { //第一条广告
  288. nextWatchAdDate = now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour)))
  289. }
  290. eggEnergyUserWatchRecords.ResidueWatchAdNum = residueWatchAdNum
  291. eggEnergyUserWatchRecords.NextWatchAdDate = nextWatchAdDate
  292. _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsUpdate(eggEnergyUserWatchRecords.Id, eggEnergyUserWatchRecords, "residue_watch_ad_num", "next_watch_ad_date")
  293. if err2 != nil {
  294. return rewardValue, err2
  295. }
  296. }
  297. redisKey := fmt.Sprintf(md2.UserNextWatchAdDate, uid)
  298. var watchAdDate string
  299. if eggEnergyUserWatchRecords.ResidueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) {
  300. if eggEnergyUserWatchRecords.NextWatchAdDate.Before(time.Now()) {
  301. watchAdDate = ""
  302. } else {
  303. watchAdDate = eggEnergyUserWatchRecords.NextWatchAdDate.Format("2006-01-02 15:04:05")
  304. }
  305. } else {
  306. watchAdDate = time.Now().Add(time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.IntervalMinutes)) * time.Second).Format("2006-01-02 15:04:05")
  307. }
  308. cache.SetEx(redisKey, watchAdDate, 60*60*24) //TODO::默认缓存1小时
  309. return
  310. }
  311. func dealEcpm(user model.User, ecpm string, ch *rabbit.Channel) {
  312. //查找缓存中的ecpm值和当前的ecpm是否一致
  313. key := fmt.Sprintf(md.UserEcpmCacheKey, user.Id)
  314. ecpmCacheValue, _ := cache.GetString(key)
  315. if ecpmCacheValue == "" || ecpmCacheValue != ecpm {
  316. //更新缓存值
  317. cache.SetEx(key, ecpm, md.UserEcpmCacheTime)
  318. //TODO::推入rabbitmq 异步处理
  319. ch.Publish(md2.EggEnergyExchange, md.DealUserEcpmReq{
  320. Uid: user.Id,
  321. Ecpm: ecpm,
  322. }, md2.EggEnergyRoutKeyForDealUserEcpm)
  323. }
  324. }
  325. func ActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error) {
  326. amountValue, _ := decimal.NewFromString(amount)
  327. //1、查找 `egg_energy_basic_setting` 基础设置
  328. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  329. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  330. "key": "is_open",
  331. "value": 1,
  332. })
  333. if err != nil {
  334. return
  335. }
  336. if eggEnergyBasicSetting == nil {
  337. err = errors.New("蛋蛋能量设置未开启!")
  338. return
  339. }
  340. var coin model.VirtualCoin
  341. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  342. if err != nil {
  343. return
  344. }
  345. personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  346. //2、判断个人蛋蛋积分是否足够
  347. var personUserVirtualAmount model.UserVirtualAmount
  348. _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount)
  349. if err != nil {
  350. fmt.Println("err:::::1111", err)
  351. return
  352. }
  353. personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount)
  354. needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue)
  355. needVirtualAmount, _ := amountValue.Mul(personActivePointsCoinExchangeRatioValue).Float64()
  356. if personUserVirtualAmountValue.LessThan(needVirtualAmountValue) {
  357. err = errors.New("当前蛋蛋积分不足!")
  358. return
  359. }
  360. //3、扣除对应个人蛋蛋积分
  361. session := engine.NewSession()
  362. defer func() {
  363. session.Close()
  364. if err := recover(); err != nil {
  365. _ = zhios_order_relate_logx.Error(err)
  366. }
  367. }()
  368. session.Begin()
  369. //给相应的用户加上"个人"活跃积分
  370. err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{
  371. Kind: "sub",
  372. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggPointCoinToAliPayRealName),
  373. TransferType: int(enum.EggPointCoinToAliPayRealName),
  374. CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId,
  375. Uid: uid,
  376. Amount: needVirtualAmount,
  377. })
  378. if err != nil {
  379. _ = session.Rollback()
  380. fmt.Println("err:::::2222", err)
  381. return err
  382. }
  383. err = session.Commit()
  384. if err != nil {
  385. _ = session.Rollback()
  386. return errors.New("事务提交失败")
  387. }
  388. return
  389. }
  390. func CheckActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error, isCan bool) {
  391. amountValue, _ := decimal.NewFromString(amount)
  392. //1、查找 `egg_energy_basic_setting` 基础设置
  393. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  394. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  395. "key": "is_open",
  396. "value": 1,
  397. })
  398. if err != nil {
  399. return
  400. }
  401. if eggEnergyBasicSetting == nil {
  402. err = errors.New("蛋蛋能量设置未开启!")
  403. return
  404. }
  405. var coin model.VirtualCoin
  406. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  407. if err != nil {
  408. return
  409. }
  410. personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  411. //2、判断个人蛋蛋积分是否足够
  412. var personUserVirtualAmount model.UserVirtualAmount
  413. _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount)
  414. if err != nil {
  415. fmt.Println("err:::::1111", err)
  416. return
  417. }
  418. personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount)
  419. needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue)
  420. if personUserVirtualAmountValue.GreaterThan(needVirtualAmountValue) {
  421. isCan = true
  422. }
  423. return
  424. }
  425. // CalcUserContinuousDailyActivityDays 计算用户连续活跃天数
  426. func CalcUserContinuousDailyActivityDays(engine *xorm.Engine, uid int, startDate string, endDate string) (err error, days int, isContinuousDailyActivity bool) {
  427. startAt, err := time.ParseInLocation("2006-01-02", startDate, time.Local) //起始时间
  428. endAt, err := time.ParseInLocation("2006-01-02", endDate, time.Local) //起始时间
  429. var list []model.EggEnergyUserActivity
  430. err = engine.Where("date >= ?", startAt.Format("2006-01-02")).
  431. And("date < ?", endAt.Format("2006-01-02")).
  432. And("uid =?", uid).Find(&list)
  433. if err != nil {
  434. fmt.Println("err:::::1111", err)
  435. return
  436. }
  437. days = len(list)
  438. diffDays := egg_system_rules.GetDiffDays(endAt, startAt) //相差天数
  439. if days == diffDays {
  440. isContinuousDailyActivity = true
  441. }
  442. return
  443. }