package diamond_tx import ( "fmt" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/internal/enum/diamond_e" "git.hilo.cn/hilo-common/internal/enum/msg_e" "git.hilo.cn/hilo-common/internal/model/diamond_m" "git.hilo.cn/hilo-common/myerr" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/txop/msg" "github.com/sirupsen/logrus" "gorm.io/gorm" ) // 下发钻石 func SendDiamond(model *domain.Model, userId mysql.ID, opt diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num, msgType ...msg_e.MsgUserRecordType) error { diamondAccount, err := diamond_m.GetDiamondAccountByUserId(model, userId) if err != nil { return err } diamondSendAccountDetail, err := diamondAccount.AddDiamondAccountDetail(opt, originId, diamondNum) if err != nil { return err } if err := diamondSendAccountDetail.Persistent(); err != nil { return err } if len(msgType) > 0 { // 小助手提示获得钻石 msg.SendLittleAssistantMsg(model, userId, msgType[0], fmt.Sprintf("%d", diamondNum), "", "", "", "") } return nil } // 下发钻石 func SendDiamondPink(model *domain.Model, userId mysql.ID, opt diamond_e.OperateType, originId mysql.ID, diamondNum mysql.Num, operateIds string, msgType ...msg_e.MsgUserRecordType) error { diamondAccount, err := diamond_m.GetDiamondAccountByUserId(model, userId) if err != nil { return err } diamondSendAccountDetail, err := diamondAccount.ChangePinkDiamondAccountDetail(opt, originId, diamondNum, operateIds) if err != nil { return err } if err := diamondSendAccountDetail.Persistent(); err != nil { return err } if len(msgType) > 0 { // 小助手提示获得钻石 msg.SendLittleAssistantMsg(model, userId, msgType[0], fmt.Sprintf("%d", diamondNum), "", "", "", "") } return nil } // 事务操作账号明细 // 注意:外层不能再加事务了 // 注意:DiamondOperateSet限流的不能用 // 账号冻结/账号余额:属于业务逻辑,不在事务做 // 函数步骤 // 1. 非事务前置判断: 获取账号信息,加减,封号等 // 事务 // 2. diamondAccount表原子操作, 判断更新条数 // 3. 更新明细表 // param extraTxFunc: 外部函数,可能会影响到事务回滚的函数 func TxAddReduceDiamondAccount(model *domain.Model, userId mysql.ID, operateType diamond_e.OperateType, diamondNum mysql.Num, originId mysql.ID, operateIds mysql.Str, extraTxFunc ...func() error) error { var diamondOperateSet diamond_m.DiamondOperateSet var err error if err = model.DB().Where(&diamond_m.DiamondOperateSet{ Type: operateType, Status: mysql.USER, DiamondType: diamond_e.DiamondYellow, }).First(&diamondOperateSet).Error; err != nil { return err } // logs model.Log = model.Log.WithFields(logrus.Fields{ "func": "TxAddReduceDiamondAccount", "uid": userId, "ot": operateType, "num": diamondNum, "oid": originId, "oids": operateIds, "ar": diamondOperateSet.AddReduce, }) var diamondAccount = new(diamond_m.DiamondAccount) if err := model.DB().Model(diamond_m.DiamondAccount{}).Where("user_id = ?", userId).First(diamondAccount).Error; err != nil { model.Log.Errorf("TxAddReduceDiamondAccount fail :%v", err) return err } if diamondOperateSet.AddReduce == mysql.REDUCE && diamondAccount.DiamondNum < diamondNum { return fmt.Errorf("bizerr.DiamondAccountNotEnough") } if diamondAccount.Status == diamond_e.Frozen && diamondOperateSet.AddReduce == mysql.REDUCE { return fmt.Errorf("bizerr.DiamondAccountFrozen") } return model.Transaction(func(model *domain.Model) error { // 更新diamondAccount表 var db *gorm.DB if diamondOperateSet.AddReduce == mysql.ADD { //增加 db = model.DB().Model(diamond_m.DiamondAccount{}).Where("id = ?", diamondAccount.ID).UpdateColumn("diamond_num", gorm.Expr("diamond_num + ?", diamondNum)) } else if diamondOperateSet.AddReduce == mysql.REDUCE { //减少,保证不能扣成负数 db = model.DB().Model(diamond_m.DiamondAccount{}).Where("id = ?", diamondAccount.ID).Where("diamond_num >= ?", diamondNum).UpdateColumn("diamond_num", gorm.Expr("diamond_num - ?", diamondNum)) } else { return myerr.NewSysErrorF("addReduce 枚举错误 value:", diamondOperateSet.AddReduce) } // 错误判断 if db == nil { model.Log.Errorf("db nil") return myerr.NewSysError("db nil") } if err := db.Error; err != nil { model.Log.Errorf("db err:%v", err) return myerr.WrapErr(err) } if db.RowsAffected == 0 { model.Log.Errorf("gorm condition update.RowsAffected = 0") return myerr.NewWaring("gorm condition update.RowsAffected = 0") } // 写后读(写后缓存都会丢失,多读一次不影响) //newAccount := new(diamond_m.DiamondAccount) //if err := model.DB().Model(diamond_m.DiamondAccount{}).Where("id = ?", diamondAccount.ID).First(newAccount).Error; err != nil { // model.Log.Errorf("newAccount err:%v", err) // return err //} //if newAccount.DiamondNum < 0 { // model.Log.Errorf("newAccount 0") // return myerr.NewSysError("newAccount 0") //} //// 更新明细 //befNum := mysql.Num(0) //if diamondOperateSet.AddReduce == mysql.ADD { // befNum = newAccount.DiamondNum - diamondNum //} //if diamondOperateSet.AddReduce == mysql.REDUCE { // befNum = newAccount.DiamondNum + diamondNum //} if err := model.DB().Table(diamond_m.DiamondAccountDetail{}.TableName()).Create(&diamond_m.DiamondAccountDetail{ UserId: userId, DiamondAccountId: diamondAccount.ID, OperateId: diamondOperateSet.ID, OperateType: operateType, OriginId: originId, AddReduce: diamondOperateSet.AddReduce, Num: diamondNum, Remark: diamondOperateSet.Name, BefNum: 0, AftNum: 0, }).Error; err != nil { model.Log.Errorf("add detail fail:%v", err) return err } for i, f := range extraTxFunc { if err := f(); err != nil { model.Log.Errorf("extraFunc i:%v fail:%v", i, err) return err } } return nil }) }