-
Notifications
You must be signed in to change notification settings - Fork 15
/
freeze_user_asset_logic.go
98 lines (85 loc) · 2.93 KB
/
freeze_user_asset_logic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package logic
import (
"context"
"database/sql"
"github.com/dtm-labs/client/dtmgrpc"
"github.com/luxun9527/gex/app/account/rpc/internal/dao/model"
"github.com/luxun9527/gex/common/errs"
logger "github.com/luxun9527/zaplog"
"github.com/luxun9527/gex/common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/luxun9527/gex/app/account/rpc/internal/svc"
"github.com/luxun9527/gex/app/account/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type FreezeUserAssetLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewFreezeUserAssetLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FreezeUserAssetLogic {
return &FreezeUserAssetLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// 冻结用户资产。
func (l *FreezeUserAssetLogic) FreezeUserAsset(in *pb.FreezeUserAssetReq) (*pb.Empty, error) {
asset := l.svcCtx.Query.Asset
barrier, err := dtmgrpc.BarrierFromGrpc(l.ctx)
if err != nil {
logx.Errorw("FreezeUserAsset BarrierFromGrpc db failed", logger.ErrorField(err))
return nil, errs.CastToDtmError(errs.DtmErr)
}
underlyingDB := asset.WithContext(l.ctx).UnderlyingDB()
var ma model.Asset
querySql := underlyingDB.ToSQL(func(tx *gorm.DB) *gorm.DB {
db := tx.Select(asset.ID.ColumnName().String(), asset.AvailableQty.ColumnName().String(), asset.FrozenQty.ColumnName().String()).
Clauses(asset.UserID.Eq(in.Uid)).
Clauses(asset.CoinID.Eq(in.CoinId)).
Clauses(clause.Locking{Strength: "UPDATE"}).
Take(&ma)
return db
})
db, err := underlyingDB.DB()
if err != nil {
logx.Errorw("FreezeUserAsset get db failed", logger.ErrorField(err))
return nil, errs.CastToDtmError(errs.ExecSqlFailed)
}
logx.Infow("req", logx.Field("data", in))
if err := barrier.CallWithDB(db, func(tx *sql.Tx) error {
var userAsset model.Asset
row := tx.QueryRow(querySql)
if row.Err() != nil {
return row.Err()
}
if err := row.Scan(&userAsset.ID, &userAsset.AvailableQty, &userAsset.FrozenQty); err != nil {
logx.Errorw("scan data failed", logger.ErrorField(err))
return errs.CastToDtmError(errs.UserNotFound)
}
if userAsset.ID == 0 {
return errs.CastToDtmError(errs.UserNotFound)
}
availableQty := utils.NewFromStringMaxPrec(userAsset.AvailableQty)
qty := utils.NewFromStringMaxPrec(in.Qty)
if availableQty.LessThan(qty) {
return errs.CastToDtmError(errs.AmountInsufficient)
}
userAsset.FrozenQty = utils.NewFromStringMaxPrec(userAsset.FrozenQty).Add(qty).String()
userAsset.AvailableQty = availableQty.Sub(qty).String()
updateSql := underlyingDB.ToSQL(func(tx *gorm.DB) *gorm.DB {
return tx.Select(asset.AvailableQty.ColumnName().String(), asset.FrozenQty.ColumnName().String()).
Updates(&userAsset)
})
if _, err := tx.Exec(updateSql); err != nil {
return errs.CastToDtmError(errs.ExecSqlFailed)
}
return nil
}); err != nil {
logx.Errorw("callWithDB failed", logger.ErrorField(err))
return nil, err
}
return &pb.Empty{}, nil
}