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

322 lines
11 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/rule/egg_energy/enum"
  6. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  7. "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/svc"
  8. egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils"
  9. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache"
  10. zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx"
  11. "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
  12. "encoding/json"
  13. "errors"
  14. "fmt"
  15. "github.com/shopspring/decimal"
  16. "time"
  17. "xorm.io/xorm"
  18. )
  19. const SettlementStarLevelDividendsLockKey = "settlement_star_level_dividends_lock_key"
  20. // SettlementStarLevelDividends 蛋蛋能量星级分红
  21. func SettlementStarLevelDividends(engine *xorm.Engine, ch *rabbit.Channel) (err error) {
  22. now := time.Now()
  23. fmt.Println(now.Hour())
  24. if !(now.Hour() > 2 && now.Hour() < 8) {
  25. //TODO::只在凌晨一点 ~ 凌晨 8 点运行
  26. return errors.New("非运行时间")
  27. }
  28. //TODO::增加“悲观锁”防止串行
  29. getString, _ := cache.GetString(SettlementStarLevelDividendsLockKey)
  30. if getString != "" {
  31. fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "上一次结算未执行完")
  32. return errors.New("上一次结算未执行完")
  33. }
  34. cache.SetEx(SettlementStarLevelDividendsLockKey, "running", 3600*8) //8小时
  35. //1、查找 `egg_energy_basic_setting` 基础设置
  36. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  37. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  38. "key": "is_open",
  39. "value": 1,
  40. })
  41. if err != nil {
  42. return
  43. }
  44. isLimitDividend := eggEnergyBasicSetting.IsLimitDividend
  45. if isLimitDividend != 1 {
  46. return errors.New("必须开启限制分红!")
  47. }
  48. startDate := now.AddDate(0, 0, -1).Format("2006-01-02") + " 00:00:00"
  49. endDate := now.Format("2006-01-02") + " 00:00:00"
  50. var list []model.EggSignIn
  51. err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).Find(&list)
  52. if err != nil {
  53. fmt.Println("err:::::1111", err)
  54. return
  55. }
  56. if len(list) <= 0 {
  57. return errors.New("无须参与星级分红用户!")
  58. }
  59. var vipEquitySetting []*md2.VipEquitySettingStruct
  60. err = json.Unmarshal([]byte(eggEnergyBasicSetting.VipEquitySetting), &vipEquitySetting)
  61. if err != nil {
  62. fmt.Println("err:::::22222", err)
  63. return
  64. }
  65. userLevelDb := implement.NewUserLevelDb(engine)
  66. allUserLevel, err := userLevelDb.UserLevelAllByAsc()
  67. if err != nil {
  68. return err
  69. }
  70. var allUserLevelMap = map[int]model.UserLevel{}
  71. for _, v := range allUserLevel {
  72. allUserLevelMap[v.Id] = *v
  73. }
  74. session := engine.NewSession()
  75. defer func() {
  76. session.Close()
  77. if err := recover(); err != nil {
  78. _ = zhios_order_relate_logx.Error(err)
  79. }
  80. }()
  81. session.Begin()
  82. //2、查找 `egg_star_level_dividends_records` 基础设置
  83. eggStarLevelDividendsRecordsDb := implement.NewEggStarLevelDividendsRecordsDb(engine)
  84. eggStarLevelDividendsRecords, err := eggStarLevelDividendsRecordsDb.EggStarLevelDividendsRecordsGetOneByParamsBySession(session, map[string]interface{}{
  85. "key": "date",
  86. "value": now.AddDate(0, 0, -1).Format("2006-01-02"),
  87. })
  88. if err != nil {
  89. fmt.Println("err:::::33333", err)
  90. return
  91. }
  92. if eggStarLevelDividendsRecords == nil {
  93. return errors.New("今日无分红积分!")
  94. }
  95. //3、统计各等级人数
  96. dividendAmountValue, _ := decimal.NewFromString(eggStarLevelDividendsRecords.Amount)
  97. decimalRate := decimal.NewFromInt(100) //百分比
  98. var vipLevelUserTotalMap = map[string]map[string]int64{}
  99. var vipEquitySettingMap = map[string]string{}
  100. for _, v := range vipEquitySetting {
  101. dividendRatioValue, _ := decimal.NewFromString(v.DividendRatio)
  102. dividendRatioValue = dividendRatioValue.Div(decimalRate) //分红比例
  103. vipEquitySettingMap[v.VipLevelId] = dividendAmountValue.Mul(dividendRatioValue).String() //TODO::计算各会员等级能得到多少分红
  104. userLevel, err1 := userLevelDb.UserLevelByID(v.VipLevelId)
  105. if err1 != nil {
  106. fmt.Println("err:::::444444", err1)
  107. return err1
  108. }
  109. var ms []*model.UserLevel
  110. err1 = session.Where("is_use=1").Where("level_weight > ?", userLevel.LevelWeight).Find(&ms)
  111. if err1 != nil {
  112. fmt.Println("err:::::55555", err1)
  113. return err1
  114. }
  115. var tmpVipLevelId = []string{v.VipLevelId}
  116. for _, m := range ms {
  117. tmpVipLevelId = append(tmpVipLevelId, egg_system_rules.IntToStr(m.Id))
  118. }
  119. var users model.User
  120. count, err1 := session.In("level", tmpVipLevelId).Count(&users)
  121. if err1 != nil {
  122. fmt.Println("err:::::66666", err1)
  123. return err1
  124. }
  125. vipLevelUserTotalMap[v.VipLevelId] = map[string]int64{}
  126. vipLevelUserTotalMap[v.VipLevelId]["count"] = count
  127. vipLevelUserTotalMap[v.VipLevelId]["weight"] = int64(userLevel.LevelWeight)
  128. }
  129. //4、处理分红
  130. var userSignInArr []int64
  131. var totalDividendValue = decimal.Decimal{}
  132. userRelateDb := implement.NewUserRelateDb(engine)
  133. for _, l := range list {
  134. userSignInArr = append(userSignInArr, l.Uid)
  135. if len(userSignInArr) >= 10000 {
  136. var users []*model.User
  137. err = session.In("uid", userSignInArr).Find(&users)
  138. if err != nil {
  139. fmt.Println("err:::::7777777", err)
  140. return err
  141. }
  142. for _, item := range users {
  143. var siginDividendValue = decimal.Decimal{}
  144. for k, v := range vipLevelUserTotalMap {
  145. if int(v["weight"]) > allUserLevelMap[item.Level].LevelWeight {
  146. continue
  147. }
  148. if vipEquitySettingMap[k] != "" && vipLevelUserTotalMap[k]["count"] > 0 {
  149. dividendValue, _ := decimal.NewFromString(vipEquitySettingMap[k])
  150. userTotal := decimal.NewFromInt(vipLevelUserTotalMap[k]["count"])
  151. siginDividendValue = siginDividendValue.Add(dividendValue.Div(userTotal))
  152. }
  153. }
  154. if siginDividendValue.GreaterThan(decimal.NewFromInt(0)) {
  155. //TODO::统计当前有多少直推用户昨天签到了
  156. userRelates, err1 := userRelateDb.FindUserRelateByParentUid(item.Id, 1)
  157. if err1 != nil {
  158. fmt.Println("err:::::88888888", err1)
  159. return err
  160. }
  161. var userRelatesUids []int64
  162. if userRelates != nil {
  163. for _, userRelate := range *userRelates {
  164. userRelatesUids = append(userRelatesUids, userRelate.Uid)
  165. }
  166. }
  167. if len(userRelatesUids) > 0 {
  168. var eggEnergySignIns []*model.EggSignIn
  169. err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).In("uid", userRelatesUids).And("is_completed =?", 0).Find(&eggEnergySignIns)
  170. if err != nil {
  171. fmt.Println("err:::::999999999", err)
  172. return
  173. }
  174. if len(eggEnergySignIns) > 0 {
  175. userRelatesUidsValue := decimal.NewFromInt(int64(len(userRelatesUids)))
  176. eggEnergySignInsValue := decimal.NewFromInt(int64(len(eggEnergySignIns)))
  177. siginDividendValue = siginDividendValue.Mul(eggEnergySignInsValue.Div(userRelatesUidsValue))
  178. } else {
  179. siginDividendValue = decimal.NewFromFloat(0)
  180. }
  181. } else {
  182. siginDividendValue = decimal.NewFromFloat(0)
  183. }
  184. siginDividend, _ := siginDividendValue.Float64()
  185. if siginDividend > 0 {
  186. //TODO::推入rabbitmq 异步处理
  187. ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStarLevelDividends{
  188. Uid: item.Id,
  189. SignDividend: siginDividend,
  190. }, md2.EggEnergyRoutKeyForStarLevelDividend)
  191. totalDividendValue = totalDividendValue.Add(siginDividendValue)
  192. }
  193. }
  194. }
  195. userSignInArr = []int64{}
  196. }
  197. }
  198. if len(userSignInArr) > 0 {
  199. var users []*model.User
  200. err = session.In("uid", userSignInArr).Find(&users)
  201. if err != nil {
  202. fmt.Println("err:::::7777777", err)
  203. return err
  204. }
  205. for _, item := range users {
  206. var siginDividendValue = decimal.Decimal{}
  207. for k, v := range vipLevelUserTotalMap {
  208. if int(v["weight"]) > allUserLevelMap[item.Level].LevelWeight {
  209. continue
  210. }
  211. if vipEquitySettingMap[k] != "" && vipLevelUserTotalMap[k]["count"] > 0 {
  212. dividendValue, _ := decimal.NewFromString(vipEquitySettingMap[k])
  213. userTotal := decimal.NewFromInt(vipLevelUserTotalMap[k]["count"])
  214. siginDividendValue = siginDividendValue.Add(dividendValue.Div(userTotal))
  215. }
  216. }
  217. if siginDividendValue.GreaterThan(decimal.NewFromInt(0)) {
  218. //TODO::统计当前有多少直推用户昨天签到了
  219. userRelates, err1 := userRelateDb.FindUserRelateByParentUid(item.Id, 1)
  220. if err1 != nil {
  221. fmt.Println("err:::::88888888", err1)
  222. return err
  223. }
  224. var userRelatesUids []int64
  225. if userRelates != nil {
  226. for _, userRelate := range *userRelates {
  227. userRelatesUids = append(userRelatesUids, userRelate.Uid)
  228. }
  229. }
  230. if len(userRelatesUids) > 0 {
  231. var eggEnergySignIns []*model.EggSignIn
  232. err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).In("uid", userRelatesUids).And("is_completed =?", 0).Find(&eggEnergySignIns)
  233. if err != nil {
  234. fmt.Println("err:::::999999999", err)
  235. return
  236. }
  237. if len(eggEnergySignIns) > 0 {
  238. userRelatesUidsValue := decimal.NewFromInt(int64(len(userRelatesUids)))
  239. eggEnergySignInsValue := decimal.NewFromInt(int64(len(eggEnergySignIns)))
  240. siginDividendValue = siginDividendValue.Mul(eggEnergySignInsValue.Div(userRelatesUidsValue))
  241. } else {
  242. siginDividendValue = decimal.NewFromFloat(0)
  243. }
  244. } else {
  245. siginDividendValue = decimal.NewFromFloat(0)
  246. }
  247. siginDividend, _ := siginDividendValue.Float64()
  248. if siginDividend > 0 {
  249. //TODO::推入rabbitmq 异步处理
  250. ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStarLevelDividends{
  251. Uid: item.Id,
  252. SignDividend: siginDividend,
  253. }, md2.EggEnergyRoutKeyForStarLevelDividend)
  254. totalDividendValue = totalDividendValue.Add(siginDividendValue)
  255. }
  256. }
  257. }
  258. }
  259. //5、更新 egg_star_level_dividends_records 记录
  260. eggStarLevelDividendsRecords.AlreadyDividendsAmount = totalDividendValue.String()
  261. eggStarLevelDividendsRecords.NotDividendsAmount = dividendAmountValue.Sub(totalDividendValue).String()
  262. _, err = eggStarLevelDividendsRecordsDb.EggStarLevelDividendsRecordsUpdateBySession(session, eggStarLevelDividendsRecords.Id, eggStarLevelDividendsRecords, "already_dividends_amount", "not_dividends_amount")
  263. if err != nil {
  264. _ = session.Rollback()
  265. fmt.Println("err:::::8888888", err)
  266. return err
  267. }
  268. //6、 减少“星级分红”中的绿色能量
  269. totalDividend := totalDividendValue.String()
  270. eggEnergyCoreData, cb, err := svc.GetEggEnergyCoreData(engine)
  271. if err != nil {
  272. return err
  273. }
  274. if cb != nil {
  275. defer cb() // 释放锁
  276. }
  277. err = DealAvailableEggEnergyCoin(session, int(enum.SettlementStarLevelDividends), eggEnergyCoreData, md2.DealAvailableEggEnergyCoinReq{
  278. Amount: totalDividend,
  279. AmountFee: "",
  280. BeforePrice: eggEnergyCoreData.NowPrice,
  281. AfterPrice: eggEnergyCoreData.NowPrice,
  282. BeforePlanetTotalValue: eggEnergyCoreData.PlanetTotalValue,
  283. AfterPlanetTotalValue: eggEnergyCoreData.PlanetTotalValue,
  284. BeforeEnergyTotalNums: eggEnergyCoreData.NowEnergyTotalNums,
  285. AfterEnergyTotalNums: eggEnergyCoreData.NowEnergyTotalNums,
  286. })
  287. if err != nil {
  288. _ = session.Rollback()
  289. fmt.Println("err:::::9999999", err)
  290. return err
  291. }
  292. err = session.Commit()
  293. if err != nil {
  294. _ = session.Rollback()
  295. return errors.New("事务提交失败")
  296. }
  297. return
  298. }