package diamond_m import ( "fmt" "git.hilo.cn/hilo-common/_const/enum/diamond_e" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/utils" "hilo-user/myerr" "hilo-user/myerr/bizerr" "strconv" "time" ) type DiamondAccount struct { mysql.Entity *domain.Model `gorm:"-"` UserId mysql.ID DiamondNum mysql.Num PinkDiamondNum mysql.Num Status diamond_e.StatusAccount } //账号详情 type DiamondAccountDetail struct { mysql.Entity *domain.Model `gorm:"-"` UserId mysql.ID DiamondAccountId mysql.ID OperateId mysql.ID OperateType diamond_e.OperateType OriginId mysql.ID AddReduce mysql.AddReduce Num mysql.Num Remark mysql.Str BefNum mysql.Num AftNum mysql.Num diamondAccount *DiamondAccount `gorm:"-"` } func (DiamondAccountDetail) TableName() string { month := time.Now().Format("200601") return fmt.Sprintf("diamond_account_detail_%s", month) } // 粉钻详情 type DiamondPinkAccountDetail struct { mysql.Entity *domain.Model `gorm:"-"` UserId mysql.ID DiamondAccountId mysql.ID OperateId mysql.ID OperateType diamond_e.OperateType OriginId mysql.ID AddReduce mysql.AddReduce Num mysql.Num Remark mysql.Str BefNum mysql.Num AftNum mysql.Num diamondAccount *DiamondAccount `gorm:"-"` } //账号操作配置 type DiamondOperateSet struct { mysql.Entity *domain.Model `gorm:"-"` DiamondNum mysql.NumAll FrequencyNum mysql.NumAll FrequencyDay mysql.NumAll DiamondMaxNum mysql.NumAll AddReduce mysql.AddReduce Type diamond_e.OperateType Name mysql.Str Status mysql.UserYesNo DiamondType diamond_e.OperateType } //通过userId获取帐号 func GetDiamondAccountByUserId(model *domain.Model, userId mysql.ID) (*DiamondAccount, error) { var diamondAccount DiamondAccount if err := model.Db.WithContext(model).Where(&DiamondAccount{ UserId: userId, }).First(&diamondAccount).Error; err != nil { return nil, myerr.WrapErr(err) } diamondAccount.Model = model return &diamondAccount, nil } //匹配条件扣费 func (diamondAccount *DiamondAccount) ChangeDiamondAccountDetail(operateType diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num) (*DiamondAccountDetail, error) { return diamondAccount.addDiamondAccountDetail(operateType, originId, diamondNum) } //钻石操作记录, func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num) (*DiamondAccountDetail, error) { var diamondOperateSet DiamondOperateSet var err error if err = diamondAccount.Db.Where(&DiamondOperateSet{ Type: operateType, Status: mysql.USER, DiamondType: mysql.DiamondYellow, }).First(&diamondOperateSet).Error; err != nil { return nil, myerr.WrapErr(err) } //判断是增加,账号是否被冻结 if diamondAccount.Status == diamond_e.Frozen && diamondOperateSet.AddReduce == mysql.REDUCE { return nil, bizerr.DiamondAccountFrozen } //无限,检查次数 var count int64 if diamondOperateSet.FrequencyDay == -1 { if diamondOperateSet.FrequencyNum != -1 { diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{ UserId: diamondAccount.UserId, OperateType: operateType, }).Count(&count) if count >= int64(diamondOperateSet.FrequencyNum) { return nil, bizerr.DiamondFrequency //return nil, myerr.NewSysError("钻石操作次数多大, userId:" + mysql.IdToStr(diamondAccount.UserId) + " diamondOperateSetId" + mysql.IdToStr(diamondOperateSet.ID)) } } } else if diamondOperateSet.FrequencyDay == 1 { beginTime, err := time.ParseInLocation("2006-01-02", time.Now().Format("2006-01-02"), time.Local) if err != nil { return nil, myerr.WrapErr(err) } //一天的次数 diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{ UserId: diamondAccount.UserId, OperateType: operateType, }).Where("created_time >= ? ", beginTime).Count(&count) if count >= int64(diamondOperateSet.FrequencyNum) { return nil, bizerr.DiamondFrequency } //终极拦截,利用 diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )") } //-1,代表值无效,由参数给与 var upateDiamondNum mysql.Num if diamondOperateSet.DiamondNum == -1 { upateDiamondNum = diamondNum } else { upateDiamondNum = mysql.Num(diamondOperateSet.DiamondNum) } var afterNum mysql.Num if diamondOperateSet.AddReduce == mysql.ADD { afterNum = diamondAccount.DiamondNum + upateDiamondNum } else if diamondOperateSet.AddReduce == mysql.REDUCE { if diamondAccount.DiamondNum < upateDiamondNum { return nil, bizerr.DiamondNoEnough } afterNum = diamondAccount.DiamondNum - upateDiamondNum } else { return nil, myerr.NewSysError("AddReduce 值错误:" + mysql.TypeToString(mysql.Type(diamondOperateSet.AddReduce))) } diamondAccountDetail := &DiamondAccountDetail{ Model: diamondAccount.Model, UserId: diamondAccount.UserId, DiamondAccountId: diamondAccount.ID, OperateId: diamondOperateSet.ID, OperateType: diamondOperateSet.Type, OriginId: originId, AddReduce: diamondOperateSet.AddReduce, Num: upateDiamondNum, Remark: diamondOperateSet.Name, BefNum: diamondAccount.DiamondNum, AftNum: afterNum, diamondAccount: diamondAccount, } return diamondAccountDetail, err } // 此方法必须要在事务里面调用 func ChangeDiamondAccountDetail(model *domain.Model, operateType diamond_e.OperateType, originId mysql.ID, userId mysql.ID, diamondNum mysql.Num) error { diamondAccount, err := GetDiamondAccountByUserId(model, userId) if err != nil { model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) return err } diamondAccountDetail, err := diamondAccount.ChangeDiamondAccountDetail(operateType, originId, diamondNum) if err != nil { model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) return err } if err := diamondAccountDetail.PersistentNoInTransactional(); err != nil { model.Log.Errorf("ChangeDiamondAccountDetail operateType:%v, originId:%v, userId:%v, diamondNum:%v, err:%v", operateType, originId, userId, diamondNum, err) return err } return nil }