蛋蛋星球-制度模式
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.

422 lines
15 KiB

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