劲创营---任务项目
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.
 
 
 

646 rivejä
23 KiB

  1. package plan
  2. import (
  3. "fmt"
  4. "applet/app/comm/utils"
  5. "applet/app/comm/utils/logx"
  6. )
  7. // 佣金 积分 区块币计算
  8. func CalReturnAmountAndRatio(level, ownbuyReturnType, peerNum int, userType string, fee, integralFee float64, opt *PlanOpt) (commission, commissionRatio float64, amountList, ratioList []*VirtualCoinCommission) {
  9. // 佣金的比例兼容旧系统 比例独立出来的 所以这样算
  10. commissionRatio = getCommissionRatio(userType, level, peerNum, opt.UserRate)
  11. commission = fee * commissionRatio
  12. // 新版支持多种虚拟币 支持的种类id保存在ReturnType id=0代表现金佣金 其他为虚拟币
  13. if opt.UserRate[level].ReturnType != nil { //返佣类型
  14. for _, coinId := range opt.UserRate[level].ReturnType {
  15. newFee := integralFee
  16. if coinId == "0" {
  17. newFee = fee
  18. }
  19. ratio := getVirtualCoinRatio(userType, level, peerNum, opt.UserRate, coinId)
  20. amount := getCoinAmount(ratio, utils.StrToInt(coinId), newFee, opt.VirtualCoinMoneyRatioList)
  21. amountList = append(amountList, &VirtualCoinCommission{
  22. Cid: coinId,
  23. Val: amount,
  24. })
  25. ratioList = append(ratioList, &VirtualCoinCommission{
  26. Cid: coinId,
  27. Val: utils.AnyToFloat64(ratio),
  28. })
  29. }
  30. }
  31. if ownbuyReturnType == 1 { //自购不返利
  32. commission = 0
  33. for i := range amountList {
  34. amountList[i].Val = 0
  35. }
  36. }
  37. commission = utils.FloatFormat(commission, 6)
  38. for i, coin := range amountList {
  39. amountList[i].Val = utils.FloatFormat(coin.Val, 6)
  40. }
  41. return commission, commissionRatio, amountList, ratioList
  42. }
  43. // 按总佣金的比例进行划分计算
  44. func CalcAll(opt *PlanOpt, totalAmt, integralTotalAmt float64, userList *LvUser, pvd string, sysFee float64, integralSysFee float64) error {
  45. grade := opt.UserRate
  46. if len(grade) == 0 {
  47. return logx.Warn("level grade is not set")
  48. }
  49. //查出用户自购佣金
  50. commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(userList.Lv, userList.OwnbuyReturnType, 0, "own", totalAmt, integralTotalAmt, opt)
  51. userList.Profit = commission // 另外出来的佣金 兼容旧的
  52. userList.ProfitList = amountList // 各币种分佣
  53. userList.SubsidyFee = 0
  54. ratioListMap := convertList2Map(ratioList)
  55. for k, v := range userList.ProfitList {
  56. userList.ProfitList[k].Val = ratioListMap[v.Cid] * v.Val
  57. }
  58. // 各种币换算出总的额度
  59. totalAmtList := make([]*VirtualCoinCommission, 0)
  60. for coinId, rate := range opt.VirtualCoinMoneyRatioList {
  61. var amount float64
  62. if coinId == 0 {
  63. amount = totalAmt
  64. } else {
  65. amount = integralTotalAmt * utils.AnyToFloat64(rate)
  66. }
  67. totalAmtList = append(totalAmtList, &VirtualCoinCommission{
  68. Cid: utils.AnyToString(coinId),
  69. Val: amount,
  70. })
  71. }
  72. var (
  73. node = userList
  74. maxLv = node.Lv // 当前等级
  75. maxLevelWeight = node.LevelWeight // 当前权重
  76. peerNum = 0 // 存在同级数
  77. peerRate float64 = 0 // 同级累计比例
  78. peerRateList = make([]*VirtualCoinCommission, 0) // 各虚拟币同级累计
  79. restAmtList = make([]*VirtualCoinCommission, 0) // 各虚拟币剩余额度
  80. accumulateRatioList = make([]*VirtualCoinCommission, 0) // 各虚拟币累计比例
  81. //integralPeerRate float64 = 0 // 同级累计比例
  82. //blockIconsPeerRate float64 = 0 // 同级累计比例
  83. restAmt = totalAmt - userList.Profit // 剩余比例
  84. //integralRestAmt = totalAmt - userList.IntegralProfit // 积分剩余比例
  85. //blockIconsRestAmt = totalAmt - userList.BlockIconsProfit // 区块币剩余比例
  86. totalCommissionRatio = commissionRatio // 累计佣金比例
  87. //integralBili = integralLeaveBili // 积分累计佣金比例
  88. //blockIconsBili = blockIconsLeaveBili // 区块币累计佣金比例
  89. )
  90. // 计算剩余额度
  91. restAmtList, _ = CalVirtualCommissionMinus(totalAmtList, amountList)
  92. // 累计比例
  93. accumulateRatioList = ratioList
  94. restAmt = utils.FloatFormat(restAmt, 6)
  95. Loop:
  96. for node.ParentUser != nil { //查找上级用户
  97. node.ParentUser.Profit = 0
  98. //佣金补贴奖励
  99. subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList := subsidyFee(opt, totalAmt, integralTotalAmt, node.ParentUser, userList.NewLv, pvd, sysFee, integralSysFee)
  100. node.ParentUser.SubsidyFee = subsidyFee
  101. node.ParentUser.SubsidyFeeList = subsidyFeeList // 各币种补贴
  102. // 如果父级比当前级别低, 跳过
  103. // 同级奖, 如果父级别与当前级别一致,并且设置了对应比例
  104. count := len(grade[maxLv].PeerRate)
  105. if grade[maxLv].PeerRateList != nil {
  106. count = len(grade[maxLv].PeerRateList)
  107. }
  108. var isBreak bool
  109. zeroList := make(map[string]struct{})
  110. // 同级奖
  111. if node.ParentUser.LevelWeight == maxLevelWeight && count > peerNum {
  112. //同级奖励比例
  113. commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(maxLv, userList.OwnbuyReturnType, peerNum, "same_lv", totalAmt, integralTotalAmt, opt)
  114. //佣金 (lv, isOnlySubsidy int, restAmt, profit, peerRate, totalRatio, restRatio, subsidyFee, subsidyBili float64, opt *PlanOpt)
  115. node.ParentUser.Profit, restAmt, totalCommissionRatio, peerRate, node.ParentUser.SubsidyFee, isBreak = sameMoney(node.Lv, isOnlySubsidyFee, restAmt, commission, peerRate, totalCommissionRatio, commissionRatio, node.ParentUser.SubsidyFee, subsidyRatio, opt)
  116. // 虚拟币 newProfitList, newRestAmtList, newTotalRatioList, newPeerRateList, newSubsidyFeeList, zeroList
  117. node.ParentUser.ProfitList, restAmtList, accumulateRatioList, peerRateList, node.ParentUser.SubsidyFeeList, zeroList = sameMoneyV2(node.Lv, isOnlySubsidyFee, totalAmtList, restAmtList, amountList, peerRateList, accumulateRatioList, ratioList, node.ParentUser.SubsidyFeeList, subsidyRatioList, opt)
  118. // 全部都没得分了
  119. if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) {
  120. break Loop
  121. }
  122. peerNum++
  123. } else if node.ParentUser.LevelWeight > maxLevelWeight {
  124. if _, ok := grade[node.Lv]; !ok {
  125. return logx.Warn("level grade node.Lv is not set")
  126. }
  127. if _, ok := grade[node.ParentUser.Lv]; !ok {
  128. return logx.Warn("level grade node.ParentUser.Lv is not set")
  129. }
  130. commission, _, amountList, teamRatioList := CalReturnAmountAndRatio(node.ParentUser.Lv, userList.OwnbuyReturnType, peerNum, "team", totalAmt, integralTotalAmt, opt)
  131. //佣金
  132. node.ParentUser.Profit = commission
  133. node.ParentUser.Profit, restAmt, totalCommissionRatio, node.ParentUser.SubsidyFee, isBreak = teamDiffMoney(node.ParentUser.Profit, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmt, restAmt, grade[node.ParentUser.Lv].TeamRate, totalCommissionRatio, peerRate, node.ParentUser.SubsidyFee, subsidyRatio)
  134. //积分
  135. node.ParentUser.ProfitList = amountList
  136. // profitList []*VirtualCoinCommission, payMode, isOnlySubsidy int, totalAmtList, restAmtList, teamRatioList, totalRatioList, peerRateList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission
  137. node.ParentUser.ProfitList, restAmtList, accumulateRatioList, node.ParentUser.SubsidyFeeList, zeroList = teamDiffMoneyV2(node.ParentUser.ProfitList, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmtList, restAmtList, teamRatioList, accumulateRatioList, peerRateList, subsidyFeeList, subsidyRatioList)
  138. // 没得分了 就结束
  139. if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) {
  140. break Loop
  141. }
  142. // 等级往上升则置0
  143. maxLevelWeight, maxLv, peerRate, peerRateList, peerNum = node.ParentUser.LevelWeight, node.ParentUser.Lv, 0, nil, 0
  144. }
  145. node.Profit = utils.StrToFloat64(fmt.Sprintf("%.4f", node.Profit))
  146. node = node.ParentUser
  147. }
  148. return nil
  149. }
  150. // 公共处理同级计算 (只计算佣金 旧版本用)
  151. func sameMoney(lv, isOnlySubsidy int, restAmt, profit, peerRate, totalRatio, restRatio, subsidyFee, subsidyBili float64, opt *PlanOpt) (float64, float64, float64, float64, float64, bool) {
  152. //如果不够扣了,并且是比例返利就跳过
  153. if restAmt < profit {
  154. return 0, restAmt, totalRatio, peerRate, subsidyFee, true
  155. }
  156. //极差返利
  157. if opt.UserRate[lv].PayMode == 0 && isOnlySubsidy == 0 {
  158. restAmt -= profit // 剩余可分
  159. restAmt = utils.FloatFormat(restAmt, 6)
  160. peerRate += restRatio
  161. totalRatio += restRatio
  162. } else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的
  163. profit = 0
  164. if opt.UserRate[lv].PayMode == 0 {
  165. if restAmt < subsidyFee {
  166. subsidyFee = 0
  167. return profit, restAmt, totalRatio, subsidyFee, peerRate, true
  168. }
  169. restAmt -= subsidyFee // 剩余可分
  170. restAmt = utils.FloatFormat(restAmt, 6)
  171. totalRatio += utils.FloatFormat(subsidyBili, 6)
  172. }
  173. }
  174. return profit, restAmt, totalRatio, peerRate, subsidyFee, false
  175. }
  176. func sameMoneyV2(lv, isOnlySubsidy int, totalAmtList, restAmtList, profitList, peerRateList, totalRatioList, restRatioList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission, opt *PlanOpt) ([]*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, map[string]struct{}) {
  177. restAmtMap := convertList2Map(restAmtList)
  178. totalAmtMap := convertList2Map(totalAmtList)
  179. //profitMap := convertList2Map(profitList)
  180. restRatioMap := convertList2Map(restRatioList)
  181. totalRatioMap := convertList2Map(totalRatioList)
  182. peerRateMap := convertList2Map(peerRateList)
  183. subsidyMap := convertList2Map(subsidyFeeList)
  184. subsidyRatioMap := convertList2Map(subsidyRatioList)
  185. zeroList := make(map[string]struct{})
  186. newProfitList := make([]*VirtualCoinCommission, 0)
  187. newRestAmtList := make([]*VirtualCoinCommission, 0)
  188. newTotalRatioList := make([]*VirtualCoinCommission, 0)
  189. newPeerRateList := make([]*VirtualCoinCommission, 0)
  190. newSubsidyFeeList := subsidyFeeList
  191. //极差返利
  192. if opt.UserRate[lv].PayMode == 0 && isOnlySubsidy == 0 {
  193. for _, coin := range profitList {
  194. profitOne := &VirtualCoinCommission{}
  195. profitOne.Cid = coin.Cid
  196. profitOne.Val = totalAmtMap[coin.Cid] * restRatioMap[coin.Cid]
  197. // 不够扣了 设为0
  198. if restAmtMap[coin.Cid] < profitOne.Val {
  199. profitOne.Val = 0
  200. zeroList[coin.Cid] = struct{}{}
  201. }
  202. // 分佣
  203. newProfitList = append(newProfitList, profitOne)
  204. // 剩余
  205. restAmtMap[coin.Cid] -= profitOne.Val
  206. // 累计比例
  207. totalRatioMap[coin.Cid] += restRatioMap[coin.Cid]
  208. // 同级累计比例
  209. if _, ok := peerRateMap[coin.Cid]; !ok {
  210. peerRateMap[coin.Cid] = 0
  211. }
  212. peerRateMap[coin.Cid] += restRatioMap[coin.Cid]
  213. }
  214. } else if isOnlySubsidy == 1 {
  215. newSubsidyFeeList = make([]*VirtualCoinCommission, 0)
  216. for _, coin := range profitList {
  217. profitOne := &VirtualCoinCommission{}
  218. subsidyFeeOne := &VirtualCoinCommission{}
  219. profitOne.Cid = coin.Cid
  220. profitOne.Val = 0
  221. newProfitList = append(newProfitList, profitOne)
  222. if opt.UserRate[lv].PayMode == 0 {
  223. subsidyFeeOne.Cid = coin.Cid
  224. subsidyFeeOne.Val = subsidyMap[coin.Cid]
  225. if restAmtMap[coin.Cid] < subsidyMap[coin.Cid] {
  226. subsidyFeeOne.Val = 0
  227. zeroList[coin.Cid] = struct{}{}
  228. }
  229. newSubsidyFeeList = append(newSubsidyFeeList, subsidyFeeOne)
  230. }
  231. // 剩余额度
  232. restAmtMap[coin.Cid] -= subsidyFeeOne.Val
  233. // 累计比例
  234. totalRatioMap[coin.Cid] += subsidyRatioMap[coin.Cid]
  235. // 同级累计比例
  236. if _, ok := peerRateMap[coin.Cid]; !ok {
  237. peerRateMap[coin.Cid] = 0
  238. }
  239. peerRateMap[coin.Cid] += restRatioMap[coin.Cid]
  240. }
  241. }
  242. newTotalRatioList = convertMap2List(totalRatioMap)
  243. newPeerRateList = convertMap2List(peerRateMap)
  244. newRestAmtList = convertMap2List(restAmtMap)
  245. return newProfitList, newRestAmtList, newTotalRatioList, newPeerRateList, newSubsidyFeeList, zeroList
  246. }
  247. // 公共处理下团队-上一层 (用于旧版的制度 只有佣金时)
  248. func teamDiffMoney(profit float64, payMode, isOnlySubsidy int, totalAmt, restAmt, teamRatio, totalRatio, peerRate, subsidyFee, subsidyRatio float64) (float64, float64, float64, float64, bool) {
  249. // 如果是团队内部支出团队比例大于同级累计比例 或站长支出
  250. if payMode == 1 || teamRatio > peerRate {
  251. teamRatio = utils.FloatFormat(teamRatio-totalRatio, 6)
  252. }
  253. //极差返利
  254. if isOnlySubsidy == 0 {
  255. totalRatio += teamRatio
  256. //出现负数跳过
  257. if teamRatio <= 0 {
  258. profit = 0
  259. return profit, restAmt, totalRatio, subsidyFee, true
  260. }
  261. profit = utils.FloatFormat(teamRatio*totalAmt, 6)
  262. if restAmt < profit {
  263. profit = 0
  264. return profit, restAmt, totalRatio, subsidyFee, true
  265. }
  266. restAmt -= profit // 剩余可分
  267. } else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的
  268. totalRatio += utils.FloatFormat(subsidyRatio, 6)
  269. profit = 0
  270. if restAmt < subsidyFee {
  271. profit = 0
  272. subsidyFee = 0
  273. return profit, restAmt, totalRatio, subsidyFee, true
  274. }
  275. restAmt -= subsidyFee // 剩余可分
  276. }
  277. restAmt = utils.FloatFormat(restAmt, 6)
  278. return profit, restAmt, totalRatio, subsidyFee, false
  279. }
  280. // 处理多虚拟币团队的
  281. func teamDiffMoneyV2(profitList []*VirtualCoinCommission, payMode, isOnlySubsidy int, totalAmtList, restAmtList, teamRatioList, totalRatioList, peerRateList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission) (newProfitList, newRestAmtList, newTotalRatioList, newSubsidyFeeList []*VirtualCoinCommission, zeroList map[string]struct{}) {
  282. restAmtMap := convertList2Map(restAmtList)
  283. totalAmtMap := convertList2Map(totalAmtList)
  284. profitMap := convertList2Map(profitList)
  285. totalRatioMap := convertList2Map(totalRatioList)
  286. peerRateMap := convertList2Map(peerRateList)
  287. subsidyFeeMap := convertList2Map(subsidyFeeList)
  288. subsidyRatioMap := convertList2Map(subsidyRatioList)
  289. teamRatioMap := convertList2Map(teamRatioList)
  290. zeroList = make(map[string]struct{})
  291. newProfitList = make([]*VirtualCoinCommission, 0)
  292. for _, coin := range profitList {
  293. // 如果是团队内部支出团队比例大于同级累计比例 或站长支出
  294. if payMode == 1 || teamRatioMap[coin.Cid] > peerRateMap[coin.Cid] {
  295. teamRatioMap[coin.Cid] = utils.FloatFormat(teamRatioMap[coin.Cid]-totalRatioMap[coin.Cid], 6)
  296. }
  297. if isOnlySubsidy == 0 {
  298. totalRatioMap[coin.Cid] += teamRatioMap[coin.Cid]
  299. profitOne := &VirtualCoinCommission{}
  300. profitOne.Cid = coin.Cid
  301. profitOne.Val = utils.FloatFormat(totalAmtMap[coin.Cid]*teamRatioMap[coin.Cid], 6)
  302. // 剩余不足或比例小于0
  303. if teamRatioMap[coin.Cid] < 0 || restAmtMap[coin.Cid] < profitOne.Val {
  304. zeroList[coin.Cid] = struct{}{}
  305. profitOne.Val = 0
  306. }
  307. newProfitList = append(newProfitList, profitOne)
  308. restAmtMap[coin.Cid] -= profitOne.Val
  309. } else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的
  310. totalRatioMap[coin.Cid] += utils.FloatFormat(subsidyRatioMap[coin.Cid], 6)
  311. profitMap[coin.Cid] = 0
  312. if restAmtMap[coin.Cid] < subsidyFeeMap[coin.Cid] {
  313. subsidyFeeMap[coin.Cid] = 0
  314. }
  315. restAmtMap[coin.Cid] -= subsidyFeeMap[coin.Cid]
  316. }
  317. }
  318. newTotalRatioList = convertMap2List(totalRatioMap)
  319. newRestAmtList = convertMap2List(restAmtMap)
  320. newSubsidyFeeList = convertMap2List(subsidyFeeMap)
  321. return newProfitList, newRestAmtList, newTotalRatioList, newSubsidyFeeList, zeroList
  322. }
  323. // 补贴金额计算 仅针对会员费
  324. // types 支持的返佣类型
  325. func subsidyFee(opt *PlanOpt, totalAmt, integralTotalAmt float64, lvuser *LvUser, newLv int, pvd string, sysFee, integralSysFee float64) (subsidyFee, subsidyRatio float64, isOnlySubsidyFee int, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission) {
  326. grade := opt.UserRate
  327. lv := lvuser.Lv
  328. //会员费分佣只有直推的奖励
  329. pvdBool := utils.InArr(pvd, []string{"user_level_up", "mall_goods_user_lv"})
  330. if opt.IsCanRunSubsidy == 1 { //后台推演用
  331. if grade[lv].UserSubsidyType == "buy_goods" {
  332. pvdBool = false
  333. } else {
  334. pvdBool = true
  335. }
  336. }
  337. if pvdBool && lvuser.Diff != 1 {
  338. return 0, 0, 0, nil, nil
  339. }
  340. if _, ok := grade[lv]; !ok {
  341. return 0, 0, 0, nil, nil
  342. }
  343. if grade[lv].UserSubsidyType == "" {
  344. grade[lv].UserSubsidyType = "up_lv"
  345. }
  346. // 各等级 各虚拟币补贴设置
  347. userLvUpSubsidyList := grade[lv].UserLvUpSubsidyList
  348. if userLvUpSubsidyList == nil {
  349. return 0, 0, 0, nil, nil
  350. }
  351. //只有额外补贴跟 分销补贴按钮都开启才有的分
  352. if grade[lv].SubsidyEnable == 1 && grade[lv].UserLvUpSubsidyEnable == 1 {
  353. //判断有没有开启 如果不是推荐会员模式
  354. if pvdBool && grade[lv].UserSubsidyType != "up_lv" { // 分享会员补贴
  355. return 0, 0, 0, nil, nil
  356. }
  357. //如果不是购买商品模式 跳过
  358. if pvdBool == false && grade[lv].UserSubsidyType != "buy_goods" { // 购买商品补贴
  359. return 0, 0, 0, nil, nil
  360. }
  361. //处理每个条件的返利
  362. if grade[lv].UserLvUpSubsidyList != nil {
  363. fmt.Println(grade[lv].UserLvUpSubsidyList)
  364. for k, v1 := range grade[lv].UserLvUpSubsidyList {
  365. v, ok := v1.(map[string]interface{})
  366. if ok {
  367. //如果不相等并且是会员升级的没的返
  368. if newLv != int(utils.AnyToInt64(v["lv"])) && pvdBool {
  369. continue
  370. }
  371. //如果层级不是当前层级 且不是会员升级
  372. if pvdBool == false && k+1 != lvuser.Diff {
  373. continue
  374. }
  375. if pvdBool == false { //如果不是会员升级 newLv=旧的等级
  376. newLv = lv
  377. }
  378. //如果没开启与补贴共存 只能拿这个奖励
  379. if int(utils.AnyToInt64(v["is_use"])) != 1 {
  380. isOnlySubsidyFee = 1
  381. }
  382. modeList := grade[lv].SubsidyModeList // 每一种币按比例还是固定金额
  383. if modeList == nil {
  384. return 0, 0, 0, nil, nil
  385. }
  386. subsidyReturnType := grade[lv].SubsidyReturnType // 补贴支持的虚拟币
  387. if subsidyReturnType == nil {
  388. return 0, 0, 0, nil, nil
  389. }
  390. for _, coinId := range subsidyReturnType {
  391. ratio := GetLvUpSubsidyVirtualCoinRatio(lv, newLv, lvuser.Diff, grade, coinId)
  392. mode := modeList[coinId]
  393. if mode != "bili" && mode != "money" {
  394. continue
  395. }
  396. modeStr := mode.(string)
  397. subsidyMode := grade[lv].SubsidyMode
  398. newAmt := integralTotalAmt
  399. newSysFee := integralSysFee
  400. var moneyRate = ""
  401. if coinId == "0" {
  402. newAmt = totalAmt
  403. newSysFee = sysFee
  404. } else if mode == "bili" {
  405. rateList := opt.VirtualCoinMoneyRatioList
  406. moneyRates, ok := rateList[utils.StrToInt(coinId)]
  407. if ok {
  408. moneyRate = moneyRates
  409. }
  410. }
  411. amount, subsidyRatio := GetSubsidyVirtualCoinAmount(ratio, moneyRate, modeStr, newAmt, newSysFee, subsidyMode)
  412. subsidyFeeList = append(subsidyFeeList, &VirtualCoinCommission{
  413. Cid: coinId,
  414. Val: amount,
  415. })
  416. subsidyRatioList = append(subsidyRatioList, &VirtualCoinCommission{
  417. Cid: coinId,
  418. Val: subsidyRatio,
  419. })
  420. }
  421. }
  422. }
  423. }
  424. }
  425. subsidyFee = utils.FloatFormat(subsidyFee, 6)
  426. for i, coin := range subsidyFeeList {
  427. subsidyFeeList[i].Val = utils.FloatFormat(subsidyFeeList[i].Val, 6)
  428. if coin.Cid == "0" {
  429. subsidyFee += coin.Val // 添加上额外补贴到外部的补贴金额
  430. }
  431. }
  432. return subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList
  433. }
  434. // 获取佣金比例
  435. func getCommissionRatio(typ string, level, peerNum int, grade map[int]*LvGrade) (ratio float64) {
  436. switch typ {
  437. case "team":
  438. ratio = grade[level].TeamRate
  439. case "same_lv":
  440. if len(grade[level].PeerRate) == 0 {
  441. ratio = 0
  442. } else {
  443. ratio = grade[level].PeerRate[peerNum]
  444. }
  445. default:
  446. ratio = grade[level].SelfRate
  447. }
  448. return
  449. }
  450. // 获取佣金、虚拟币比例 0=佣金
  451. func getVirtualCoinRatio(typ string, level, peerNum int, grade map[int]*LvGrade, coinId string) (ratio string) {
  452. ok := false
  453. switch typ {
  454. case "team":
  455. ratio, ok = grade[level].TeamRateList[coinId]
  456. case "same_lv":
  457. ratio, ok = grade[level].PeerRateList[peerNum][coinId]
  458. default:
  459. ratio, ok = grade[level].SelfRateList[coinId]
  460. }
  461. if !ok {
  462. ratio = "0"
  463. }
  464. return
  465. }
  466. // GetLvUpSubsidyVirtualCoinRatio 获取各币种分销补贴比例
  467. func GetLvUpSubsidyVirtualCoinRatio(level, newLevel, diff int, grade map[int]*LvGrade, coinId string) (ratio string) {
  468. gradeCfg, ok := grade[level]
  469. if !ok || gradeCfg == nil {
  470. return "0"
  471. }
  472. levelSubsidyCfg := gradeCfg.UserLvUpSubsidyList
  473. if levelSubsidyCfg == nil {
  474. return "0"
  475. }
  476. // 找出对应等级的配置
  477. var levelRateListArr = make([]interface{}, 0)
  478. for oneKey, oneLevel := range levelSubsidyCfg {
  479. oneLevelMap, ok := oneLevel.(map[string]interface{})
  480. if !ok || oneLevelMap == nil {
  481. continue
  482. }
  483. if oneLevelMap["lv"] == "" && diff == 0 {
  484. continue
  485. }
  486. if oneLevelMap["lv"] == utils.AnyToString(newLevel) || (oneKey+1 == diff && diff > 0) {
  487. //可能不是这个类型
  488. jsons, ok := oneLevelMap["rate_list"].([]interface{})
  489. if ok {
  490. levelRateListArr = jsons
  491. }
  492. }
  493. }
  494. if len(levelRateListArr) == 0 {
  495. return "0"
  496. }
  497. // 各币种的补贴比例
  498. coinIdInt := utils.StrToInt(coinId)
  499. ratio = levelRateListArr[coinIdInt].(string)
  500. if utils.StrToFloat64(ratio) == 0 {
  501. return "0"
  502. }
  503. return ratio
  504. }
  505. // GetSubsidyVirtualCoinAmount 获取各币种补贴值
  506. // ratio 比例
  507. // typ 模式 bili money
  508. func GetSubsidyVirtualCoinAmount(ratio, moneyRate, typ string, fee, sysFee float64, subsidyMode int) (amount, subsidyRatio float64) {
  509. ratioF := utils.AnyToFloat64(ratio)
  510. if typ == "money" {
  511. amount = ratioF
  512. subsidyRatio = ratioF / fee
  513. } else {
  514. subsidyRatio = ratioF / 100
  515. if utils.StrToFloat64(moneyRate) > 0 {
  516. sysFee = sysFee * utils.StrToFloat64(moneyRate)
  517. }
  518. if utils.StrToFloat64(moneyRate) > 0 {
  519. fee = fee * utils.StrToFloat64(moneyRate)
  520. }
  521. if subsidyMode == 1 { // 按利润
  522. amount = sysFee * subsidyRatio
  523. } else { // 按佣金
  524. amount = fee * subsidyRatio
  525. }
  526. }
  527. return
  528. }
  529. // 计算佣金、虚拟币额度
  530. func getCoinAmount(ratio string, coinId int, fee float64, rateList map[int]string) (amount float64) {
  531. moneyRate, ok := rateList[coinId]
  532. if !ok {
  533. amount = 0.00
  534. return
  535. }
  536. if coinId == 0 { // 金额
  537. amount = fee * utils.StrToFloat64(ratio)
  538. } else { // 虚拟币 需要将金额按设置的比例兑换成虚拟币 这里不乘比例了 会影响后面的极差
  539. //amount = fee * utils.AnyToFloat64(moneyRate) * utils.StrToFloat64(ratio)
  540. amount = fee * utils.AnyToFloat64(moneyRate)
  541. }
  542. return
  543. }
  544. // 计算各币种数量扣除
  545. func CalVirtualCommissionMinus(a, b []*VirtualCoinCommission) (c []*VirtualCoinCommission, zeroList map[string]struct{}) {
  546. var amount float64
  547. zeroList = make(map[string]struct{})
  548. for _, coinA := range a {
  549. for _, coinB := range b {
  550. if coinA.Cid == coinB.Cid {
  551. amount = coinA.Val - coinB.Val
  552. if amount < 0 {
  553. zeroList[coinA.Cid] = struct{}{}
  554. amount = 0
  555. }
  556. c = append(c, &VirtualCoinCommission{
  557. Cid: coinA.Cid,
  558. Val: amount,
  559. })
  560. }
  561. }
  562. }
  563. return c, zeroList
  564. }
  565. func convertList2Map(a []*VirtualCoinCommission) (b map[string]float64) {
  566. b = make(map[string]float64)
  567. for _, i := range a {
  568. b[i.Cid] = i.Val
  569. }
  570. return b
  571. }
  572. func convertMap2List(a map[string]float64) (b []*VirtualCoinCommission) {
  573. for cid, val := range a {
  574. b = append(b, &VirtualCoinCommission{
  575. Cid: cid,
  576. Val: val,
  577. })
  578. }
  579. return b
  580. }