package diamond_m import ( "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/utils" "gorm.io/gorm" "hilo-group/_const/enum/diamond_e" "hilo-group/domain/model" "hilo-group/myerr" "hilo-group/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:"-"` } // 粉钻详情 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:"-"` } //通过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 } //账号操作配置 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 } //匹配条件扣费 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: 1, // 1:黄钻 2:粉钻 }).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.Model(&DiamondAccountDetail{}).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.Model(&DiamondAccountDetail{}).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 diamond_account_detail 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 (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional() error { //fixme: 这里有点奇怪, diamondAccount持久化动作在diamondAccountDetail持久化之后,RowsAffected 就一定是0 txDiamondAccount := diamondAccountDetail.Db.Model(diamondAccountDetail.diamondAccount) if diamondAccountDetail.diamondAccount.CheckUpdateCondition() { txDiamondAccount = txDiamondAccount.Where(diamondAccountDetail.diamondAccount.GetUpdateCondition()) } if diamondAccountDetail.AddReduce == mysql.ADD { //增加 txDiamondAccount.UpdateColumn("diamond_num", gorm.Expr("diamond_num + ?", diamondAccountDetail.Num)) } else if diamondAccountDetail.AddReduce == mysql.REDUCE { //减少,保证不能扣成负数 txDiamondAccount.Where("diamond_num >= ?", diamondAccountDetail.Num).UpdateColumn("diamond_num", gorm.Expr("diamond_num - ?", diamondAccountDetail.Num)) } else { myerr.NewSysError("addReduce 枚举错误 value:" + mysql.TypeToString(mysql.Type(diamondAccountDetail.AddReduce))) } if err := txDiamondAccount.Error; err != nil { return myerr.WrapErr(err) } if txDiamondAccount.RowsAffected == 0 { diamondAccountDetail.Log.Errorf("gorm condition update.RowsAffected = 0,AddReduce:%v", diamondAccountDetail.AddReduce) return myerr.NewWaring("gorm condition update.RowsAffected = 0") } //持久化diamondAccountDetail if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { return myerr.WrapErr(err) } //改变diamondAccount值 if diamondAccountDetail.diamondAccount == nil { return myerr.NewSysError("持久化错误, 模型:DiamondAccountDetail 中没有diamondAccount, DiamondAccountDetail.Id =" + strconv.Itoa(int(diamondAccountDetail.ID))) } var newDiamondAccount DiamondAccount if err := diamondAccountDetail.Db.First(&newDiamondAccount, diamondAccountDetail.diamondAccount.ID).Error; err != nil { return myerr.WrapErr(err) } if newDiamondAccount.DiamondNum < 0 { return myerr.NewSysError("diamond_account表中,diamond_num 不能小于0, diamondAccount.id = " + strconv.Itoa(int(newDiamondAccount.ID))) } return nil } //群组支持 func (diamondAccount *DiamondAccount) GroupSupportAdmin(groupSupportAwardId mysql.ID, diamondNum uint32) (*DiamondAccountDetail, error) { return diamondAccount.addDiamondAccountDetail(diamond_e.GroupSupportAdmin, groupSupportAwardId, diamondNum) } func (diamondAccountDetail *DiamondAccountDetail) Persistent() error { //fixme: 这里有点奇怪, diamondAccount持久化动作在diamondAccountDetail持久化之后,RowsAffected 就一定是0 txDiamondAccount := diamondAccountDetail.Db.Model(diamondAccountDetail.diamondAccount) if diamondAccountDetail.diamondAccount.CheckUpdateCondition() { txDiamondAccount = txDiamondAccount.Where(diamondAccountDetail.diamondAccount.GetUpdateCondition()) } if diamondAccountDetail.AddReduce == mysql.ADD { //增加 txDiamondAccount.UpdateColumn("diamond_num", gorm.Expr("diamond_num + ?", diamondAccountDetail.Num)) } else if diamondAccountDetail.AddReduce == mysql.REDUCE { //减少,保证不能扣成负数 txDiamondAccount.Where("diamond_num >= ?", diamondAccountDetail.Num).UpdateColumn("diamond_num", gorm.Expr("diamond_num - ?", diamondAccountDetail.Num)) } else { myerr.NewSysError("addReduce 枚举错误 value:" + mysql.TypeToString(mysql.Type(diamondAccountDetail.AddReduce))) } if err := txDiamondAccount.Error; err != nil { return myerr.WrapErr(err) } if txDiamondAccount.RowsAffected == 0 { mylogrus.MyLog.Errorf("gorm condition update.RowsAffected = 0,AddReduce:%v", diamondAccountDetail.AddReduce) return myerr.NewWaring("gorm condition update.RowsAffected = 0") } //持久化diamondAccountDetail if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { return myerr.WrapErr(err) } //改变diamondAccount值 if diamondAccountDetail.diamondAccount == nil { return myerr.NewSysError("持久化错误, 模型:DiamondAccountDetail 中没有diamondAccount, DiamondAccountDetail.Id =" + strconv.Itoa(int(diamondAccountDetail.ID))) } var newDiamondAccount DiamondAccount if err := diamondAccountDetail.Db.First(&newDiamondAccount, diamondAccountDetail.diamondAccount.ID).Error; err != nil { return myerr.WrapErr(err) } if newDiamondAccount.DiamondNum < 0 { return myerr.NewSysError("diamond_account表中,diamond_num 不能小于0, diamondAccount.id = " + strconv.Itoa(int(newDiamondAccount.ID))) } return nil } //群组支持 func (diamondAccount *DiamondAccount) GroupSupportMgr(groupSupportAwardId mysql.ID, diamondNum uint32) (*DiamondAccountDetail, error) { return diamondAccount.addDiamondAccountDetail(diamond_e.GroupSupportMgr, groupSupportAwardId, diamondNum) } //群组IM群发 func (diamondAccount *DiamondAccount) GroupImMass() (*DiamondAccountDetail, error) { return diamondAccount.addDiamondAccountDetail(diamond_e.GroupIMMass, 0, 0) } //购买自定义群组主题 func (diamondAccount *DiamondAccount) BuyGroupCustomTheme(diamondAccountDetailId mysql.ID) (*DiamondAccountDetail, error) { return diamondAccount.addDiamondAccountDetail(diamond_e.GroupCustomTheme, diamondAccountDetailId, 0) }