package cp_m import ( "fmt" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/mysql" "gorm.io/gorm" "hilo-user/_const/enum/cp_e" "hilo-user/myerr" "time" ) // cp等级 type CpLevel struct { mysql.Entity CpId mysql.ID SmallUserId mysql.ID LargeUserId mysql.ID Points mysql.Num Level cp_e.CpLevel ExpireAt time.Time } // cp等级积分明细 type CpLevelDetail struct { mysql.Entity CpId mysql.ID SmallUserId mysql.ID LargeUserId mysql.ID AddReduce mysql.AddReduce Num mysql.Num BefNum mysql.Num AftNum mysql.Num Remark string } // 添加cp等级积分增减明细 func AddCpLevelDetail(model *domain.Model, detail CpLevelDetail) error { return model.DB().Create(&detail).Error } // 增加cp等级积分 // 送礼1钻石=1点数 // condition // 1.记录不存在,首充加points计算level增加90天有效期 // 2.记录存在 // 2.1 在有效期内,直接加points后判断新level,升级需要更新有效期 // 2.2 不有效期内,算首充,重置points后判断新level,升级需要更新有效期 func AddCpLevelPoints(model *domain.Model, userId mysql.ID, points mysql.Num) (err error) { start := time.Now() defer func() { model.Log.Infof("AddCpLevelPoints cost:%v,err:%v", time.Now().Sub(start), err) }() cpId := mysql.ID(1) // todo get from weijian small, large := mysql.ID(4552), mysql.ID(7642) // todo get from weijian var cpLevel CpLevel var cpLevelDetails []CpLevelDetail if err := model.DB().Model(CpLevel{}).Where("cp_id = ?", cpId).First(&cpLevel).Error; err != nil { if err != gorm.ErrRecordNotFound { return myerr.WrapErr(err) } // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.ADD, Num: points, BefNum: 0, AftNum: points, Remark: fmt.Sprintf("send %d gift diamonds", points), }) // 1.记录不存在,首充加points计算level增加90天有效期 var level cp_e.CpLevel for l := cp_e.CpLevelMax; l >= cp_e.CpLevel0; l-- { if cp_e.CpLevelPoints[l] <= points { level = l break } } if level > 0 { points = points - cp_e.CpLevelPoints[level] // 减去用于已用于升级的积分 // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.REDUCE, Num: cp_e.CpLevelPoints[level], BefNum: cp_e.CpLevelPoints[level] + points, AftNum: points, Remark: fmt.Sprintf("Become LEVEL%d", level), }) } cpLevel = CpLevel{ CpId: cpId, SmallUserId: small, LargeUserId: large, Points: points, Level: level, ExpireAt: time.Now().AddDate(0, 0, cp_e.EffectDays), } } else { // 2.记录存在 // 2.1 在有效期内,直接加points后判断新level,升级需要更新有效期 if cpLevel.ExpireAt.After(time.Now()) { cpLevel.Points += points // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.ADD, Num: points, BefNum: cpLevel.Points - points, AftNum: cpLevel.Points, Remark: fmt.Sprintf("send %d gift diamonds", points), }) oldLevel := cpLevel.Level levelPoint := cp_e.CpLevelPoints[oldLevel] // 已经用于升级的积分 for level := cp_e.CpLevelMax; level > oldLevel; level-- { if cp_e.CpLevelPoints[level] <= cpLevel.Points+levelPoint { cpLevel.Level = level break } } // 升级 if oldLevel != cpLevel.Level { // 减去已用于升级的积分 cpLevel.Points = cpLevel.Points - (cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel]) cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays) // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.REDUCE, Num: cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel], BefNum: cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level] - cp_e.CpLevelPoints[oldLevel], AftNum: cpLevel.Points, Remark: fmt.Sprintf("Become LEVEL%d", cpLevel.Level), }) } } else { // 2.2 不有效期内,算首充,重置points后判断新level,更新有效期30天 oldPoints := cpLevel.Points cpLevel.Points = points // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.ADD, Num: points, BefNum: oldPoints, AftNum: cpLevel.Points, Remark: fmt.Sprintf("send %d gift diamonds", points), }) for level := cp_e.CpLevelMax; level >= cp_e.CpLevel0; level-- { if cp_e.CpLevelPoints[level] <= cpLevel.Points { cpLevel.Level = level break } } if cpLevel.Level > 0 { cpLevel.Points -= cp_e.CpLevelPoints[cpLevel.Level] // 减去已用于升级的积分 // 明细 cpLevelDetails = append(cpLevelDetails, CpLevelDetail{ CpId: cpId, SmallUserId: small, LargeUserId: large, AddReduce: mysql.REDUCE, Num: cp_e.CpLevelPoints[cpLevel.Level], BefNum: cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level], AftNum: cpLevel.Points, Remark: fmt.Sprintf("Become SVIP%d", cpLevel.Level), }) } cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays) } } // 顺序增加明细 for _, detail := range cpLevelDetails { if err := AddCpLevelDetail(model, detail); err != nil { return myerr.WrapErr(err) } } return cpLevel.Persistence(model) } // 清理过期svip积分 // 降级保级: 积分清零,svip去到大于0的等级,有效期90天 // svip0:积分清零,有效期保持过期 func ClearExpireUserSvipPoints(model *domain.Model) error { var cpLevels []*CpLevel // 过期 + (积分 or level) 大于0 if err := model.DB().Model(CpLevel{}).Where("expire_at < ? AND (points > 0 or level > 0) ", time.Now()).Find(&cpLevels).Error; err != nil { return myerr.WrapErr(err) } for _, cpLevel := range cpLevels { var doubleCheck CpLevel if err := model.DB().Model(CpLevel{}).Where("id = ?", cpLevel.ID).First(&doubleCheck).Error; err != nil { model.Log.Errorf("double check fail:%v", err) continue } if doubleCheck.ExpireAt.After(time.Now()) { continue } oldPoints := cpLevel.Points cpLevel.Level, cpLevel.Points = cp_e.CpLevel0, 0 // 清零 var newLevel cp_e.CpLevel // 0级不刷新30天有效期 for level := cp_e.CpLevelMax; level > cp_e.CpLevel0; level-- { if cp_e.CpLevelPoints[level] <= oldPoints { newLevel = level break } } // 降级/保级刷新30天有效期 if newLevel > 0 { cpLevel.Level = newLevel cpLevel.ExpireAt = time.Now().AddDate(0, 0, cp_e.EffectDays) // 明细 if err := AddCpLevelDetail(model, CpLevelDetail{ CpId: cpLevel.CpId, SmallUserId: cpLevel.SmallUserId, LargeUserId: cpLevel.LargeUserId, AddReduce: mysql.REDUCE, Num: cp_e.CpLevelPoints[newLevel], BefNum: oldPoints, AftNum: 0, Remark: fmt.Sprintf("Become LEVEL%d", newLevel), }); err != nil { model.Log.Errorf("AddCpLevelDetail fail:%v", err) } } if err := cpLevel.Persistence(model); err != nil { model.Log.Errorf("cpLevel persistence fail:%v", err) } // 明细 if err := AddCpLevelDetail(model, CpLevelDetail{ CpId: cpLevel.CpId, SmallUserId: cpLevel.SmallUserId, LargeUserId: cpLevel.LargeUserId, AddReduce: mysql.SET, Num: oldPoints - cp_e.CpLevelPoints[newLevel], BefNum: oldPoints - cp_e.CpLevelPoints[newLevel], AftNum: 0, Remark: fmt.Sprintf("Expired clear"), }); err != nil { model.Log.Errorf("AddCpLevelDetail fail:%v", err) } } return nil }